【问题标题】:Transaction not starting Spring + Hibernate + MySQL事务未启动 Spring + Hibernate + MySQL
【发布时间】:2014-02-06 20:26:41
【问题描述】:

我遇到了 Spring 中的事务无法启动的问题,因此对数据库所做的更改没有保存。配置如下:

web.xml(没有dispatcherServlet,有FacesServlet)

<context-param>
    <param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

applicationContext.xml 中的相关配置如下:

<context:annotation-config />
<context:component-scan base-package="pl.web.beans,pl.csci.dao" />

<bean id="sessionFactoryCsci" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
    <property name="configLocation" value="classpath:csci_database.cfg.xml" />
</bean>

<bean id="hibernateTemplateCsci" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory">
        <ref bean="sessionFactoryCsci" />
    </property>
</bean>

<bean id="hibernateDaoSupportCsci" class="org.springframework.orm.hibernate3.support.HibernateDaoSupport" abstract="true">
    <property name="hibernateTemplate" ref="hibernateTemplateCsci" />
</bean>

<bean id="csciPermSystemDAO" class="pl.csci.dao.CsciPermSystemDAO" parent="hibernateDaoSupportCsci">
</bean>

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

<tx:annotation-driven transaction-manager="transactionManager"/>

最后是负责保存实体的类:

pl.csci.dao
@Transactional(readOnly = true)
public class CsciPermSystemDAO extends HibernateDaoSupport implements ICsciPermSystemDAO {
@Override
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public Integer addPermission(Permissions Permission) throws DaoException {
    try {
       Integer permissionId = (Integer) getHibernateTemplate().save(Permission);
        LOGGER.info("Is transaction active?:" + DebugUtils.transactionActive() );
        return permissionId;
    } catch (Throwable ex) {
        // exception handling
    }
}

上面的代码 sn-p (DebugUtils.transactionActive()) 返回 false。此方法使用 TransactionSynchronizationManager 类来确定事务是否处于活动状态。

在调试 Hibernate 时,我可以看到来自插入的日志,但这些插入实际上从未出现在数据库中:

2014-01-30 15:13:15 调试 [hibernate.SQL] - 插入 csci_perm.permissions(BRANCH、GROUP_ID、PERSON_ID、READ_PERM、SYSTEM_ID、WRITE_PERM)值(?、?、?、?、?, ?)

您能告诉我我的配置有什么问题吗?

最后,这里是hibernate配置:

<hibernate-configuration>
  <session-factory>
    <!-- Database connection settings -->
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/csci_perm</property>
    <property name="hibernate.connection.useUnicode">true</property>
    <property name="hibernate.connection.characterEncoding">utf8</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.username">user</property>
    <property name="hibernate.connection.password">password</property>
    <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
    <property name="c3p0.acquire_increment">1</property>
    <property name="c3p0.idle_test_period">3000</property>
    <!-- seconds -->
    <property name="c3p0.max_size">20</property>
    <property name="c3p0.max_statements">50</property>
    <property name="c3p0.min_size">3</property>
    <property name="c3p0.timeout">100</property>
    <!-- seconds -->
    <!-- Enable Hibernate's automatic session context management -->
    <property name="current_session_context_class">thread</property>
    <!-- Disable the second-level cache  -->
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
    <!-- Echo all executed SQL to stdout - You can disable this once you have it working -->
    <property name="show_sql">true</property>
    <property name="hibernate.jdbc.batch_size">10</property>
    <mapping class="pl.csci.model.Permissions"/>
  </session-factory>
</hibernate-configuration>

【问题讨论】:

  • 你如何定义你的 TransactionManager?
  • 我已经编辑了第一篇文章

标签: java mysql spring hibernate


【解决方案1】:

可能是数据库不支持事务。

检查这个document

MySQL 服务器(版本 3.23-max 和所有版本 4.0 及以上)支持使用 InnoDB 和 BDB 事务存储引擎的事务。

【讨论】:

  • 我运行命令“显示表状态;”在 MySQL 数据库上,它显示使用了 InnoDB 引擎。此外,当我运行“显示引擎”命令时,我可以看到默认使用 InnoDB,这似乎启用了事务。
【解决方案2】:

你的配置是错误的,使用 spring 时不要乱用current_session_context_class,除非你使用的是 JTA。将其设置为线程会禁用正确的事务管理。

接下来,您的代码还会破坏正确的事务管理,永远不要捕获并吞下期望,这样事务管理就会失败,因为它永远不会看到异常并会尝试提交。要么接住再扔,要么不接住。

最后你不应该使用HibenateDaoSupport 和/或HibernateTemplate,它们应该被认为从 Hibernate 3.0.1(大约 2006 年)开始被弃用。按照here 的说明直接使用SessionFactory

基本上你的 dao 应该是这样的

@Transactional(readOnly = true)
public class CsciPermSystemDAO implements ICsciPermSystemDAO {

    private SessionFactory sf;

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public Integer addPermission(Permissions Permission) throws DaoException {
        LOGGER.info("Is transaction active?:" + DebugUtils.transactionActive() );
        return (Integer) sf.getCurrentSession().save(permission);
    }

    public void setSessionFactory(SessionFactory sf) {
        this.sf=sf;
    }
}

另一个提示你hibernate.cfg.xml 文件中的hibernate.connectionc3p0 属性是无用的。您正在注入数据源,并且这些属性仅在 hibernate 管理数据源/连接时使用。

关于你的弹簧配置&lt;context:annotation-config /&gt; 已经被&lt;context:component-scan /&gt; 暗示了。在您的会话工厂配置中,您正在设置 org.hibernate.cfg.AnnotationConfiguration 删除它,而是使用 AnnotationSessionFactoryBean 而不是 LocalSessionFactoryBean。这可以为您节省一些 xml。

【讨论】:

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