java - 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
在它们上方添加注释,但这没有帮助。
我错过了什么?
解决方案
通常由于缓存的原因,实际上是在事务完成时执行对数据库的调用。您正在使用@Transactional
属性,因此调用是在方法的末尾完全由 执行的flush()
,更具体地说是在内部执行的commit()
。这就是为什么您看不到代码的更改并且没有生成值的原因 - 之前没有完成对 db 的调用flush()
。