Попытка достичь низкой связи между объектами JPA - PullRequest
0 голосов
/ 14 ноября 2018

Одна проблема, с которой я сталкиваюсь, - это хороший способ сопоставить отношения «один ко многим» с JPA / Hibernate, не жертвуя при этом принципами SOLID. Вот пример этой проблемы из текущего проекта, над которым я работаю:

Учитывая следующий код, который определяет однонаправленное отношение «один ко многим»:

@Entity
@Table(name = "users")
public class User extends AggregateEntity<User> implements HasRoles, HasContactInfo, HasContacts, HasDeals {

    @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
    @JoinColumn(name = "fk_hasContacts")
    private Set<Contact> contacts;}

Насколько я понимаю, это создает столбец "fk_hasContacts" в таблице "контакты", при этом класс "Контакт" не знает и не заботится о том, на какой объект он ссылается. Также обратите внимание на то, как «Пользователь» реализует интерфейс «hasContacts», который создает эффект разделения между двумя объектами. Если завтра я хочу добавить еще один класс; скажем, «BusinessEntity», который также имеет контакты, нет ничего, что нужно изменить в текущем коде. Однако после прочтения этой темы кажется, что этот подход неэффективен с точки зрения производительности базы данных.

Лучший способ отобразить связь @OneToMany - это полагаться на сторону @ManyToOne для распространения всех изменений состояния сущности - Как изложено здесь .

Кажется, преобладающая мудрость. Если бы я разработал его таким образом, класс «Пользователь» теперь выглядел бы так:

@Entity
@Table(name = "users")
public class User extends AggregateEntity<User> implements HasRoles, HasContactInfo, HasContacts, HasDeals {

    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
    private Set<Contact> contacts;

И (ранее отсоединенный) класс «Контакт» теперь должен выглядеть следующим образом:

@Entity
@Table(name = "contacts")
public class Contact extends StandardEntity<Contact> {

    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "fk_user")
    private User user;

Ключевая проблема в том, что из здесь кажется, что JPA не поддерживает определение интерфейса в качестве атрибута сущности. Итак, этот код:

@Entity
@Table(name = "contacts")
public class Contact extends StandardEntity<Contact> {

    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "fk_user")
    private HasContacts hasContacts;//some class which implements the "HasUser" interface

Не вариант. Кажется, нужно было бы выбирать между SOLID OOP и действительными объектами ORM. После долгих чтений я до сих пор не знаю, достаточно ли плох для производительности базы данных, чтобы оправдать написание того, что представляет собой тесно связанный, жесткий и в конечном итоге плохой код.

Есть ли обходные пути / решения этого кажущегося противоречия в принципах проектирования?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...