自定义事务注解
1.代码整合
1.SQL文件
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`last_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`gender` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`d_id` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of employee
-- ----------------------------
INSERT INTO `employee` VALUES (1, '张华', '123456@qq.com', '1', 1);
INSERT INTO `employee` VALUES (2, '宋祖儿', '129256@qq.com', '0', 1);
INSERT INTO `employee` VALUES (3, '胡歌', '129256@qq.com', '1', 2);
INSERT INTO `employee` VALUES (4, '张华', '1245@126.com', '1', 1);
INSERT INTO `employee` VALUES (5, '张华', '12748574@.123.com', '1', 1);
SET FOREIGN_KEY_CHECKS = 1;
2.maven依赖与配置文件
org.springframework.boot
spring-boot-starter-parent
1.5.10.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-devtools
org.projectlombok
lombok
1.18.6
mysql
mysql-connector-java
runtime
org.springframework
spring-jdbc
4.3.11.RELEASE
org.springframework.boot
spring-boot-starter-aop
org.aspectj
aspectjweaver
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.2
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/spring_cache?&useSSL=false&serverTimezone=UTC&characterEncoding=utf8
username: root
password: 178121
driver-class-name: com.mysql.jdbc.Driver
mybatis:
type-aliases-package: com.itheima.entity
#打印sql语句
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
@MapperScan("com.itheima.mapper")
@SpringBootApplication
public class CustomTransactionApplication {
public static void main(String[] args) {
SpringApplication.run(CustomTransactionApplication.class,args);
}
}
3.持久层文件
import com.itheima.entity.Employee;
import org.apache.ibatis.annotations.*;
public interface EmployeeMapper {
@Insert("INSERT INTO employee(last_name,email,gender,d_id) VALUES(#{lastName},#{email},#{gender},#{dId})")
public void insertEmployee(Employee employee);
}
4.逻辑层
import com.itheima.entity.Employee;
public interface EmployeeService {
public void saveEmp(Employee employee);
}
import com.itheima.annotation.CustomTransaction;
import com.itheima.entity.Employee;
import com.itheima.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
@CustomTransaction
public void saveEmp(Employee employee) {
employeeMapper.insertEmployee(employee);
System.out.println(1/0);
employeeMapper.insertEmployee(employee);
}
}
5.表现层
import com.itheima.entity.Employee;
import com.itheima.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@GetMapping("/hello")
@ResponseBody
public String hello(){
Employee employee = new Employee();
employee.setLastName("张华");
employee.setEmail("12748574@.123.com");
employee.setGender("1");
employee.setDId(1);
employeeService.saveEmp(employee);
return "接口返回成功";
}
}
6.实体类
package com.itheima.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {
private static final long serialVersionUID = 959420245225757073L;
private Integer id;
private String lastName;
private String email;
private String gender; //性别 1男 0女
private Integer dId;
}
7.自定义注解
package com.itheima.annotation;
import java.lang.annotation.documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD,ElementType.TYPE}) //定义注解用在方法上和(类与接口上)
@Retention(RetentionPolicy.RUNTIME) //运行时注解
@documented
public @interface CustomTransaction {
String value() default "";
}
8.工具类
package com.itheima.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
@Component
//@Scope(value = "prototype")
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TransactionUtils {
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
public TransactionStatus init(){
System.out.println("创建事务了...");
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
return transactionStatus;
}
public void commit(TransactionStatus transactionStatus){
System.out.println("提交事务...");
dataSourceTransactionManager.commit(transactionStatus);
}
public void rollback(TransactionStatus transactionStatus){
System.out.println("事务回滚了....");
dataSourceTransactionManager.rollback(transactionStatus);
}
}
9.AOP反射类
package com.itheima.aop;
import com.itheima.util.TransactionUtils;
import com.itheima.annotation.CustomTransaction;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import java.lang.reflect.Method;
@Aspect
@Component
public class CustomTransactionAspect {
@Autowired
private TransactionUtils transactionUtils;
@Pointcut("@annotation(com.itheima.annotation.CustomTransaction)")
public void transactionPointCut() {
}
@Around("transactionPointCut()")
public void around(ProceedingJoinPoint point){
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();//获取到方法对象
//获取到注解类
CustomTransaction annotation = method.getAnnotation(CustomTransaction.class);
if(annotation != null){
System.out.println(annotation.value());//打印注解上value的内容
}
//请求的类名以及方法名
String className = point.getTarget().getClass().getName();
String methodName = signature.getName();
System.out.println("执行的方法为:" + className + "." + methodName + "()");
//开启事务
TransactionStatus transactionStatus = transactionUtils.init();
try {
//执行方法
point.proceed();
//执行成功提交事务
transactionUtils.commit(transactionStatus);
} catch (Throwable throwable) {
//执行方法出错则回滚事务
transactionUtils.rollback(transactionStatus);
return;
}
}
}