声明式事务
3.1、搭建声明式事务的环境
3.1.1、搭建Spring环境
3.1.1.1、导入Spring的依赖
创建一个简单的maven项目并导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
项目结构
3.1.1.2、创建相应的JavaBean以及dao、service
/***************************JavaBean******************************************/
@Component
public class User {
private String username;
private String password;
/*
get / set 方法 有无参构造器
*/
}
/*******************************service**************************************/
public interface UserService {
}
/************************UserServiceImpl **************************************/
@Service
public class UserServiceImpl implements UserService{
}
3.1.1.3、创建配置类,配置包扫描将组件加入ioc容器
@ComponentScan("test")
@Configuration
public class FirstConfig {
}
3.1.1.3、创建测试类,测试容器中是否存在我们加入的组件
@Test
public void test1(){
AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(FirstConfig.class);
String[] names = ioc.getBeanDefinitionNames();
for (String name :
names) {
System.out.println("name " +name);
}
}
测试结果
说明spring环境没有问题
3.1.2、搭建Spring数据库环境
3.1.2.1、导入相关依赖
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
目前项目结构
3.1.2.2、用注解的方式在配置类中配置数据源以及JdbcTempalte
@ComponentScan("test")
@Configuration
public class FirstConfig {
@Bean
public DataSource dataSource () throws Exception {
ComboPooledDataSource dataSource=new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("mypasswordis123");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
return dataSource;
}
/*
这里我就不用mybatis了,直接用一个jdbcTemplate
*/
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){//在这个方法参数中的参数都能从容器中获取
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
}
3.1.2.3、数据库以及数据表
3.1.2.4、加入dao以及修改service
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import test.bean.User;
import java.util.UUID;
@Repository
public class UserDao {
@Autowired
JdbcTemplate jdbcTemplate;
public void insert(User user){
String sql="INSERT INTO t_user (username,password) VALUES(?,?)";
jdbcTemplate.update(sql,user.getUsername(),user.getPassword());
}
}
/************************************************/
public interface UserService {
public void insert(User user);
}
/***************************************************/
@Service
public class UserServiceImpl implements UserService{
@Autowired
UserDao userDao;
@Override
public void insert(User user) {
userDao.insert(user);
}
}
3.1.2.5、测试数据库环境
@Test
public void test1(){
AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(FirstConfig.class);
UserService userService = (UserService) ioc.getBean(UserService.class);
User user = new User("zhang", "zhang");
userService.insert(user);
System.out.println("------------------");
}
说明数据库环境搭建完成!
但是此时我们并没有加上事务控制,现在倘若在程序的执行过程中且在插入语句之后出现某处错误的话,也会插入成功,并没有体现原子性操作。
现在我们在UserServiceImpl中模拟一个除零错误,验证是否实现事务控制。
@Service
public class UserServiceImpl implements UserService{
@Autowired
UserDao userDao;
@Override
public void insert(User user) {
userDao.insert(user);
System.out.println("插入语句已执行....");
int i=1/0;
}
}
再次运行上面的测试方法
此时数据库中仍然会出现数据
3.1.3、搭建Spring事务环境
我们之前使用xml配置spring事务的时候,完成之后只需要在需要添加事务的方法上加上一个@Transactional注解,即可表示该方法是一个事务方法。但是之前用XML方法开启注解事务的时候,需要设置一个tx配置
所以我们基于注解的也要加上,只不过在注解这里添加上面的tx配置换成了另一个注解,即在配置类中加入如下注解:@EnableTransactionManagement
@EnableTransactionManagement
@ComponentScan("test")
@Configuration
public class FirstConfig {
@Bean
public DataSource dataSource () throws Exception {
ComboPooledDataSource dataSource=new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("mypasswordis123");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
return dataSource;
}
/*
这里我就不用mybatis了,直接用一个jdbcTemplate
*/
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){//在这个方法参数中的参数都能从容器中获取
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
}
我们再来进行一次测试方法,这个时候又报了一个错误
这个错误提示我们,还没有进行配置事务管理器PlatformTransactionManager,所以ioc容器中找不到事务管理器。所以说配置事务管理器这一步也是关键的一步。
而事务管理器PlatformTransactionManager的实现有很多种,但不管是spring的事务管理器还是mybatis的事务管理器都是用下图这个DataSourceTransactionManager事务管理器进行管理事务的
所以我们现在来将这个事务管理器添加进入容器,但是要注意,当我们配置这个事务管理器的时候,记得要把相应的数据源作为参数传递进去,这样人家事务管理器才能够管理数据源,它才能够控制数据源里的每一条连接。
在配置类中修改内容:
@EnableTransactionManagement
@ComponentScan("test")
@Configuration
public class FirstConfig {
@Bean
public PlatformTransactionManager transactionManager() throws Exception {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public DataSource dataSource () throws Exception {
ComboPooledDataSource dataSource=new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("mypasswordis123");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
return dataSource;
}
/*
这里我就不用mybatis了,直接用一个jdbcTemplate
*/
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){//在这个方法参数中的参数都能从容器中获取
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
}
此时进行测试仍然像之前没配置事务一样出现了相同的错误的,但是数据库中没有插入相应的数据
说明我们的基于注解方式的事务环境已经配置完成!!!!