事务:
事物作用:在数据层保障一系列的数据库操作同成功同失败。
Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败。
事务角色:
- 事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法。
- 事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法。
事务传播行为:
例:@Transactional(propagation = Propagation.REQUIRES_NEW)
事务相关配置:
程序在error时候和运行时异常会发生回滚,有些异常默认不参与回滚,需要加条件。
例如:@Transactional(rollbackFor = {IOException.class})
代码实现:
config包
JdbcConfig.java
package com.it.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
Mybatis.java
package com.it.config;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class MybatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
ssfb.setTypeAliasesPackage("com.it.domain");
ssfb.setDataSource(dataSource);
return ssfb;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.it.dao");
return msc;
}
}
SpringConfig.java:
package com.it.config;
import org.springframework.context.annotation.*;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@ComponentScan("com.it")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
@EnableTransactionManagement //事务注解
public class SpringConfig {
}
dao包:
AccountDao.java:
package com.it.dao;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
public interface AccountDao {
@Update("update acc set money = money + #{money} where name = #{name}")
void inMoney(@Param("name") String name, @Param("money") Double money);
@Update("update acc set money = money - #{money} where name = #{name}")
void outMoney(@Param("name") String name, @Param("money") Double money);
}
LogDao.java
package com.it.dao;
import org.apache.ibatis.annotations.Insert;
public interface LogDao {
@Insert("insert into acc_log (info,createDate) values(#{info},now())")
void log(String info);
}
service包:
impl包:
AccountServiceImpl.java:
package com.it.service.impl;
import com.it.dao.AccountDao;
import com.it.service.AccountService;
import com.it.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Autowired
private LogService logService;
public void transfer(String out,String in,Double money){
try{
accountDao.outMoney(out,money);
accountDao.inMoney(in,money);
}
finally {
logService.log(out,in,money);
}
}
}
LogServiceImpl.java:
package com.it.service.impl;
import com.it.dao.LogDao;
import com.it.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LogServiceImpl implements LogService {
@Autowired
private LogDao logDao;
public void log(String out, String in, Double money) {
logDao.log("转账由"+out+"到"+in+"金额"+money);
}
}
AccountService.java:
package com.it.service;
import org.springframework.transaction.annotation.Transactional;
public interface AccountService {
/**
* 转账操作
* @param out 转出
* @param in 转入
* @param money 金额
*/
@Transactional //开启事务
public void transfer(String out, String in, Double money);
}
LogService.java
package com.it.service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
public interface LogService {
@Transactional(propagation = Propagation.REQUIRES_NEW) //开辟新事物
void log(String out,String in,Double money);
}
Test:
test.java:
package com.it;
import com.it.config.SpringConfig;
import com.it.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.io.IOException;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountTest{
@Autowired
private AccountService accountService;
@Test
public void testTransfer() throws IOException{
accountService.transfer("zhangsan","lisi",50D);
}
}