一:环境搭建
1:maven依赖
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<!-- aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<!-- 事务 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<!-- jdbc数据访问 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<!-- mysql数据库连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<!-- dhcp连接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
2:项目目录
3:编写Controller、Service、Dao层代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.mote.service.UserService;
@Controller
public class UserController {
@Autowired
private UserService userService;
public void addUser() {
userService.addUser();
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mote.dao.UserDao;
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void addUser() {
userDao.addUser();
//int b = 1/0; //制造异常
}
}
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
@Autowired
private BasicDataSource dataSource;
public void addUser() {
JdbcTemplate template = new JdbcTemplate(dataSource); //创建JDBC模板,操作数据库
String sql = "INSERT INTO debo_role (NAME, AGE) VALUES (?, ?)";
template.update(sql, "super",22); //执行sql语句
}
}
二:声明式事务
1:编写 applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!-- 包扫描:将配置了@Controller、@Service、@Repository、@Compoment注解的组件添加到Spring容器 -->
<context:component-scan base-package="com.mote" />
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<!-- mysql连接驱动jar版本为6.06,驱动类由com.mysql.jdbc.Driver变为com.mysql.cj.jdbc.Driver -->
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://114.215.83.3:3306/debo" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>
<!-- 定义事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置事务特性 -->
<tx:advice id="adviceRef" transaction-manager="transactionManager">
<tx:attributes>
<!-- add*:匹配以add为开头的所有方法,符合此命名规则的方法作为一个事务。
REQUIRED:若当前没有事务,就新建一个事务,若存在一个事务中,加入该事务中。这是最常见的选择 -->
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="upd*" propagation="REQUIRED" />
<tx:method name="get*" propagation="REQUIRED" />
<tx:method name="*" read-only="true" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<!-- 配置切点(需要加事务类、方法),并切入事务 -->
<aop:config>
<!-- 配置事务切点 -->
<aop:pointcut id="cutPoint"
expression="execution(public * com.mote.service.*.*(..))" />
<!-- 切入事务 -->
<aop:advisor pointcut-ref="cutPoint" advice-ref="adviceRef" />
</aop:config>
</beans>
2:测试代码
@Test
public void testXml() {
// 创建容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从容器中获取bean
UserController userController = context.getBean(UserController.class);
// 调用方法
userController.addUser();
}
结果显示:若Service层出现异常,事务回滚成功
三:纯注解
1:编写配置类
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement// 开启基于注解的事务管理功能
@Configuration// 标注这是一个配置类
@ComponentScan("com.mote")// 包扫描,将@Controller,@Service,@Repostory,@Compoment组件注册到Spring容器
public class MainConfig {
@Bean// 配置数据源
public BasicDataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl("jdbc:mysql://114.215.83.3:3306/debo");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
@Bean// 配置事务管理器
public DataSourceTransactionManager dataSourceManager(
BasicDataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
2:修改UserDao,添加@Transactional
@Repository
public class UserDao {
@Autowired
private BasicDataSource dataSource;
@Transactional //标注这是一个事务方法
public void addUser() {
JdbcTemplate template = new JdbcTemplate(dataSource); //创建JDBC模板,操作数据库
String sql = "INSERT INTO user (NAME, AGE) VALUES (?, ?)";
template.update(sql, "super",22); //执行sql语句
}
}
3:测试
@Test
public void test() {
// 创建容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
// 从容器中获取bean
UserController userController = context.getBean(UserController.class);
// 调用方法
userController.addUser();
}
tip 1:@Transactional标注在类上面, 表示类中所有方法都进行事物控制
而当类中某些方法不需要添加事务时:@Transactional(propagation =Propagation.NOT_SUPPORTED)
@Repository
@Transactional
public class UserDao {
@Autowired
private BasicDataSource dataSource;
@Transactional(propagation =Propagation.NOT_SUPPORTED)
public void addUser() {
JdbcTemplate template = new JdbcTemplate(dataSource); //创建JDBC模板,操作数据库
String sql = "INSERT INTO debo_role (NAME, COMPANY_ID, DESCRIPTION) VALUES (?, ?, ?)";
template.update(sql, "super",1,"管理员"); //执行sql语句
}
}
tip 2:切点表达式书写规则
表达式模板:execution(修饰符 返回值 包.类.方法名(参数) throws异常)
修饰符,一般省略
public 公共方法
* 任意
返回值,不能省略
void 返回没有值
String 返回值字符串
* 任意
包
com.zby.service 固定包
com.zby.oa.*.service oa包下面子包 (例如:com.zby.oa.flow.service)
com.zby.oa.. oa包下面的所有子包(含自己)
com.zby.oa.*.service.. oa包下面任意子包,固定目录service,service目录任意包
类
UserServiceImpl 指定类
*Impl 以Impl结尾
User* 以User开头
* 任意
方法名,不能省略
addUser 固定方法
add* 以add开头
*Do 以Do结尾
* 任意
(参数)
() 无参
(int) 一个整型
(int ,int) 两个
(..) 参数任意
throws ,可省略,一般不写