|
|
|
@ -3,18 +3,22 @@ package cn.estsh.i3plus.core.apiservice.serviceimpl.busi;
|
|
|
|
|
import cn.estsh.i3plus.core.api.iservice.busi.ITestTransService;
|
|
|
|
|
import cn.estsh.i3plus.core.apiservice.dao.ITestTransDao;
|
|
|
|
|
import cn.estsh.i3plus.core.apiservice.dao.ITransDaoSec;
|
|
|
|
|
import cn.estsh.i3plus.pojo.platform.bean.SysDepartment;
|
|
|
|
|
import cn.estsh.i3plus.pojo.platform.bean.SysTool;
|
|
|
|
|
import cn.estsh.i3plus.pojo.platform.bean.SysUser;
|
|
|
|
|
import cn.estsh.i3plus.pojo.platform.bean.SysUserInfo;
|
|
|
|
|
import cn.estsh.i3plus.pojo.platform.bean.*;
|
|
|
|
|
import cn.estsh.i3plus.pojo.platform.repository.SysDepartmentRepository;
|
|
|
|
|
import cn.estsh.i3plus.pojo.platform.repository.SysUserInfoRepository;
|
|
|
|
|
import cn.estsh.i3plus.pojo.platform.repository.SysUserRepository;
|
|
|
|
|
import com.netflix.discovery.converters.Auto;
|
|
|
|
|
import cn.estsh.i3plus.pojo.platform.repository.TestTransUserRepository;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.data.jpa.repository.Lock;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.transaction.TransactionDefinition;
|
|
|
|
|
import org.springframework.transaction.annotation.Isolation;
|
|
|
|
|
import org.springframework.transaction.annotation.Propagation;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
|
|
import javax.persistence.LockModeType;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Random;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @Description :
|
|
|
|
@ -41,6 +45,9 @@ public class TestTransService implements ITestTransService {
|
|
|
|
|
@Autowired
|
|
|
|
|
private ITransDaoSec testTransSecDao;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private TestTransUserRepository testTransUserRepository;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void testListTran(int type,String name) {
|
|
|
|
|
if(type == 1) {
|
|
|
|
@ -130,8 +137,380 @@ public class TestTransService implements ITestTransService {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Transactional(propagation=Propagation.NESTED,isolation=Isolation.DEFAULT,readOnly = false,rollbackFor = Exception.class)
|
|
|
|
|
@Lock(value = LockModeType.PESSIMISTIC_WRITE)
|
|
|
|
|
@Override
|
|
|
|
|
public void testTran() {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<TestTransUser> listRead() {
|
|
|
|
|
|
|
|
|
|
List<TestTransUser> ul = testTransUserRepository.list();
|
|
|
|
|
testTransUserRepository.flush();
|
|
|
|
|
System.out.println("查询333数量:" + ul);
|
|
|
|
|
|
|
|
|
|
return ul;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void write() {
|
|
|
|
|
Random ran = new Random(10000);
|
|
|
|
|
TestTransUser u = new TestTransUser();
|
|
|
|
|
u.setName("na2me" + ran.nextInt(100));
|
|
|
|
|
u.setSalary(ran.nextDouble());
|
|
|
|
|
System.out.println("插入对象:" + u);
|
|
|
|
|
|
|
|
|
|
u = testTransUserRepository.insert(u);
|
|
|
|
|
System.out.println("插入对象:" + u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void transReadWrite() {
|
|
|
|
|
System.out.println("===写事务:查询后插入===");
|
|
|
|
|
listRead();
|
|
|
|
|
write();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void readWrite() {
|
|
|
|
|
System.out.println("===读事务:查询后插入===");
|
|
|
|
|
listRead();
|
|
|
|
|
write();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void updateTestTransUser(String name, double salary) {
|
|
|
|
|
TestTransUser u = testTransUserRepository.getByProperty("name",name);
|
|
|
|
|
u.setSalary(salary);
|
|
|
|
|
|
|
|
|
|
testTransUserRepository.update(u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void insertTestTransUser(String name, double salary) {
|
|
|
|
|
TestTransUser u = new TestTransUser();
|
|
|
|
|
u.setName(name);
|
|
|
|
|
u.setSalary(salary);
|
|
|
|
|
|
|
|
|
|
u = testTransUserRepository.insert(u);
|
|
|
|
|
System.out.println("插入对象:" + u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void deleteTestTransUser(String name) {
|
|
|
|
|
testTransUserRepository.deleteByProperty("name",name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(propagation = Propagation.NEVER) //没有事务
|
|
|
|
|
public void updateLost(String name, int time, boolean execp) {
|
|
|
|
|
TestTransUser u = testTransUserRepository.getByProperty("name",name);
|
|
|
|
|
u.setSalary(u.getSalary() + 100);
|
|
|
|
|
|
|
|
|
|
testTransUserRepository.update(u);
|
|
|
|
|
|
|
|
|
|
if(time > 0){
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(time);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(execp){
|
|
|
|
|
throw new RuntimeException("手动异常");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(propagation = Propagation.REQUIRED) //默认事务
|
|
|
|
|
public void updateLostTrans(String name,double salary, int time, boolean execp) {
|
|
|
|
|
TestTransUser u = testTransUserRepository.getByProperty("name",name);
|
|
|
|
|
u.setSalary(salary);
|
|
|
|
|
|
|
|
|
|
testTransUserRepository.update(u);
|
|
|
|
|
|
|
|
|
|
if(time > 0){
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(time);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(execp){
|
|
|
|
|
throw new RuntimeException("手动异常");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void writeDirtyA(long id) {
|
|
|
|
|
TestTransUser u = testTransUserRepository.getById(id);
|
|
|
|
|
System.out.println("脏读开始,对象值:" + u.getSalary());
|
|
|
|
|
u.setSalary(u.getSalary() + 666);
|
|
|
|
|
|
|
|
|
|
testTransUserRepository.update(u);
|
|
|
|
|
System.out.println("脏读数据已更新:" + u.getSalary());
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(3000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(u.getSalary() > 0){
|
|
|
|
|
throw new RuntimeException("手动抛出,数据回滚。");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
|
|
|
|
|
public void writeDirtyB(long id) {
|
|
|
|
|
TestTransUser u = testTransUserRepository.getById(id);
|
|
|
|
|
System.out.println("第一次查询:" + u);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(3000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
u = testTransUserRepository.getById(id);
|
|
|
|
|
System.out.println("第二次查询:" + u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void writeRepeatA(long id) {
|
|
|
|
|
TestTransUser u = testTransUserRepository.getById(id);
|
|
|
|
|
System.out.println("不可重复读开始,对象值:" + u.getSalary());
|
|
|
|
|
u.setSalary(u.getSalary() + 666);
|
|
|
|
|
|
|
|
|
|
testTransUserRepository.update(u);
|
|
|
|
|
System.out.println("不可重复读数据已更新:" + u.getSalary());
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(5000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
System.out.println("不可重复读已提交数据!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void writeRepeatB(long id) {
|
|
|
|
|
TestTransUser u = testTransUserRepository.getById(id);
|
|
|
|
|
System.out.println("第一次查询:" + u);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(5000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
u = testTransUserRepository.getById(id);
|
|
|
|
|
System.out.println("第二次查询:" + u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
//@Transactional(isolation = Isolation.SERIALIZABLE)
|
|
|
|
|
public void writePhantomA(long id,boolean listOrDelete) {
|
|
|
|
|
int count = testTransUserRepository.listCount();
|
|
|
|
|
System.out.println("幻读开始,记录数量:" + count);
|
|
|
|
|
|
|
|
|
|
if(listOrDelete){
|
|
|
|
|
TestTransUser u = new TestTransUser();
|
|
|
|
|
u.setName("testPhantom");
|
|
|
|
|
u.setSalary(500d);
|
|
|
|
|
|
|
|
|
|
u = testTransUserRepository.insert(u);
|
|
|
|
|
System.out.println("插入对象:" + u);
|
|
|
|
|
|
|
|
|
|
u.setSalary(u.getSalary() * 10);
|
|
|
|
|
testTransUserRepository.update(u);
|
|
|
|
|
testTransUserRepository.flush();
|
|
|
|
|
System.out.println("update对象:" + u);
|
|
|
|
|
}else{
|
|
|
|
|
testTransUserRepository.deleteById(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(5000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
if(count > 0){
|
|
|
|
|
throw new RuntimeException("幻读抛出异常");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
count = testTransUserRepository.listCount();
|
|
|
|
|
System.out.println("幻读结束,记录数量:" + count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void testListTranSec(int type,String name) {
|
|
|
|
|
@Transactional(isolation = Isolation.SERIALIZABLE)
|
|
|
|
|
public void writePhantomB() {
|
|
|
|
|
int count = testTransUserRepository.listCount();
|
|
|
|
|
System.out.println("幻读另一个事务开始,记录数量:" + count);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(3000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
count = testTransUserRepository.listCount();
|
|
|
|
|
System.out.println("幻读另一个事务结束,记录数量:" + count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(propagation = Propagation.REQUIRED)
|
|
|
|
|
public void writeRequireNew() {
|
|
|
|
|
int count = testTransUserRepository.listCount();
|
|
|
|
|
System.out.println("插入前数量:" + count);
|
|
|
|
|
insertTestTransUser("require new",100);
|
|
|
|
|
|
|
|
|
|
count = testTransUserRepository.listCount();
|
|
|
|
|
System.out.println("插入后数量:" + count);
|
|
|
|
|
|
|
|
|
|
TestTransUser u = testTransUserRepository.getByProperty("name","require new");
|
|
|
|
|
System.out.println("查询对象:" + u);
|
|
|
|
|
|
|
|
|
|
writeRequireNewMore();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
|
|
|
|
public void writeRequireNewMore() {
|
|
|
|
|
int count = testTransUserRepository.listCount();
|
|
|
|
|
System.out.println("【子事务】查询数量:" + count);
|
|
|
|
|
|
|
|
|
|
TestTransUser u = testTransUserRepository.getByProperty("name","require new");
|
|
|
|
|
System.out.println("【子事务】查询对象:" + u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(propagation = Propagation.NEVER)
|
|
|
|
|
public void writeTransMandatory() {
|
|
|
|
|
int count = testTransUserRepository.listCount();
|
|
|
|
|
System.out.println("数量:" + count);
|
|
|
|
|
|
|
|
|
|
writeTransMandatoryMore();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(propagation = Propagation.MANDATORY)
|
|
|
|
|
public void writeTransMandatoryMore() {
|
|
|
|
|
int count = testTransUserRepository.listCount();
|
|
|
|
|
System.out.println("【子事务】查询数量:" + count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
//@Transactional(isolation=Isolation.REPEATABLE_READ)
|
|
|
|
|
//@Lock(value = LockModeType.WRITE)
|
|
|
|
|
public void writeOptimisticA(long id,int type) {
|
|
|
|
|
if(type == 1){
|
|
|
|
|
//脏读
|
|
|
|
|
writeDirtyA(id);
|
|
|
|
|
}else if(type == 2){
|
|
|
|
|
writeRepeatA(id);
|
|
|
|
|
}else if(type == 3){
|
|
|
|
|
writePhantomA(id,true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void writeOptimisticB(long id,int type) {
|
|
|
|
|
if(type == 1){
|
|
|
|
|
//脏读
|
|
|
|
|
writeDirtyB(id);
|
|
|
|
|
}else if(type == 2){
|
|
|
|
|
writeRepeatB(id);
|
|
|
|
|
}else if(type == 3){
|
|
|
|
|
writePhantomB();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
//@Transactional(isolation=Isolation.REPEATABLE_READ)
|
|
|
|
|
//@Lock(value = LockModeType.PESSIMISTIC_WRITE)
|
|
|
|
|
public void writePessimisticA(long id,int type) {
|
|
|
|
|
if(type == 1){
|
|
|
|
|
//脏读
|
|
|
|
|
writeDirtyA(id);
|
|
|
|
|
}else if(type == 2){
|
|
|
|
|
writeRepeatA(id);
|
|
|
|
|
}else if(type == 3){
|
|
|
|
|
writePhantomA(id,true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void writePessimisticB(long id,int type) {
|
|
|
|
|
if(type == 1){
|
|
|
|
|
//脏读
|
|
|
|
|
writeDirtyB(id);
|
|
|
|
|
}else if(type == 2){
|
|
|
|
|
writeRepeatB(id);
|
|
|
|
|
}else if(type == 3){
|
|
|
|
|
writePhantomB();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void writePatternWrong(long id,double salary) {
|
|
|
|
|
System.out.println("==事务并发问题==");
|
|
|
|
|
TestTransUser u = testTransUserRepository.getById(id);
|
|
|
|
|
System.out.println("更新前:" + u.getName() + "," + u.getSalary());
|
|
|
|
|
u.setSalary(salary);
|
|
|
|
|
System.out.println("更新后:" + u.getName() + "," + u.getSalary());
|
|
|
|
|
|
|
|
|
|
testTransUserRepository.update(u);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(5000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public synchronized void writePatternSynchron(long id,double salary) {
|
|
|
|
|
System.out.println("==添加线程锁==");
|
|
|
|
|
writePatternWrong(id,salary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void writePatternOpti(long id,double salary) {
|
|
|
|
|
System.out.println("==乐观锁==");
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
writePatternWrong(id, salary);
|
|
|
|
|
}catch(Exception e){
|
|
|
|
|
System.out.println("在此处进行再次处理");
|
|
|
|
|
System.out.println("乐观锁抛出异常:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void writePatternPessi(long id,double salary) {
|
|
|
|
|
writePatternWrong(id, salary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void writePatternParamUpdate(long id,double salary) {
|
|
|
|
|
System.out.println("==通过更新属性值保证事务==");
|
|
|
|
|
|
|
|
|
|
TestTransUser u = testTransUserRepository.getById(id);
|
|
|
|
|
System.out.println("更新前:" + u.getName() + "," + u.getSalary());
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep(5000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//update TestTransUser set salary = salary + :salary where name=:name;
|
|
|
|
|
testTransUserRepository.updateByPropertiesWithVal("id",id,"salary",salary);
|
|
|
|
|
System.out.println("5秒后更新:" + u.getName() + "," + u.getSalary());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|