首页 > 解决方案 > Hibernate Generated fields null 直到刷新

问题描述

我正在尝试使用数据库触发器生成的多个字段来保存实体。

public class MyEntity {
    @Id
    @GeneratedValue
    protected UUID id;

    //generated by DB trigger   
    @Generated(value = GenerationTime.ALWAYS)
    @Column(name = "generated_number", insertable = false, updatable = false)
    private String generatedNumber;

    //generated by DB trigger
    @Generated(value = GenerationTime.INSERT)
    @Column(name = "postfix", insertable = false, updatable = false)
    private Integer postfix;

   //other normal fields
}

@Repository
public interface MyRepository extends PagingAndSortingRepository<MyEntity, UUID>, JpaRepository<MyEntity, UUID>

文档指出生成的注释将字段标记为由 DB 填充。Hibernate 应该从 DB 加载生成的数据。

生成的属性是其值由数据库生成的属性。通常,Hibernate 应用程序需要刷新包含数据库为其生成值的任何属性的对象。但是,将属性标记为已生成,可以让应用程序将此责任委托给 Hibernate。当 Hibernate 为已定义生成属性的实体发出 SQL INSERT 或 UPDATE 时,它会立即发出 select 以检索生成的值。

标记为已生成的属性还必须是不可插入和不可更新的。只有@Version 和@Basic 类型可以标记为已生成。

但是,在刷新之前不会加载生成的字段的内容。

@Transactional
public MyEntity save(MyEntity entity) {
    //save without flush
    //assertions fail
    //MyEntity updated = repository.save(entity);
    //works fine
    MyEntity updated = repository.saveAndFlush(entity);
    assert updated.getGeneratedNumber() != null;
    assert updated.getPostfix() != null;
}

我生成的字段被标记为不可插入和不可更新。它们是基本的字符串类型。我还尝试@Basic在它们上方添加注释,但这没有帮助。

我错过了什么?

标签: javahibernatespring-data-jpahibernate-mapping

解决方案


通常由于缓存的原因,实际上是在事务完成时执行对数据库的调用。您正在使用@Transactional属性,因此调用是在方法的末尾完全由 执行的flush(),更具体地说是在内部执行的commit()。这就是为什么您看不到代码的更改并且没有生成值的原因 - 之前没有完成对 db 的调用flush()


推荐阅读