【问题标题】:Spring transaction does not startSpring事务没有启动
【发布时间】:2016-07-15 16:31:37
【问题描述】:

环境:Eclipse Keppler,码头 7.5.1, Spring 3.2.1、Hibernate 4.2.5、Oracle 11

问题:休眠实体保存不适用于物理上的数据库

问题的原因可能是:没有活跃的事务

问题:为什么交易没有开始?

注意:如果我将 openSession() 更改为 getCurrentSession(),一切正常。事务开始 & 实体物理保存到数据库。


GenericDaoImpl:

@Transactional(propagation = Propagation.REQUIRED, readOnly = false, 
               value = "transactionManager")
public abstract class GenericDaoImpl<T, ID extends Serializable> implements GenericDao<T, ID> {

    private Class<T> persistentClass;   

    protected SessionFactory sessionFactory;

    @Override
    public T addEntity(T entity) {

        Session session = null;

        try {
            session = sessionFactory.openSession();

            session.save(entity);
        } catch (Exception e) {
            e.printStackTrace();    
        } finally {

            if(session != null){
                Transaction t = session.getTransaction();               
System.out.println("Transaction().isActive()......." + session.getTransaction().isActive());            
System.out.println("before: session.isOpen()  " + session.isOpen() + " trx wasCommitted " + t.wasCommitted());  

                session.close();

System.out.println("after: session.isOpen()  " + session.isOpen() + " trx  wasCommitted" + t.wasCommitted());               
        }
    }

    return entity;
}

UserDaoImpl 扩展 GenericDaoImpl:

@Component
@Scope("prototype")
@Transactional(propagation = Propagation.REQUIRED, readOnly = false, value = "transactionManager")
public class UserDaoImpl extends GenericDaoImpl<User, Long> implements UserDao {
    .
    .
    }

以下代码执行后调用:

userDao.addEntity(user);   

日志打印如下:

Transaction().isActive().......false
before: session.isOpen()  true trx wasCommitted false
after: session.isOpen()  false trx  wasCommittedfalse

交易记录:

[2016-07-15 10:42:04,567][DEBUG] Adding transactional method 'addEntity' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; 'transactionManager' 

databaseContext.xml:

<bean class="com.blabla.dao.local.implementations.UserDaoImpl"
    scope="prototype" name="userDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven />

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

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan"
        value="com.blabla.model.local,com.blabla.model.authorization, com.blabla.model.authentication" />
    <property name="entityInterceptor">
        <bean class="com.blabla.listeners.EntityInterceptor" />
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.transaction.flush_before_completion">true</prop>
            <prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
            <prop key="hibernate.connection.driver_class">${jdbc.driver}</prop>
            <prop key="hibernate.connection.url">${jdbc.url}</prop>
            <prop key="hibernate.connection.username">${jdbc.user}</prop>
            <prop key="hibernate.connection.password">${jdbc.password}</prop>
        </props>
    </property>
</bean>
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"
    destroy-method="close">
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.user}" />
    <property name="password" value="${jdbc.password}" />
    <property name="initialSize" value="5" />
    <property name="maxActive" value="10" />
</bean>

【问题讨论】:

  • 在将 sessionFactory 对象注入到你的 userDaoImpl 时,你不应该使用作用域作为原型,在这种情况下,spring 将为每个新调用创建新的 sessionFactory obj。 sessionFactory obj 必须为每个应用程序一个
  • 问题是你不使用getCurrentSession 这是你应该使用的,否则它将不起作用。您不应该自己搞乱打开/关闭会话,如果这样做,您还必须自己管理交易。
  • 您正在尝试将 sessionFactory 对象注入到您的 userDaoImpl 类中,而不是使用注释或 xml 映射将其直接注入到您的泛型类中。
  • @M. Deinum 请告诉我,他将 sessionFactory obj 注入到 userDaoImpl 类中,原型为范围,然后尝试在泛型类中访问,这怎么可能?
  • 假设 setSessionFactory 在通用 dao 上,他注入的东西非常好。此外,接收会话工厂的 bean 是原型范围的这一事实根本不会影响任何事情。

标签: spring transactions spring-transactions


【解决方案1】:

在您的示例中,spring 处理休眠会话和事务非常明显:

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

所以你不能使用这个:

session = sessionFactory.openSession();

因为您正在打开新的休眠会话,而 spring 对此一无所知。

使用:sessionFactory.getCurrentSession() 意味着spring 将使用您的正确配置处理幕后的所有事情。

【讨论】:

    猜你喜欢
    • 2011-11-25
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    相关资源
    最近更新 更多