Соединение Spring / JPA по ключу пространства имен - PullRequest
0 голосов
/ 28 июня 2018

Я создаю приложение Spring 4 / Spring Data для существующей базы данных. Структура базы данных и данные определяются программным обеспечением с закрытым исходным кодом.

Одним из аспектов существующей системы является то, что вы можете создать комментарий к любому другому элементу в системе. Это означает, что статья, документ, мультимедийный файл (все объекты в системе) могут иметь любое количество комментариев, и каждый комментарий относится только к одному объекту в системе. Все комментарии в таблице * comment.

Способ, которым это реализовано, состоит в том, что таблица comment имеет столбец comment_for, в котором содержится сцепленная / именованная / префиксная ссылка на фактическую сущность, для которой это комментарий. Похоже, что текущая система просто строит запрос соединения, добавляя к первичному ключу имя таблицы:

+----+-------------------+----------------+
| id | comment_for       | comment        |
+----+-------------------+----------------+
|   1| article:12345     | This is nice...|
|   2| document:42       | Cool doc!      |
+----+-------------------+----------------+

В этом примере показаны два комментария: один для статьи с article.id из 12345 и один для документа с document.id из 42. Я создал @Entities, сопоставляя таблицы базы данных и соответствующие интерфейсы репозитория с методами запросов Я нуждаюсь.

Я хотел бы использовать репозитории / сущности данных Spring, чтобы заполнить коллекции моих сущностей соответствующими комментариями, например (псевдокод) для статьи сущностей.

@OneToMany(mappedBy = "comment_for", prefix = "article:")
private List<Comment> comment = new ArrayList<>();

Мне нужно только однонаправленное. Мои сущности (на данный момент Article, Document и Mediafile) должны хранить коллекцию своих комментариев. Мне не нужны комментарии, чтобы удерживать ссылку на сущность.

Есть ли способ сделать это? Результирующий запрос SQL должен выглядеть примерно так:

SELECT * FROM .... WHERE comment.comment_for = concat('<entityname>:', <entity>.id); 

Я посмотрел на @JoinColumn, но не могу изменить используемое значение для объединения, только имя столбца. Единственное решение, которое у меня есть на данный момент, это ручное @Query s в интерфейсе CommentRepository, которое дает мне ArrayList всех комментариев для определенной комбинации Entity / ID. Но я хотел бы, чтобы комментарии автоматически включались как часть моей организации.

Обновление : похоже, я могу разделить пространство имен и идентификатор из comment_for на два новых столбца, не прерывая существующее программное обеспечение. Два столбца теперь comment_for_id и comment_for_entityname

1 Ответ

0 голосов
/ 28 июня 2018

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

Также вы можете использовать @JoinColumn на стороне владельца отношений между сущностью и комментариями. Похоже, что в вашем случае это будет сущность / таблица Comment, поскольку для каждой сущности существует много комментариев.

Пример:

@Entity
@NamedQueries({ @NamedQuery(name = "Comments.findAll", query = "select o from Comments o") })
@IdClass(CommentsPK.class)
public class Comments implements Serializable {
    private static final long serialVersionUID = 4787438687752132432L;
    @Id
    @Column(name = "COMMENT_TEXT", nullable = false, length = 30)
    private String commentText;
    @Id
    @Column(name = "ENTITY_TYPE", nullable = false, length = 30)
    private String entityType;
    @ManyToOne
    @Id
    @JoinColumn(name = "COMMENT_FOR")
    private EntityDemo entityDemo;

Обратите внимание, что я установил комбинацию всех трех полей в качестве первичного ключа, я не уверен, какие критерии используются в качестве PK в текущей настройке.

Вот пример сущности. Атрибуты были составлены с целью демонстрации.

@Entity
@NamedQueries({ @NamedQuery(name = "EntityDemo.findAll", query = "select o from EntityDemo o") })
@Table(name = "ENTITY_DEMO")
public class EntityDemo implements Serializable {
    private static final long serialVersionUID = -8709368847389356776L;
    @Column(length = 1)
    private String data;
    @Id
    @Column(nullable = false)
    private BigDecimal id;
    @OneToMany(mappedBy = "entityDemo", cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    private List<Comments> commentsList;
...