2017-05-02 79 views
1

我想在我的方法中做幾個插入,並且想要在出現任何錯誤時回滾所有插入。 這裏是我的JDBC bean定義如何在Spring JDBC中回滾事務?

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context.xsd 
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> 

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

    <context:property-placeholder location="classpath:jdbc.properties"/> 

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="${jdbc.driverClassName}"/> 
     <property name="url" value="${jdbc.url}"/> 
     <property name="username" value="${jdbc.username}"/> 
     <property name="password" value="${jdbc.password}"/> 
    </bean> 

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
     <property name="dataSource" ref="dataSource"/> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
     <property name="dataSource" ref="dataSource"/> 
    </bean> 

</beans> 

這是我的方法

@Transactional 
public void save(Map<String, String> properties, Long moduleId, 
       String language, String propertyFileName, String filePath) { 

    KeyHolder keyHolder = new GeneratedKeyHolder(); 

    final String propertyFileQuery = "INSERT INTO property_file " + 
      "(moduleId, languageId, propertyFileName,hash,path) " + 
      "VALUES (?,?,?,?,?)"; 

    jdbcTemplate.update(connection -> { 
     PreparedStatement ps = 
       connection.prepareStatement(propertyFileQuery, new String[]{"id"}); 
     ps.setLong(1, moduleId); 
     ps.setString(2, language); 
     ps.setString(3, propertyFileName); 
     ps.setString(4, "hash goes here"); 
     ps.setString(5, filePath); 

     return ps; 
    }, keyHolder); 

    int x = 0/0; 

    final String propertiesQuery = "INSERT INTO property_value " + 
      "(propertyFileId, propKey, propValue) " + 
      "VALUES (?,?,?)"; 

    properties.forEach((key, value) -> jdbcTemplate.update(
      propertiesQuery, keyHolder.getKey(), key, value 
    )); 

} 

我希望它回滾第一次插入,它滿足了運行時異常0/0

之後,但在數據進入數據庫,並不會回滾。

我在做什麼錯了?

回答

0

發現了原因。事務管理是好的,我在交易中無法完成工作的原因是因爲我的MySQL引擎。它被設置爲MyISAM。 作爲MySQL網站引用

MyISAM不支持事務,可能永遠也不會。

剛將表格從MyISAM更改爲InnoDb,並得到它的工作。

0

您可以將@Transactional設置爲您的類,而不是將其綁定到單個方法,因爲當您將其綁定到類時,所有操作都將參與單個全局事務,並且如果任何事務失敗,您的操作將被回滾

0
private PlatformTransactionManager transactionManager; 

public void setDataSource(DataSource dataSource) { 

    this.jdbcTemplate = new JdbcTemplate(dataSource); 
} 

public void setTransactionManager(PlatformTransactionManager transactionmanager) { 
    this.transactionManager = transactionmanager; 
} 

和方法內,你必須使用

TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); 

jdbcTemplate.update後,你必須提交事務

 transactionManager.commit(status); 

你也可以用@Transactional(propagation=Propagation.REQUIRED) `

+0

doens't work:/ – Carmine