Spring支持编程式事务管理和声明式事务管理。
-
编程式事务管理:事务和业务代码耦合度太高。
-
声明式事务管理:侵入性小,把事务从业务代码中抽离出来,使用AOP配置到配置文件中,提高维护性。
第一步:项目结构图
导入相关依赖包,并且在applicationContext.xml配置文件引入tx的命名空间第二步:编写pojo
package cn.zj.spring.pojo;
public class User {
private Integer id;
private String name;
private String email;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", email=" + email + "]";
}
public User(Integer id, String name, String email) {
super();
this.id = id;
this.name = name;
this.email = email;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
}
第三步:编写持久层(dao)的代码
package cn.zj.spring.dao.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import cn.zj.spring.dao.UserDao;
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void transOut(Integer outId, Integer money) {
this.jdbcTemplate.update("update t_account set balance = balance - ? where id = ?",money,outId);
}
@Override
public void transIn(Integer inId, Integer money) {
this.jdbcTemplate.update("update t_account set balance = balance + ? where id = ?",money,inId);
}
}
第四步:编写业务层接口和实现类
package cn.zj.spring.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import cn.zj.spring.dao.UserDao;
import cn.zj.spring.service.UserService;
@Service
@Transactional(readOnly = false,isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,timeout = 5)
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void trans(Integer outId, Integer inId, Integer money) {
//扣钱
userDao.transOut(outId, money);
System.out.println(1/0);
//打钱
userDao.transIn(inId, money);
}
@Transactional(readOnly = true)//readOnly默认为false
public Object selectByPrimaryKey(Integer id) {
return null;
}
}
第五步:编写db.properties配置文件
#批量修改 alt+shift +a 修改完毕以后 ,alt+shirf+a 还原
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/gj1?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
jdbc.maxActive=10
第六步:编写SpringConfig配置类
package cn.zj.spring.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.alibaba.druid.pool.DruidDataSource;
/*
*
* 此类在Spring全注解开发中当做Spring框架的配置类,用于替代applicaitonContext.xml配置文件
*
* ------------------------------------------
* @Configuration
* 把当前类作为Spring框架配置文件类
* -------------------------------------------
* @ComponentScan
* 配置spring支持注解配置的包扫描注解
* basePackages :设置包扫描的位置
* 也可以用value
* 简写
* @ComponentScan("cn.zj.spring")
* -------------------------------------------
* @PropertySource()
* 用于读取 xx.properties 配置文件,相当于 ;<context:property-placeholder location="classpath:db.properties"/>
* value 属性,读取配置文件的属性
* 注意:value默认可以省略,读取配置文件必须加上前缀 classpath:
* -------------------------------------------
* @Import()
* 导入其他的配置文件
* @Import(SpringConfig1.class)
*
*
*/
@Configuration
//@ComponentScan(basePackages = {"cn.zj.spring.dao","cn.zj.spring.service","cn.zj.spring.controller"})
@ComponentScan("cn.zj.spring")
@PropertySource("classpath:db.properties")
@EnableTransactionManagement //设置支持注解配置事务
public class SpringConfig {
/*
*
* @Value 用于读取 xx.properties 配置文件key对象的value
*
* @Value(value="xx.properties对应的ky")
* 如:
* @Value(value="${jdbc.driverClassName}")
* 简写
* @Value("${jdbc.driverClassName}")
*
* 如果开发者不想读取配置文件的key,也可以直接写固定的值
*/
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
//@Value("${jdbc.driverClassName}")
@Value("10")
private Integer maxActive;
/*
* @Bean 创建Spring的Bean对象。相当于<bean id="myDataSource" >
* 属性
* name :设置bena的名称,相当于<bean name="s1 s2 s3" >
* initMethod : 设置初始化方法,相当于 <bean init-method="xxx">
* destroyMethod :设置对象销毁方法,相当于<ben destory-method="xxx">
*
*/
@Bean(initMethod = "init",destroyMethod = "close")
//@Scope("prototype")
public DataSource getDataSource() {
System.out.println("创建数据源");
DruidDataSource dataSouce = new DruidDataSource();
dataSouce.setDriverClassName(this.driverClassName);
dataSouce.setUrl(this.url);
dataSouce.setUsername(this.username);
dataSouce.setPassword(this.password);
dataSouce.setMaxActive(this.maxActive);
return dataSouce;
}
@Bean
@Scope("prototype")
public JdbcTemplate getJdbcTemplate() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSource());
return jdbcTemplate;
}
//创建事务管理器(事务代理对象)
@Bean
public PlatformTransactionManager getTxManager() {
return new DataSourceTransactionManager(getDataSource());
}
}
第七步:测试代码
package cn.zj.spring.test;
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 cn.zj.spring.service.UserService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {
@Autowired
UserService userService;
@Test
public void testInsert() {
userService.trans(10086, 10010, 1000);
}
}