В моей базе данных 3 объекта, назовем их A
, B
и C
.
A
и B
разделяют отношения друг с другом. A
имеет SortedSet
из B
с, но B
не ссылается на A
(коллекция не настроена или не настроена). Итак, у нас есть следующее.
// Inside class A
@ManyToMany
@JoinTable(name = "a_b",
joinColumns = {@JoinColumn(name = "a_id")},
inverseJoinColumns = {@JoinColumn(name = "b_id")})
@LazyCollection(LazyCollectionOption.FALSE)
@SortNatural
private SortedSet<B> bSet = new TreeSet<B>();
B
и C
имеют отношения «один ко многим» друг с другом (от 1 B
до многих C
с). C
имеет B
в своей сущности, но B
не имеет ссылки на множество C
сущностей. Итак, у нас есть следующий
// Inside class C
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "b_id", nullable = false, updatable = true)
protected B b;
У нас есть процесс syn c, который запускает ночное задание для обновления A
сущностей и их ассоциаций до B
сущностей (что не очень часто меняется ). В итоге получается нечто похожее на следующее (действительно, с DAO, сервисами и т. Д. Все намного сложнее).
// Get the A value to be updated
A aToUpdate = entityManager.find(A.class, idForA);
// Out of scope of the question, but we need to figure out B via a string field on C
C cValue = myDao.getByProperty("fieldName", fieldValue);
// Determine the B values to set on aToUpdate
B bToSetOnA = cValue.getB();
TreeSet<B> bSet = new TreeSet<>();
bSet.add(bToSetOnA);
// Update aToUpdate
aToUpdate.setBSet(bSet);
aToUpdate = entityManager.merge(aToUpdate);
entityManager.flush();
Когда это происходит, возникает следующая ошибка.
ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (Sync Thread)
Duplicate entry 'myAId-almostMyBId' for key 'uk_a_b'
Одна интересная вещь заключается в том, что almostMyBId
на 1 символ меньше реального B
ID. Но в таблице a_b отображается только полный идентификатор.
Когда я просматриваю базу кода, на индекс в таблице a_b накладывается ограничение uk_a_b
. Это из ликвидазы.
<createIndex indexName="uk_a_b" tableName="a_b" unique="true">
<column name="a_id"/>
<column name="b_id"/>
</createIndex>
Если удалить строку aToUpdate.setBSet(bSet);
, ошибка исчезнет.
Я добавил логирование и подтвердил, что идентификаторы новых bSet
такие же, как и у старых aToUpdate
.
Каким-то образом Hibernate, похоже, пытается заново добавить ассоциацию, даже если мы проводим слияние, и ассоциации действительно не изменились.
Я пытался изменить некоторые вещи CascadeType и FetchType тут и там, но, похоже, ошибка не исчезла go. Кто-нибудь имеет представление о том, что происходит?