如何使用@Transactional

时间:2017-07-26 08:08:43

标签: java spring spring-boot transactions

我有2个存储库 - 每个存储库都有不同对象的保存方法。 我想将这两个方法作为事务执行,这意味着如果其中一个方法失败,那么事务将被回滚。 (这是我认为交易的含义)。

这是我的代码:

@Repository
public class BananaRep {

    private JdbcTemplate jdbc;

    @Autowired
    public BananaRep(JdbcTemplate jdbc) {
        this.jdbc = jdbc;
    }

    public void saveBanana(Banana banana) {
        jdbc.update("insert into ......", ...);
    }
}

@Repository
public class TomatoRep {
    private JdbcTemplate jdbc;

    @Autowired
    public TomatoRep(JdbcTemplate jdbc) {
        this.jdbc = jdbc;
    }

    public void saveTomato(Tomato tomato) {
        jdbc.update("insert into ... ", ....);
    }
}

@RestController
public class MixController {
    @Autowired
    BananaRep bananaRep;
    @Autowired
    TomatoRep tomatoRep;

    @Transactional
    @RequestMapping(value="/mix", method= RequestMethod.GET)
    public Car mix() {

        Banana banana = new Banana(....);
        bananaRep.saveBanana(banana );

        Tomato tomato= new Tomato(...);
        tomatoRep.saveTomato(tomato);
        return banana;
    }
}

我的构建:

buildscript {
    ext {
        springBootVersion = '2.0.0.M2'
    }
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/snapshot" }
        maven { url "https://repo.spring.io/milestone" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
    maven { url "https://repo.spring.io/snapshot" }
    maven { url "https://repo.spring.io/milestone" }
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter-jersey')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-starter-jdbc')
    compile('mysql:mysql-connector-java')
}

为了测试它,我在Tomato表中更改了一个db列的名称,因此在我的控制器中saveTomato(番茄)方法将失败。如果发生这种情况,我希望保存香蕉以便回滚。我认为应该使用@Transactional方法注释,但我错了。

如何实现我的目标呢?

3 个答案:

答案 0 :(得分:1)

@Autowired
    private SessionFactory sessionFactory;

@Transactional
    @RequestMapping(value="/mix", method= RequestMethod.GET)
    public Car mix() {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        Banana banana = new Banana(....);
        bananaRep.saveBanana(banana );

        Tomato tomato= new Tomato(...);
        tomatoRep.saveTomato(tomato);
        session.getTransaction().commit();
        return banana;
    }

对于bean:

import org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean;

 @Bean
    public HibernateJpaSessionFactoryBean sessionFactory(){
        return new HibernateJpaSessionFactoryBean();
    } 

我不知道这是否是最佳解决方案,但就我而言,这是有效的;)

答案 1 :(得分:1)

交易控制应放在服务业务处理层

答案 2 :(得分:0)

问题是我在MySQL表中使用了MyISAM,它们不支持事务。这对我来说是个大问题。我希望我的解决方案可以帮助像我这样的其他人。