Как создать объект гибернации из внешнего класса API?

Я пишу в 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

}

Вам нужно сопоставление для этого класса. Другим решением было бы сериализовать и сохранить в этой форме.

Andronicus 21.02.2019 19:03

Возможный дубликат Сохранение сторонних объектов с помощью JPA

Tobias Liefke 22.02.2019 14:08
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
701
3

Ответы 3

Единственный реалистичный/хороший способ сделать это — Instrumentation.
Возможно, вы захотите создать и применить Java Agent, который преобразует нужные классы во время загрузки, добавляя аннотации JPA. Это в основном модификация байт-кода.

См., например, ClassFileTransformer.

это очень интересно, не знал, что это существует. на практике это лучшее решение, чем создание класса-оболочки для желаемого объекта. я бы подумал, что это не очень обновляемо, так как это очень зависит от версии.

Shawn 21.02.2019 19:57

@ Шон, хорошо, это решение, основанное на мнении. Лично мне не нравится загрязнять мои пакеты классами-обертками. И только подумайте об этом, каждый раз, когда вам нужно взаимодействие между классом API (простым классом) и вашим сервисом/репозиторием, вам нужно его обернуть. Может быть, вы можете централизовать это, а может быть, и нет. Честно говоря, способ ClassFileTransformer мне гораздо больше нравится. Я могу поддерживать его как отдельный модуль/проект. Что вы имеете в виду под зависимостью от версии?

LppEdd 21.02.2019 20:09

@Shawn Я бы также добавил, что, говоря об оптимизации производительности и памяти, этот подход нельзя превзойти.

LppEdd 21.02.2019 20:13

спасибо, это имеет смысл. мне нужно будет попробовать это в одном из моих проектов и лучше познакомиться с этим API.

Shawn 21.02.2019 20:14

@Шон, попробуй. Это очень мощный механизм. С ним можно делать красивые вещи. Просто найдите «ткачество времени загрузки - аспектно-ориентированное программирование»

LppEdd 21.02.2019 20:16

Хотя это может быть решение а, оно явно не единственный реалистичный/хороший способ сделать это. Смотрите ответ @Tobias Liefke

Alan Hay 22.02.2019 14:34

По сути, вам придется дублировать данные в ваших классах сущностей: т. е. создавать сущности с похожими полями и сохранять их, а не использовать классы 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.

Alan Hay 22.02.2019 14:31

Другие вопросы по теме