Spring事务
2019-05-14 本文已影响0人
employeeeee
分布式项目总会面临分布式事务的问题。公司的项目中有多个子系统用户同步信息的问题。最近要研究解决一下出现分布式事务时候的解决办法。把学习的过程记录一下
Spring事务管理的特点
- 提供的统一的API接口 支持不同的资源
- 提供声明式 事务管理
- 方便与spring框架集成
- 多个资源的事务的管理 同步
Spring抽象事务
- PlatformTranscationManager
- TranscationStatus
- TranscationDefinition
Public interface TranscationDefinition(){
int getPropagation Behavior();
int getIsolationLevel();
String getName();
int getTimeOut();
boolean isReadOnly();
}
public interface TranscationStatus extends SavepointManager{
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
boolean isCompleted();
}
启用spring事务可以通过代码的方式 也可以通过注解的方式,在自己的项目中 我用注解的方式更多一些 主要就是简单 不需要写那么的代码 而注解完成事务及回滚也是通过代理的方式来完成的。在本地的测试中 使用
springboot + h2数据库+jpa
的方式 这样会方便一点
jpa在自己写的实际项目中 用的比较少 但是确实是更方便了一点 不需要再xml文件中 进行对应 只要在实体类中 通过@Entity
@column
这种方式 来进行对应 而且对于dao层 mybatis
的dao层 需要一个实现类
而在jpa
中 实现是通过 repository
从名字可以看出来 仓库 在其中 会有很多增删改差的方法 直接调用就可以 不需要自己在实现类中写了
测试的代码参考了慕课网上大漠风老师课程中思路
service中的方法 是使用了通过代码和通过注解两种方式
domain 类
package com.emp.transcationjap.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* Created with IntelliJ IDEA.
* User: employeeeee
* Date: 2019/5/13
* Time: 16:15
* Description: No Description
*/
@Entity(name = "customer")
public class Customer {
@Id
@GeneratedValue
private Long id;
@Column(name = "user_name", length = 6)
private String username;
private String password;
private String role;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
dao层Repository
package com.emp.transcationjap.dao;
import com.emp.transcationjap.domain.Customer;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* Created with IntelliJ IDEA.
* User: employeeeee
* Date: 2019/5/13
* Time: 16:17
* Description: No Description
*/
public interface CustomerRepository extends JpaRepository<Customer,Long> {
}
两个service
package com.emp.transcationjap.service;
import com.emp.transcationjap.dao.CustomerRepository;
import com.emp.transcationjap.domain.Customer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: employeeeee
* Date: 2019/5/13
* Time: 16:21
* Description: No Description
*/
@Service
public class CustomerServiceTcInAnnotation {
@Resource
CustomerRepository customerRepository;
@Transactional
public Customer save(Customer customer) throws Exception{
return customerRepository.save(customer);
}
public List<Customer> saveAll(List<Customer> customerList) throws Exception{
return customerRepository.saveAll(customerList);
}
}
package com.emp.transcationjap.service;
import com.emp.transcationjap.dao.CustomerRepository;
import com.emp.transcationjap.domain.Customer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import javax.annotation.Resource;
/**
* Created with IntelliJ IDEA.
* User: employeeeee
* Date: 2019/5/13
* Time: 16:21
* Description: No Description
*/
@Service
public class CustomerServiceTcInCode {
@Resource
private CustomerRepository customerRepository;
@Resource
private PlatformTransactionManager transactionManager;
public Customer save(Customer customer) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
//隔离机制 所有的操作都会进行排队 对性能的影响比较大
def.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_SERIALIZABLE);
//传播机制
def.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_SUPPORTS);
def.setTimeout(15);
TransactionStatus status = transactionManager.getTransaction(def);
try{
customerRepository.save(customer);
return customer;
}catch (Exception e){
transactionManager.rollback(status);
throw e;
}
}
}
controller
package com.emp.transcationjap.web;
import com.emp.transcationjap.dao.CustomerRepository;
import com.emp.transcationjap.domain.Customer;
import com.emp.transcationjap.service.CustomerServiceTcInAnnotation;
import com.emp.transcationjap.service.CustomerServiceTcInCode;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: employeeeee
* Date: 2019/5/13
* Time: 16:55
* Description: No Description
*/
@RestController
@RequestMapping("/test")
public class CustomerController {
@Resource
private CustomerServiceTcInAnnotation customerServiceTcInAnnotation;
@Resource
private CustomerServiceTcInCode customerServiceTcInCode;
@Resource
private CustomerRepository customerRepository;
@RequestMapping("/code")
public void saveInCode(Customer customer){
customer.setId(1001L);
customer.setUsername("zhou");
customer.setPassword("123456");
customer.setRole("user");
customerServiceTcInCode.save(customer);
}
@RequestMapping("/anno")
public void saveInAnno(Customer customer) throws Exception {
customer.setId(1002L);
customer.setUsername("KrisW");
customer.setPassword("123456");
customer.setRole("user");
customerServiceTcInAnnotation.save(customer);
}
@RequestMapping("/saveAll")
@Transactional
public void saveAll() throws Exception {
Customer customer1 = new Customer();
customer1.setId(1003L);
customer1.setUsername("kunkun");
customer1.setPassword("123456");
customer1.setRole("user");
Customer customer2 = new Customer();
customer2.setId(1004L);
customer2.setUsername("liu");
customer2.setPassword("123456");
customer2.setRole("user");
Customer customer3 = new Customer();
customer3.setId(1005L);
customer3.setUsername("KrisWuuuuu");
customer3.setPassword("123456");
customer3.setRole("user");
customerServiceTcInCode.save(customer1);
customerServiceTcInCode.save(customer2);
customerServiceTcInCode.save(customer3);
}
@RequestMapping("/getAll")
public List<Customer> getAll(){
List<Customer> customerList = customerRepository.findAll();
return customerList;
}
}
然后就在web上进行 测试就OK了
那么有了事务 和 没有事务的区别是什么呢
就是在saveAll的方法中
我让第三个用户的名字超出了 length为6的限制 所以就会报错
然后查询出来的结果 会是这样的
image.png
也就是说 虽然项目报错了 但是前两条数据还是已经加入到了数据库中 这样显然不是我们想要的效果 当我们加上事务时候
就会出现回滚 也就是前两条数据 就不会被添加到数据库中了