如何在Hibernate中禁用脏检查

3
这是一个简单的代码。
我通过JPA存储库从数据库中获取一些实体,进行一些逻辑操作,并且不希望Hibernate为我保存它。
      @GetMapping("/{id}")
      @Transactional
      public ERespondent getRespondent(@PathVariable Long id) {
          var entity= respondentRepository.findById(id).get();
          entity.setFirstName("weqweqwdq");
          // other logic here..
          return entity;
      }

在配置文件中将FlushMode设置为MANUAL,但仍然可以看到Hibernate在最后进行更新。
我需要在一个事务中执行才能触发延迟加载集合吗?
我想自己管理实体,并且不希望Hibernate执行额外的工作,比如在缓存中保存实体的副本,检查是否有更改,然后保存到数据库。
2个回答

3

我知道3个选项

  1. 将事务标记为只读:

@Transactional(readOnly = true)

  1. 首先分离实体:
@Autowired
private EntityManager em;

@Transactional
public ERespondent getRespondent(@PathVariable Long id) {
    var entity= respondentRepository.findById(id).get();
    em.detach(entity); //now it is disconnected from persistence and becomes +- POJO
    entity.setFirstName("weqweqwdq");
    // some other logic
    return entity;
}

复制整个对象,进行修改并返回副本:
@Transactional
public ERespondent getRespondent(@PathVariable Long id) {
    var entity= respondentRepository.findById(id).get();
    copy=new EResponsend(entity); // you have to implement copy constructor
    copy.setFirstName("weqweqwdq");
    return copy;
}

1
要分离实体,我需要使用EntityManager - 这意味着我需要生成数十亿行样板代码。我需要为整个应用程序做这个,而不仅仅是一个方法。 - Алексеев станислав
1
复制实体不是一个好主意 - 我想要禁用它 - 因为Hibernate会自动处理 - Алексеев станислав
1
@Transactioanl(readOnly=true) 这也不是一个好主意,因为你不能自己保存实体。但是我需要自己保存实体,而不想通过Hibernate来做同样的事情 - 我只需要禁用脏检查,仅此而已... - Алексеев станислав
你想要完全禁用它在应用程序层面上,并且永远不再重新启用吗?我在考虑偶发的分离。毕竟,JPA存在的目的是实际管理实体,而不仅仅是用SQL结果填充POJOs。 - Antoniossss
关于通过实体管理器分离对象,您可以编写切面,在需要的时候将对象分离(不清楚何时应该这么做和何时不应该)。 - Antoniossss
显示剩余9条评论

0

您可以编写一个拦截器来清除实体管理器。然后,您只需使用拦截器注释或Spring中的其他方式对顶级类进行注释(可能请参阅此文章https://www.baeldung.com/cdi-interceptor-vs-spring-aspectj),就可以开始工作了。根据您如何分离代码,您可能需要将其放在单独的方法上而不是在类级别上,或者考虑在“只读”和“写入”代码路径之间拆分代码。我通常通过将此“只读”代码移动到所谓的DataAccess类中,将“写入”代码移动到Service类中来完成此操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接