Я пишу в API игрового движка, поэтому у меня нет прямого доступа к классам, и я не могу добавлять аннотации гибернации (@Entity, @Table и т. д.), но я должен сохранить этот класс из API в своем объекте (таблице). Как я могу это сделать? Расширяет объект API и создает новый с аннотациями спящего режима или анализирует этот объект в строку? Любые идеи?
Класс, например, что я имею в виду:
@Entity
@Table(name = "users")
public class User {
@Id
@Column(name = "id")
private int id;
@Column(name = "location")
private Location locationOfPlayer; // - this is the class from API
}
Возможный дубликат Сохранение сторонних объектов с помощью JPA




Единственный реалистичный/хороший способ сделать это — Instrumentation.
Возможно, вы захотите создать и применить Java Agent, который преобразует нужные классы во время загрузки, добавляя аннотации JPA. Это в основном модификация байт-кода.
См., например, ClassFileTransformer.
это очень интересно, не знал, что это существует. на практике это лучшее решение, чем создание класса-оболочки для желаемого объекта. я бы подумал, что это не очень обновляемо, так как это очень зависит от версии.
@ Шон, хорошо, это решение, основанное на мнении. Лично мне не нравится загрязнять мои пакеты классами-обертками. И только подумайте об этом, каждый раз, когда вам нужно взаимодействие между классом API (простым классом) и вашим сервисом/репозиторием, вам нужно его обернуть. Может быть, вы можете централизовать это, а может быть, и нет. Честно говоря, способ ClassFileTransformer мне гораздо больше нравится. Я могу поддерживать его как отдельный модуль/проект. Что вы имеете в виду под зависимостью от версии?
@Shawn Я бы также добавил, что, говоря об оптимизации производительности и памяти, этот подход нельзя превзойти.
спасибо, это имеет смысл. мне нужно будет попробовать это в одном из моих проектов и лучше познакомиться с этим API.
@Шон, попробуй. Это очень мощный механизм. С ним можно делать красивые вещи. Просто найдите «ткачество времени загрузки - аспектно-ориентированное программирование»
Хотя это может быть решение а, оно явно не единственный реалистичный/хороший способ сделать это. Смотрите ответ @Tobias Liefke
По сути, вам придется дублировать данные в ваших классах сущностей: т. е. создавать сущности с похожими полями и сохранять их, а не использовать классы API. Недостатком этого является то, что вам придется вручную обновлять модель данных, но преимуществом является то, что изменения в API не нарушат код вашей базы данных напрямую.
Как только вы закончите дублировать данные, вы можете использовать фреймворк сопоставления (мне больше нравится Mapstruct, потому что он выполняет сопоставление во время компиляции, но библиотеки времени выполнения, такие как Orika, также довольно популярны для этой задачи).
Для этого вы можете использовать файл сопоставления, который вам нужно определить в файле persistence.xml:
<persistence version = "2.0" ...>
<persistence-unit name = "database">
<mapping-file>mapping.xml</mapping-file>
...
</persistence-unit>
</persistence>
В вашем файле сопоставления вы можете определить сопоставления ORM даже для сторонних классов:
<entity-mappings version = "1.0" xmlns = "http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">
<package>thirdparty</package>
<entity class = "Location" name = "Location">
...
</entity>
</entity-mappings>
Правильный ответ ИМО. Если сама спецификация JPA позволяет обрабатывать такие случаи, то зачем вводить что-то еще. Дополнительная информация содержится в главе 12 Дескриптор объектно-реляционного сопоставления спецификации JPA 2.1.
Вам нужно сопоставление для этого класса. Другим решением было бы сериализовать и сохранить в этой форме.