在带有
spring-boot-starter-data-jpa
的 spring-boot 3 应用程序中,我有一个实体:
@Entity
public class SomeJson {
public static final ObjectMapper MAPPER = new ObjectMapper();
public static final TypeReference<HashMap<String, Object>> MAP_REF = new TypeReference<HashMap<String, Object>>() {};
// some fields
public String jsonData;
@Transient
public HashMap<String, Object> data = new HashMap<String, Object>();
@Transient
private int initialHashCode = 0;
/**
* Converts JSON-Data to {@link HashMap}.
*/
@PostLoad
public void onLoad() {
try {
if (StringUtils.isNotEmpty(jsonData))
data.putAll( MAPPER.readValue(jsonData, MAP_REF) );
} catch (JacksonException ignore) {}
initialHashCode = data.hashCode();
}
/**
* Converts {@link HashMap} to JSON-String if dirty.
*/
@PreUpdate
public void onSave() {
System.out.println("**** " + initialHashCode + " == " + data.hashCode() );
if( initialHashCode == data.hashCode() ) return;
try {
jsonData = MAPPER.writeValueAsString(data);
} catch (JsonProcessingException e) {}
}
}
以及相应的存储库:
@Repository
public interface SomeJsonRepo extends JpaRepository<SomeJson, Long> {}
@PostLoad
工作得很好,但是代码
SomeJson sj = someJsonRepo.findById(42);
sj.data.put("lastSuccessfulExport", System.currentTimeMillis());
// sj.onSave(); (1)
someJsonRepo.save(er);
log.info( "Authentication failed" );
不会触发
@PreUpdate
方法。
如果我取消注释行
(1)
,我会看到 onSave()
被执行了两次:
**** -888829936 == 1673013342
2024-02-19T11:44:27.913+01:00 INFO 18408 --- [nio-8050-exec-1] some.Service : Authentication failed
**** -888829936 == 1673013342
JPA/Hibernate 是否无法确定实例是否脏并且“忘记”触发
@PreUpdate
?
您可以使用实体监听器
@PreUpdate 回调方法是你可以自定义的