基于存储库方法在JPA中以不同的方式处理数据



在Java Spring应用程序中,我有一个类似于下面的类:

class MyModel {
// other properties here

private Boolean accessAllowed;
public Boolen isAccessAllowed() {
return accessAllowed;
}
public void setAccessAllowed(Boolean accessAllowed) {
this.accessAllowed = accessAllowed;
}
public void updateAccessAllowedForResponse() {
// business logic to update `accessAllowed` only for read methods of repository
}
public void updateAccessAllowedForSave() {
// business logic to update `accessAllowed` only for write methods of repository
}
}

我们的想法是,我们在DB中使用三个值,即nulltruefalse,并使用空值为"default"也就是说,用户没有做出选择。因此,如果该值在DB中为空,则根据某些业务逻辑返回truefalse

问题是这个值只意味着在内存中更新。对于响应或其他应用领域,但updateAccessAllowedForResponse()之后实体的变化不应该在DB中保留。

目前,我将实体从存储库中的Hibernate会话中移除,例如

class MyRepository extends GenericRepository<MyModel> {
public MyModel get(Long id) {
MyModel instance = super.get(id);
Session session = entityManager.unwrap(Session.class);
session.evict(instance);
instance.updateAccessAllowedForResponse();
return instance;
}
public MyModel merge(MyModel instance) {
instance.updateAccessAllowedForSave()
return super.merge(instance);
}
}

这是有效的,但是上面的方法有一个很大的问题:我必须在很多地方重复这个。理想情况下,我希望能够在MyModel本身上定义这个逻辑。也可以选择使用自定义存储库,但这是一个非常特殊的用例,我们没有时间为这个功能编写一个自定义存储库。

老实说,我是Java/Spring的新手。所以我希望有一些方法可以做到这一点,我无法通过谷歌找到。

您可以使用Spring事务来完成此任务,通过创建两个单独的保存方法,其中一个具有SpringTransactionalisolation = Isolation.SERIALIZABLE,另一个没有。你的意思是,你想强迫用户使用特定的保存点,无论他们是否想在交易中使用不同的对象做其他事情。在这种情况下,强制提交,刷新,调用yourPersistenceService.saveSecondaryObject(x)或其他东西,然后你说yourPersistenceService.savePrimaryObject(y)总是需要之前调用。或者,对于MyModel对象,通过更新触发方法进行预保存和后保存。这应该由Hibernate自动完成,因此您有机会跟踪其中的字段更改,并在持久化后设置字段。这与我在只读字段中遇到的情况是一样的,只读字段只需要为了输出而复制(数据库是Postgres 12,我创建了一个复制表,它只在廉价触发器上从一个表到只读表进行事务性复制。这样,每次模型更改时,它都会触发Postgres上的过去的作业来更新表)。

public MyModel get(Long id) {
MyModel instance = super.get(id);
Hibernate.initialize(instance.accessAllowed);
instance.flush();
return instance;
}

作为第三种选择,您可以让控制器处理所有这些,接收JPA对象,设置字段,然后将其发送到JSP,而不需要刷新或重新加载任何东西。

最新更新