加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

java – 当我有Spring管理的Hibernate事务时如何启用Hibernate

发布时间:2020-12-15 01:33:55 所属栏目:大数据 来源:网络整理
导读:如果我与@Cascade(CascadeType.SAVE_UPDATE)有@OneToMany关系如下 public class One { private Integer id; private List 很多课 public class Many { private Integer id; /** * required no-arg constructor */ public Many() {} public Many(Integer uniq

如果我与@Cascade(CascadeType.SAVE_UPDATE)有@OneToMany关系如下

public class One {

    private Integer id;

    private List

很多课

public class Many {

    private Integer id;

    /**
      * required no-arg constructor
      */ 
    public Many() {}

    public Many(Integer uniqueId) {
        this.id = uniqueId
    }

    /**
      * Without @GeneratedValue annotation
      * Hibernate will use assigned Strategy
      */ 
    @Id
    public Integer getId() {
        return this.id;
    }

}

如果我有以下场景

One one = new One();

/**
  * generateUniqueId method will Take care of assigning unique id for each Many instance
  */
one.getManyList().add(new Many(generateUniqueId()));
one.getManyList().add(new Many(generateUniqueId()));
one.getManyList().add(new Many(generateUniqueId()));
one.getManyList().add(new Many(generateUniqueId()));

我打电话给

sessionFactory.getCurrentSession().save(one);

继续之前

根据Transitive persistence Hibernate参考文档,您可以看到

If a parent is passed to save(),update() or saveOrUpdate(),all children are passed to saveOrUpdate()

好.现在让我们看看Java Persistence With Hibernate一书中有关saveOrUpdate方法的内容

Hibernate queries the MANY table for the given id,and if it is found,Hibernate updates the row. If it is not found,insertion of a new row is required and done.

哪个可以翻译

INSERT INTO ONE (ID) VALUES (?)

/**
  * I have four Many instances added To One instance
  * So four select-before-saving
  *
  * I DO NOT NEED select-before-saving 
  * Because i know i have a Fresh Transient instance
  */
SELECT * FROM MANY WHERE MANY.ID = ?
SELECT * FROM MANY WHERE MANY.ID = ?
SELECT * FROM MANY WHERE MANY.ID = ?
SELECT * FROM MANY WHERE MANY.ID = ?

INSERT INTO MANY (ID,ONE_ID) VALUES (?,?)
INSERT INTO MANY (ID,?)

任何解决方法避免选择之前保存???是的,你也可以

>添加@Version列(未应用)
>实现Hibernate拦截器提供的isTransient方法(我有选项)

因此,当使用这种级联时,为了避免选择保存前的默认行为,我通过将Hibernate Interceptor分配给一个Hibernate Session来改进我的代码,Hibernate Session的Transaction由Spring管理.

这是我的存储库

之前(没有任何Hibernate拦截器):它工作正常!

@Repository
public class SomeEntityRepository extends AbstractRepository

之后(使用Hibernate Inteceptor):出现问题(没有执行SQL查询 – 无论是INSERT还是SELECT-BEFORE-SAVING)

@Repository
public class SomeEntityRepository extends AbstractRepository

我的问题是:为什么Spring在使用Hibernate拦截器时不会持久保存我的实体及其关系,我该怎么办才能解决这个问题呢?

最佳答案
Spring维护当前会话和当前事务之间的关联(参见SessionFactoryUtils.java.)由于已经存在与当前DAO方法调用相关联的会话,因此您必须使用此会话,或者参与处理黑暗的细节将新会话与先前的事务上下文相关联.这可能是可能的,但风险很大,绝对不推荐.在休眠状态下,如果你已经打开了一个会话,那么就应该使用它.

话虽如此,您可能会为您创建一个新会话并将其与当前事务上下文相关联.使用SessionFactoryUtils.getNewSession(SessionFactory,Interceptor).如果你使用它而不是hibernate的sessionFactory,那么这应该保持与事务的关联.

最初,您可以直接在DAO中编写代码.当它经过试验和测试并希望能够正常工作时,您可以采取措施将弹簧代码移出DAO,例如使用AOP向add()方法添加建议,以创建和清理新会话.

另一种选择是使用全局拦截器.即使它是全局的,你也可以赋予它本地可控的行为. TransientInterceptor包含threadLocal< Boolean>.这是当前线程的标志,用于指示拦截器是否应为isTransient返回true.您在add()方法的开头将其设置为true,并在结束时将其清除.例如.

   class TransientInterceptor extends EntityInterceptor {
      ThreadLocal

然后在你的DAO中:

@Override
public void add(SomeEntity instance) {
   try {
       TransientInterceptor.set(true);
       sessionFactory.getCurrentSession().save(instance);
   }
   finally {
      TransientInterceptor.set(false);   
   }
}

然后,您可以将TransientInterceptor设置为SessionFactory上的全局拦截器(例如,LocalSessionFactoryBean).为了减少这种侵入,您可以创建一个AOP周围的建议,以便在适当的情况下将此行为应用于所有DAO添加方法.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读