是否可以删除应用于子类中@MappedSuperclass中的@Id列的@GeneratedValue字段注释?

时间:2016-04-08 19:09:48

标签: hibernate jpa spring-data-jpa hsqldb

我有一个标记为@MappedSuperclass的抽象基类,其id属性设置为@Id @GeneratedValue

我还有一个@Entity从中派生出来,需要设置自己的ID而不是依赖于生成。

我有大量的衍生实体依赖于@MappedSuperclass中设置的ID,我不想在每个实体中设置ID。

如何才能避免这个派生实体的@GeneratedValue?我希望手动设置ID以覆盖生成,但事实并非如此。

id列的DDL(HSQL):

id bigint generated by default as identity (start with 1)

根据http://hsqldb.org/doc/guide/ch02.html#N104B3 ID生成只应在为id列指定空值时生成。

以下是一些示例代码:

@MappedSuperclass
class Parent {
    @Id @GeneratedValue
    private Long id;
}

@Entity
class Child extends Parent
    @PrePersist
    public void prePersist() {
        LOG.info("PrePersist with id #{}", this.id);
    }
}

Child t = new Child();
t.setId(123);

LOG.debug("Creating: Child #{}", t.getId());
childRepository.save(t); // Spring Data JPA Repositories
LOG.debug("Created: Child #{}", t.getId());

// Outputs:
// Creating: Child #123
// PrePersist with id #123 
// Created: Child #1

修改

事实证明,默认的@GeneratedValue策略不允许指定ID。数据库将始终生成它们。事实证明我需要编写自定义ID生成器......

public class CustomIdGenerator extends SequenceStyleGenerator {

    @Override
    public Serializable generate(SessionImplementor session, Object object)
        throws HibernateException {
        Serializable id = session.getEntityPersister(null, object)
            .getClassMetadata().getIdentifier(object, session);
        return id != null ? id : super.generate(session, object);
    }

}

...然后按如下方式注释父ID的ID字段......

@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "CustomIdGenerator")
@GenericGenerator(name = "CustomIdGenerator", strategy = "com.foo.CustomIdGenerator")
private Long id;

这会导致序列表或本机序列用于ID生成,但是会延迟到实体上设置的ID。

1 个答案:

答案 0 :(得分:1)

编辑:工作回答:好的,现在我看到没有办法以纯JPA方式执行此操作,但如果您正在使用Hibernate,您可能会尝试编写自定义SequenceGenerator,因为它是{{ 3}}。基本上,只有在未设置id时,它才会生成一个值(调用super.generate())。