Hibernate:在某些情况下绕过生成的ID

时间:2013-09-05 07:47:46

标签: hibernate hibernate-mapping

我有两个实体Parent和Child。父母只能有一个孩子,因此它包含孩子的外键。

所有ID都由IdentifierGenerator的自定义实现生成。对于某些实体,我想手动设置ID。所以我在自定义IdentifierGenerator中找到了一种方法来获取id字段的值。

问题是,当孩子的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 个答案:

答案 0 :(得分:0)

您是否尝试将其配置为手动ID,然后使用拦截器或事件侦听器,而不是使用生成器,而是在未手动分配的情况下为这些情况生成值?

萨拉

答案 1 :(得分:0)

如果ID尚未拥有,您可以使用@PrePersist注释生成ID。我对你的评论感到惊讶,因为它无法通过拦截器或事件监听器完成,所以我决定尝试一下。

以下是如何操作的示例。我有一个类“Test”,它有一个手动分配的id,然后我实现了一个@PrePersist方法,如果它还没有ID,则将ID分配给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());
        }
    }

我测试了已分配和未分配的ID,同时创建了新实体并更新了现有实体,并没有遇到任何问题。

创建新实体的示例:

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();

希望这有帮助。

萨拉