HibernateException: общие ссылки, вызываемые самим jpa (?) - PullRequest
0 голосов
/ 05 апреля 2019

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

Допустим, есть класс A :

@Entity(name = "a")
@Table(schema = "foo")
public class A {
    private static final long serialVersionUID = -5305374150112492804L;
    logger = LoggerFactory.getLogger(A.class);

    @Id
    @Column(name = "tid", nullable = false, unique = true)
    @SequenceGenerator(name = "globalSequenceGen", schema = "foo", sequenceName = "foo_sequence")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "globalSequenceGen")
    private Integer TID;

    @Column(name = "b")
    private String bId;

    @OneToMany(targetEntity = B.class)
    @JoinColumn(name = "random_b_attribute", referencedColumnName = "b", updatable = false, insertable = false)
    private List<B> b;

    @PrePersist
    @PreUpdate
    public void prePersist() {
        bId = b == null || b.isEmpty() ? null : b.get(0).getRandomAttribute();
    }
    ...
}

Ссылочный класс B довольно прост: он содержит только @Column аннотированных атрибутов. Обратите внимание, что экземпляры A могут и будут ссылаться на один и тот же «набор» B s в своем атрибуте b.

Существует третий класс D , ссылающийся на A :

@Entity(name = "d")
@Table(schema = "foo")
public class D {
    private static final long serialVersionUID = -5305374150112492804L;
    logger = LoggerFactory.getLogger(D.class);

    @Id
    @Column(name = "tid", nullable = false, unique = true)
    @SequenceGenerator(name = "globalSequenceGen", schema = "foo", sequenceName = "foo_sequence")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "globalSequenceGen")
    private Integer TID;

    @Column(name = "a")
    private Integer aId;

    @ManyToOne(targetEntity = A.class)
    @JoinColumn(name = "a", referencedColumnName = "tid", updatable = false, insertable = false)
    private A a;

    @PrePersist
    @PreUpdate
    public void prePersist() {
        aId = a == null ? null : a.getTID();
    }
    ...
}

Подходя к проблеме:

  1. Я получаю объекты D из базы данных (ленивый). Ни один из них не ссылается ни на какие объекты A (например, столбец a в базе данных пуст).
  2. Я извлекаю все объекты A из базы данных с теми же EntityManager, как я позже хотел бы вставить их в D экземпляров (также ленивых).
  3. Я делаю НЕ касаюсь любого атрибута D#a или A#b.
  4. Попытка EntityManager#persist любого вновь созданного экземпляра D приводит к получению следующего исключения:
Caused by: org.hibernate.HibernateException: Found shared references to a collection: random.package.structure.A.b

Во время моего исследования я обнаружил, что ошибка может быть вызвана предоставлением того же Collection (не путать с Collection, имеющим те же записи). Очевидно, это связано с инициализацией A экземпляров самой jpa ?! Кажется, будет хорошей идеей перерабатывать тот же Collection, но, очевидно, вызывает проблемы при обновлении неизмененных объектов ...

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

Есть ли у вас какие-либо советы о том, как создавать новые Collection s для каждого экземпляра A или предотвращать сбой другими способами?

Заранее большое спасибо, если я пропустил какую-либо информацию, просто спросите!

1 Ответ

0 голосов
/ 15 апреля 2019

Большое спасибо за ваши ответы! Намек @crizzis сделал свое дело.

Конечно, это @ManyToMany отношение. Я изменил свою модель данных (чтобы использовать таблицы сопоставления), и это решило мою проблему!

...