简体   繁体   English

如何在Spring JDBC中回滚事务?

[英]How to rollback transaction in Spring JDBC?

I want to do several inserts in my method, and want to rollback all the inserts if anything goes wrong. 我想在我的方法中执行几个插入操作,并且如果有任何问题要回滚所有插入操作。 Here's my jdbc bean definition 这是我的jdbc bean定义

<?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>

And here's my method 这是我的方法

@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
    ));

}

I want it to rollback the first insert, after it meets the runtime exception 0/0 我希望它遇到运行时异常0/0后回滚第一个插入

But the data goes into the database, and doesn't get rolled back. 但是数据进入数据库,并且不会回滚。

What am i doing wrong? 我究竟做错了什么?

Found out the reason. 找出原因。 The transaction management was ok, the reason I couldn't do my job in a transaction was because of my MySQL Engine. 事务管理还可以,我无法完成事务的原因是我的MySQL Engine。 It was set to MyISAM . 它设置为MyISAM As cited in MySQL web site 如MySQL网站中所引用

MyISAM does not support transactions and probably never will. MyISAM不支持交易,可能永远不会。

Just changed the tables from MyISAM to InnoDb , and got it working. 刚刚将表从MyISAM更改为InnoDb ,并使其正常工作。

您可以将@Transactional设置为您的类,而不是将其与单个方法绑定,因为当您将其绑定到类时,所有操作将参与单个全局事务,并且如果任何事务失败,则您的操作将被回滚

private PlatformTransactionManager transactionManager;

public void setDataSource(DataSource dataSource) {

    this.jdbcTemplate = new JdbcTemplate(dataSource);
}

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

and inside the method you have to use 在您必须使用的方法内

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

and after jdbcTemplate.update you have to commit transaction jdbcTemplate.update之后,您必须提交事务

        transactionManager.commit(status);

you can also use @Transactional(propagation=Propagation.REQUIRED) ` 您还可以使用@Transactional(propagation=Propagation.REQUIRED) `

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM