Hibernate: обход сгенерированного идентификатора в некоторых случаях
У меня есть две сущности Родитель и Ребенок. Родитель может иметь только одного ребенка, поэтому он содержит внешний ключ ребенка.
Все ID генерируются пользовательской реализацией IdentifierGenerator. Для какой-то сущности я хочу установить идентификатор вручную. Так что я нашел способ в моем пользовательском IdentifierGenerator получить значение поля id.
Проблема в том, что генератор никогда не вызывается, когда идентификатор дочернего элемента был предварительно определен, а дочерний элемент еще не сохранен.
Файл parent-hbm.xml:
<hibernate-mapping default-cascade="all">
<class name="com.ParentImpl" table="Parent" dynamic-insert="false" dynamic-update="false">
<cache usage="read-write" />
<id name="id" type="java.lang.Long" unsaved-value="null">
<column name="ID" sql-type="BIGINT"/>
<generator class="com.EntityIdGenerator">
</generator>
</id>
<many-to-one name="child" class="com.ChildImpl" foreign-key="CHILDSC" cascade="all" lazy="false" fetch="select">
<column name="CHILD_FK" not-null="true" sql-type="BIGINT" unique="true"/>
</many-to-one>
</class>
</hibernate-mapping>
файл child-hbm.xml:
<id name="id" type="java.lang.Long" unsaved-value="null">
<column name="ID" sql-type="BIGINT"/>
<generator class="com.EntityIdGenerator">
</generator>
</id>
Как я могу изменить это поведение?
Любая идея?
Заранее спасибо.
2 ответа
Вместо использования генератора, пытались ли вы настроить его для ручных идентификаторов, а затем использовать перехватчик или прослушиватель событий, который генерирует значение для случаев, когда он не назначен вручную?
Сара
Вы можете использовать аннотацию @PrePersist для создания идентификатора, если у него его еще нет. Я был удивлен вашим комментарием, что это не может быть сделано с перехватчиками или слушателями событий, поэтому я решил попробовать это.
Вот пример того, как это сделать. У меня есть класс "Test", который имеет назначенный вручную идентификатор, а затем я реализовал метод @PrePersist, чтобы присвоить идентификатор значению hashCode(), если у него еще нет идентификатора. Вы можете заменить любую схему генерации вместо вызова hashCode().
@Entity
@Table (name="Test")
public class Test{
@Id
@Column(name="id")
private String id;
@Column(name="PROPERTY")
private String property;
public Test() {
}
... // Other constructors, getters and setters
@PrePersist
void generateId() {
if (id == null) {
id = Integer.toHexString(hashCode());
}
}
Я протестировал как назначенные, так и неназначенные идентификаторы, создав новые сущности и обновив существующие, и не столкнулся с какими-либо проблемами.
Пример создания нового объекта:
Test assigned = new Test("assigned", "p1");
Test generate = new Test();
generate.setProperty("p2");
manager.persist(assigned);
manager.persist(generate);
manager.getTransaction().commit();
Пример обновления существующего объекта:
Test update = manager.find(Test.class, "assigned");
actionUpdate.setProperty("imageUpdated");
Test update2 = manager.find(Test.class, "some-generated-id");
update2.setProperty("videoUpdated");
manager.getTransaction().commit();
Надеюсь это поможет.
Сара