【问题标题】:Hibernate and Spring DataSourceTransactionManagerHibernate 和 Spring DataSourceTransactionManager
【发布时间】:2014-11-12 14:13:16
【问题描述】:

我正在尝试使用 Hibernate 和 Spring DataSourceTransactionManager 来处理提交和回滚功能,但可能我没有得到任何东西。

在使用 Spring DataSourceTransactionManager 之前,这是我的 DAO 类之一

  package com.springgestioneerrori.DAO;

  public class UtenteDAO extends DAOBase{   

       public void salvaUtente(Utente utenteIn) throws DAOException{ 

            Session session = getHibernateSession(); //from this method  I get Hibernate SessionFactory
              try{   
                  session.beginTransaction();             
                  session.saveOrUpdate(Object); 
                  session.getTransaction().commit();    
                  }
              catch(Exception e){
                  session.getTransaction().rollback()
              }
        }
}

这是给我 sessionFactory 的类

 private static final SessionFactory sessionFactory = buildSessionFactory();

            private static SessionFactory buildSessionFactory() {
                try {
                    // Create the SessionFactory from hibernate.cfg.xml
                    return new AnnotationConfiguration().configure().buildSessionFactory();  
                }
                catch (Throwable ex) {
                              System.err.println("Initial SessionFactory creation failed." + ex);
                    throw new ExceptionInInitializerError(ex);
                }
            }

            public static SessionFactory getSessionFactory() {
                return sessionFactory;
            }

            public static void shutdown() {             
                getSessionFactory().close();
            }

public Session getHibernateSession (){
    Session session = HibernateUtil.getSessionFactory().openSession();
    return session;
}   

现在我正在尝试以声明方式使用 DataSourceTransactionManager。按照网上的一些例子,我写了这个:

 <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />        

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="salvaUtente"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="userDaoTxPointcut" expression="execution(* com.springgestioneerrori.DAO.UtenteDAO.salvaUtente(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="userDaoTxPointcut" />
</aop:config>       

现在,我应该在方法 salvaUtente() 中写什么来执行许多插入,例如像这些

  session.saveOrUpdate(User); 
  session.saveOrUpdate(UserCredentials); 
  session.saveOrUpdate(UserOtherDetails); 

并让 Spring 处理 commint 和回滚?

【问题讨论】:

  • 单位工作是什么?所有插入都是一个工作单元,或者插入编号 3 应该发生,而与其他插入无关
  • 所有插入都相互绑定,如果一个插入失败,其他插入必须无效。

标签: java spring hibernate spring-mvc spring-transactions


【解决方案1】:

首先,您使用了错误的事务管理器。 DataSourceTransactionManager 不是用于 Hibernate,而是用于普通 JDBC。如果您使用普通的 Hibernate,请使用 HibernateTransactionManager。 (假设您在这里使用的是 Hibernate 4!)。

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

现在我还建议使用@Transactional 而不是&lt;tx:advice /&gt;&lt;aop:config /&gt; 块。使您的配置更容易。只需删除提到的 2 个块并替换为 &lt;tx:annotation-driven /&gt;

<tx:annotation-driven />

现在您的代码是错误的,因为您自己开始交易。使用 @Transactional 注释您的方法(添加上述内容后)并删除您的事务处理代码。

@Transactional
public void salvaUtente(Utente utenteIn) throws DAOException{ 
    Session session = getHibernateSession(); //from this method  I get Hibernate SessionFactory
    session.saveOrUpdate(Object); 
}

现在我不知道您的 getHibenateSession 方法做了什么,但请确保您不要在 SessionFactory 上使用 openSession 来获取会话。请改用getCurrentSession

protected Session getHibernateSession() {
    return sessionFactory.getCurrentSession();
}

您当前的BaseDAO 课程有缺陷。删除您的 buildSessionFactory 并删除 static final。让 Spring 配置并注入 SessionFactory

public abstract class BaseDAO {

    @Autowired
    private SessionFactory sessionFactory;

    protected Session getHibernateSession() {
        return sessionFactory.getCurrentSession();
    }
}

在您的配置中添加LocalSessionFactoryBean 的配置。

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    ... Other Hibernate Properties
</bean>

这基本上就是所需要的。这在the Spring Reference guide中也有详细解释。我强烈建议阅读。

【讨论】:

  • 我编辑了我的帖子并添加了为我提供 sessionFactory 的类
  • 如果 io 尝试使用 getCurrentSession 而不是 openSessione 获取未配置的 CurrentSessionContext!
  • 那么您的配置是错误的(请参阅我修改后的答案),请阅读现在包含在其中的链接。参考指南详细解释了如何使用 hibernate 进行设置。我强烈建议阅读。
  • 谢谢你。我按照您的示例阅读了链接,但仍然错过了一步。现在,在调用 saveOrUpdate() 方法后,我的持久对象上出现错误 Unknown entity,注释为 @Entity。可能我必须在 sessioneFactory 或 transactionManager bean 中映射该类,但我在该链接上找不到示例。
  • 也许我明白了。我用扩展 LocalSessionFactoryBean 的 AnnotationSessionFactoryBea 替换了 LocalSessionFactoryBean。这样我就可以使用 annotatedClasses 属性。到目前为止,它似乎工作。非常感谢您的宝贵帮助。
【解决方案2】:

我建议

@Transaction(rollbackFor = {if you need to rollback on certain checked exception})
salvaUtente()

除非另有说明,否则事务只会因未经检查的异常而回滚。

如果事务中的任何时候发生异常,salvaUtente 将被回滚,否则一旦方法存在,事务将被提交

【讨论】:

  • 我还是错过了一步。我应该写什么 insde salveUtente() 来管理 3 插入 session.saveOrUpdate(User); session.saveOrUpdate(UserCredentials); session.saveOrUpdate(UserOtherDetails);
【解决方案3】:

HibernateTransactionManager 还可以管理 DataSource 上的事务。我们需要在 HibernateTransactionManager 中注入 DataSource,它应该适用于 Hibernate 和普通旧 SQL。

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager>
  <property name="sessionFactory" ref="sessionFactory"/>
  <property name="dataSource" ref="dataSource"/>
</bean>

希望这对你有用。

我知道这已经很晚了,但可能会帮助有人登陆这篇文章

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多