2017-07-26 80 views
0

我有2个存储库 - 每个存储库都有针对不同对象的保存方法。 我想执行这两个方法作为事务,这意味着如果其中一个失败,事务将被回滚。 (这在我看来是交易的意义)。如何在@Transactional中实现春季真正的交易

这里是我的代码:

@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') 
} 

为了测试它,我在我的控制器saveTomato改变一个数据库列的名称在番茄台,所以(番茄)方法会失败。如果发生这种情况,我想要保存的香蕉回滚。我认为它应该像@Transactional方法注释一样工作,但我错了。

那么如何实现我的目标呢?

+0

你不使用弹簧引导,是吗?如果没有,你是否声明了'DataSourceTransactionManager'?请显示你的配置。 – alfcope

+0

请保持会话工厂和事务对象。 –

+0

您是使用'@ EnableAutoConfiguration'创建数据源吗?你应该有一个由Spring自动创建的'DataSourceTransactionManager' bean。 – alfcope

回答

0

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

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(); 
    } 

我不知道这是否是最好的解决办法,但在我的情况下,工作的;)

+0

为了获得SessionFactory,我应该添加到spring引导中的依赖项? – ivanlirchev

+0

我认为这种依赖关系:spring-boot-starter-data-jpa – Liline

+0

以及如何配置bean,因为它表示没有找到类型为SessionFactory的bean?用@Transactional传播还有什么方法吗?否则这个注释是无用的。 – ivanlirchev

1

事务控制应该放在服务业务处理层

+0

不看结构。这只是一个例子。 – ivanlirchev