事务调整及demo

yun-zuoyi
alwaysfrin 6 years ago
parent 3eb83cd6a0
commit 3fb4018626

@ -16,25 +16,25 @@ public interface ISystemInitService {
*
*/
@ApiOperation(value = "初始化加载所有数据",notes = "初始化加载所有数据")
void loadAll();
void putAndLoadAll();
/**
*
*/
@ApiOperation(value = "加载系统配置",notes = "加载系统配置")
void loadSysConfig();
void putAndLoadSysConfig();
/**
*
*/
@ApiOperation(value = "加载字典数据",notes = "加载字典数据")
void loadSysDictionary();
void putAndLoadSysDictionary();
/**
*
*/
@ApiOperation(value = "加载语言数据",notes = "加载语言数据")
void loadSysLocaleLanguage();
void putAndLoadSysLocaleLanguage();
/**
*

@ -6,6 +6,7 @@ import cn.estsh.i3plus.pojo.base.common.Pager;
import cn.estsh.i3plus.pojo.platform.bean.SysUser;
import io.swagger.annotations.ApiOperation;
import javax.transaction.Transactional;
import java.util.List;
/**
@ -25,4 +26,8 @@ public interface ITestService {
@ApiOperation(value = "in条件封装查询")
List<SysUser> querySysUserByPack(DdlPackBean packBean);
@ApiOperation(value = "读写分离测试写")
@Transactional
void write();
}

@ -1,6 +1,11 @@
package cn.estsh.i3plus.core.api.iservice.busi;
import cn.estsh.i3plus.pojo.platform.bean.TestTransUser;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @Description :
@ -15,5 +20,106 @@ public interface ITestTransService {
void testListTran(int type,String name);
@ApiOperation(value = "自定义dao混用")
void testListTranSec(int type,String name);
void testTran();
/******************** 读写分离部分测试 **********************/
@ApiOperation(value = "读写分离测试读")
@Transactional
List<TestTransUser> listRead();
@ApiOperation(value = "读写分离测试写")
@Transactional
void write();
@ApiOperation(value = "读写分离测试读写-写事务")
void transReadWrite();
@ApiOperation(value = "读写分离测试读写-读事务")
void readWrite();
/******************** 事务机制部分demo **********************/
//@ApiOperation(value = "开始事务执行过程中休眠seconds秒")
//void readTransTest(int seconds);
//void testListTranSec(int type,String name);
@ApiOperation(value = "更新对象")
void updateTestTransUser(String name, double salary);
@ApiOperation(value = "新增对象")
void insertTestTransUser(String name,double salary);
/**
* type == 1
* type == 2 name
*/
@ApiOperation(value = "删除对象")
void deleteTestTransUser(String name);
@ApiOperation(value = "第一类丢失更新")
void updateLost(String name, int time, boolean execp);
@ApiOperation(value = "第二类丢失更新")
void updateLostTrans(String name,double salary, int time, boolean execp);
@ApiOperation(value = "脏读模拟A")
void writeDirtyA(long id);
@ApiOperation(value = "脏读模拟B")
void writeDirtyB(long id);
@ApiOperation(value = "不可重复读A")
void writeRepeatA(long id);
@ApiOperation(value = "不可重复读B")
void writeRepeatB(long id);
@ApiOperation(value = "幻读模拟A")
void writePhantomA(long id,boolean listOrDelete);
@ApiOperation(value = "幻读模拟B")
void writePhantomB();
@ApiOperation(value = "创建新事务")
void writeRequireNew();
@ApiOperation(value = "创建新事务-子方法")
void writeRequireNewMore();
@ApiOperation(value = "没有事务抛出异常")
void writeTransMandatory();
@ApiOperation(value = "没有事务抛出异常-子方法")
void writeTransMandatoryMore();
@ApiOperation(value = "乐观锁 Optimistic lockA")
void writeOptimisticA(long id,int type);
@ApiOperation(value = "乐观锁 Optimistic lockB")
void writeOptimisticB(long id,int type);
@ApiOperation(value = "悲观锁 pessimistic lockA")
void writePessimisticA(long id,int type);
@ApiOperation(value = "悲观锁 pessimistic lockB")
void writePessimisticB(long id,int type);
@ApiOperation(value = "常见事务处理-可能出现并发问题")
void writePatternWrong(long id,double salary);
@ApiOperation(value = "事务模式-线程锁")
void writePatternSynchron(long id,double salary);
@ApiOperation(value = "事务模式-乐观锁")
void writePatternOpti(long id,double salary);
@ApiOperation(value = "事务模式-悲观锁")
void writePatternPessi(long id,double salary);
@ApiOperation(value = "属性更新")
void writePatternParamUpdate(long id,double salary);
}

@ -42,7 +42,7 @@ public class AppStartSystemInit implements CommandLineRunner {
packIMPPResources();
LOGGER.info("【IMPP-Core开始加载基础信息...】");
systemInitService.loadAll();
systemInitService.putAndLoadAll();
}
/**

@ -1,18 +1,27 @@
package cn.estsh.i3plus.core.apiservice.controller;
import cn.estsh.i3plus.core.api.iservice.busi.ITestService;
import cn.estsh.i3plus.core.api.iservice.busi.ITestTransService;
import cn.estsh.i3plus.platform.common.util.PlatformConstWords;
import cn.estsh.i3plus.pojo.platform.bean.TestTransUser;
import cn.estsh.impp.framework.base.controller.CoreBaseController;
import cn.estsh.impp.framework.boot.datasource.DataSourceConfig;
import cn.estsh.impp.framework.boot.datasource.DynamicDataSourceHolder;
import cn.estsh.impp.framework.boot.util.ResultBean;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.persistence.LockModeType;
import java.util.List;
/**
* @Description : entityManager
* @Reference :
@ -22,13 +31,16 @@ import org.springframework.web.bind.annotation.RestController;
**/
@RestController
@Api(description = "对事务以及entityManager的操作演示")
@RequestMapping(PlatformConstWords.BASE_URL + "/demo-trans")
@RequestMapping("/demo-trans")
public class DemoTransactionController extends CoreBaseController {
private static final Logger LOGGER = LoggerFactory.getLogger(DemoTransactionController.class);
@Autowired
private ITestTransService transService;
@Autowired
private ITestService testService;
/**
* dao
*
@ -45,17 +57,350 @@ public class DemoTransactionController extends CoreBaseController {
}
/**
* dao2
*
*
* @param type
* @param name
* @return
*/
@PostMapping("/test2")
@ApiOperation(value = "dao混合调用2")
public ResultBean transTest2(int type, String name) {
transService.testListTranSec(type, name);
@PostMapping("/test-dynamic-datasource")
@ApiOperation(value = "测试多数据源切换")
public ResultBean testDynamicDataSource(int type) {
//多服务调用
startMultiService();
if(type == 1){
System.out.println("====先查后插入====");
List<TestTransUser> uList = transService.listRead();
System.out.println("对象总数:" + uList.size());
System.out.println("开始插入");
transService.write();
uList = transService.listRead();
System.out.println("再次查询:" + uList.size());
}else if(type == 2){
System.out.println("====先插入后查====");
System.out.println("开始插入");
transService.write();
List<TestTransUser> uList = transService.listRead();
System.out.println("对象总数:" + uList.size());
if(uList.size() > 0){
throw new RuntimeException("111");
}
}else if(type == 3){
System.out.println("====先查后插入====");
List<TestTransUser> uList = transService.listRead();
System.out.println("对象总数:" + uList.size());
System.out.println("开始插入");
testService.write();
uList = transService.listRead();
System.out.println("再次查询:" + uList.size());
}
return ResultBean.success("测试成功");
}
/**
* Controller
*
* @return
*/
@PostMapping("/test-dynamic-datasource-more")
@ApiOperation(value = "测试多数据源切换")
public ResultBean testDynamicDataSourceWithController(boolean withMulti) {
if(withMulti) {
//多服务调用
startMultiService();
}
//读
readWriteTransactionTest(1);
//写
readWriteTransactionTest(2);
return ResultBean.success("测试成功");
}
/**
* -
* @return
*/
@PostMapping("/read-write-test")
@ApiOperation(value = "读写分离-事务测试")
public ResultBean readWriteTransactionTest(@RequestParam("testType") int testType) {
if(testType == 1) {
//读
List<TestTransUser> uList = transService.listRead();
System.out.println("对象总数:" + uList.size());
for (TestTransUser u : uList){
System.out.println(u);
}
}else if(testType == 2) {
//写
transService.write();
}else if(testType == 3) {
//读写(写事务)
transService.transReadWrite();
}else if(testType == 4) {
//读写(写事务)
transService.readWrite();
}
return ResultBean.success("测试成功");
}
/******************* 事务并发出现的问题*******************/
/**
*
* @param name name
* @param time
* @param execp
* @return
*/
@PostMapping("/update-lost")
@ApiOperation(value = "第一类丢失更新")
public ResultBean updateLost1(String name,int time,boolean execp) {
transService.updateLost(name,time,execp);
return ResultBean.success("幻读模拟结束");
}
/**
*
* @return
*/
@PostMapping("/update-lost-trans")
@ApiOperation(value = "第二类丢失更新")
public ResultBean updateLostTrans(String name,double salary,int time,boolean execp) {
transService.updateLostTrans(name,salary,time,execp);
return ResultBean.success("第二类丢失更新结束");
}
/**
*
* @return
*/
@PostMapping("/trans-dirty-a")
@ApiOperation(value = "脏读模拟A")
public ResultBean transDirtyA(long id) {
try{
transService.writeDirtyA(id);
}catch(Exception e){
System.out.println(e.getMessage());
}
return ResultBean.success("脏读模拟A结束");
}
/**
*
* @return
*/
@PostMapping("/trans-dirty-b")
@ApiOperation(value = "脏读模拟B")
public ResultBean transDirtyB(long id) {
transService.writeDirtyB(id);
return ResultBean.success("脏读模拟B结束");
}
/**
* A
* @return
*/
@PostMapping("/trans-repeat-a")
@ApiOperation(value = "不可重复读A")
public ResultBean transRepeatA(long id) {
transService.writeRepeatA(id);
return ResultBean.success("不可重复读A结束");
}
/**
* B
* @return
*/
@PostMapping("/trans-repeat-b")
@ApiOperation(value = "不可重复读B")
public ResultBean transRepeatB(long id) {
transService.writeRepeatB(id);
return ResultBean.success("不可重复读B结束");
}
/**
*
* @return
*/
@PostMapping("/trans-phantom-a")
@ApiOperation(value = "幻读模拟A")
public ResultBean transPhantomA(long id,boolean listOrDelete) {
try {
transService.writePhantomA(id, listOrDelete);
}catch(Exception e){
System.out.println("幻读异常:" + e.getMessage());
}
return ResultBean.success("幻读模拟A结束");
}
/**
*
* @return
*/
@PostMapping("/trans-phantom-b")
@ApiOperation(value = "幻读模拟B")
public ResultBean transPhantomB() {
transService.writePhantomB();
return ResultBean.success("幻读模拟B结束");
}
/********************* 事务传播 *******************/
/**
* -
* @return
*/
@PostMapping("/trans-require-new")
@ApiOperation(value = "创建新事务")
public ResultBean transRequireNew() {
transService.writeRequireNew();
return ResultBean.success("require-new结束");
}
/**
* -mandatory
* @return
*/
@PostMapping("/trans-mandatory")
@ApiOperation(value = "没有事务抛出异常")
public ResultBean transMandatory() {
transService.writeTransMandatory();
return ResultBean.success("mandatory结束");
}
/******************* 事务隔离级别 *******************/
//调用事务出现的问题,打开事务注释
/********************* 乐观锁 Optimistic lock *******************/
/**
* A
* @return
*/
@PostMapping("/trans-optimistic-a")
@ApiOperation(value = "乐观锁 Optimistic lockA")
public ResultBean transOptimisticA(long id,int type) {
transService.writeOptimisticA(id,type);
return ResultBean.success("乐观锁 Optimistic lockA结束");
}
/**
* B
* @return
*/
@PostMapping("/trans-optimistic-b")
@ApiOperation(value = "乐观锁 Optimistic lockB")
public ResultBean transOptimisticB(long id,int type) {
transService.writeOptimisticB(id,type);
return ResultBean.success("乐观锁 Optimistic lockB结束");
}
/********************* 悲观锁 Pessimistic Lock *******************/
/**
* A
* @return
*/
@PostMapping("/trans-pessimistic-a")
@ApiOperation(value = "悲观锁 pessimistic lockA")
public ResultBean transPessimisticA(long id,int type) {
transService.writePessimisticA(id,type);
return ResultBean.success("悲观锁 pessimistic lockA结束");
}
/**
* B
* @return
*/
@PostMapping("/trans-pessimistic-b")
@ApiOperation(value = "悲观锁 pessimistic lockB")
public ResultBean transPessimisticB(long id,int type) {
transService.writePessimisticB(id,type);
return ResultBean.success("悲观锁 pessimistic lockB结束");
}
/********************* 事务设计 *******************/
/**
*
* @return
*/
@PostMapping("/trans-pattern-wrong")
@ApiOperation(value = "常见事务处理(可能出现并发问题)")
public ResultBean transPatternWrong(long id,double salary) {
transService.writePatternWrong(id,salary);
return ResultBean.success("常见事务处理");
}
/**
* 线
* @return
*/
@PostMapping("/trans-pattern-synchronized")
@ApiOperation(value = "事务模式-线程锁")
public ResultBean transPatternSynchron(long id,double salary) {
transService.writePatternSynchron(id,salary);
return ResultBean.success("事务模式-线程锁");
}
/**
*
* @return
*/
@PostMapping("/trans-pattern-opti")
@ApiOperation(value = "事务模式-乐观锁")
public ResultBean transPatternOpti(long id,double salary) {
transService.writePatternOpti(id,salary);
return ResultBean.success("事务模式-乐观锁");
}
/**
*
* @return
*/
@PostMapping("/trans-pattern-pessi")
@ApiOperation(value = "事务模式-悲观锁")
public ResultBean transPatternPessi(long id,double salary) {
transService.writePatternPessi(id,salary);
return ResultBean.success("事务模式-悲观锁");
}
/**
*
* @return
*/
@PostMapping("/trans-pattern-param-update")
@ApiOperation(value = "事务模式-属性更新")
public ResultBean transPatternParamUpdate(long id,double salary) {
transService.writePatternParamUpdate(id,salary);
return ResultBean.success("事务模式-属性更新");
}
}

@ -219,7 +219,7 @@ public class WhiteController extends CoreBaseController {
// 从缓存获取语言信息
Map<Object, Object> resourceMap = redisRes.getHashMap(CommonConstWords.REDIS_PREFIX_CACHE_LANGUAGE + languageCode);
if (resourceMap == null || resourceMap.size() == 0) {
systemInitService.loadSysLocaleLanguage();
systemInitService.putAndLoadSysLocaleLanguage();
resourceMap = redisRes.getHashMap(CommonConstWords.REDIS_PREFIX_CACHE_LANGUAGE + languageCode);
}

@ -75,7 +75,7 @@ public class SysConfigController extends CoreBaseController {
ConvertBean.modelInitialize(sysConfig,user);
sysConfigService.insertSysConfig(sysConfig);
systemInitService.loadSysConfig();
systemInitService.putAndLoadSysConfig();
return ResultBean.success("操作成功").setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode());
}catch(ImppBusiException busExcep){
return ResultBean.fail(busExcep);
@ -105,7 +105,7 @@ public class SysConfigController extends CoreBaseController {
}
sysConfigService.deleteSysConfigById(Long.parseLong(idStr));
systemInitService.loadSysConfig();
systemInitService.putAndLoadSysConfig();
return ResultBean.success("操作成功").setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode());
}catch(ImppBusiException busExcep){
return ResultBean.fail(busExcep);
@ -137,7 +137,7 @@ public class SysConfigController extends CoreBaseController {
ConvertBean.modelUpdate(sysConfig,user);
sysConfigService.updateSysConfig(sysConfig);
systemInitService.loadSysConfig();
systemInitService.putAndLoadSysConfig();
return ResultBean.success("操作成功").setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode());
}catch(ImppBusiException busExcep){
return ResultBean.fail(busExcep);
@ -268,7 +268,7 @@ public class SysConfigController extends CoreBaseController {
ValidatorBean.checkNotNull(value,"值不能为空");
sysConfigService.updateSysConfigByCode(code,value);
systemInitService.loadSysConfig();
systemInitService.putAndLoadSysConfig();
return ResultBean.success("操作成功").setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode());
}catch(ImppBusiException busExcep){
return ResultBean.fail(busExcep);

@ -92,7 +92,7 @@ public class SysLocaleLanguageController extends CoreBaseController {
sysLocaleLanguageService.updateSysLocaleLanguage(sysLocaleLanguage);
// 重新加载资源
systemInitService.loadSysLocaleLanguage();
systemInitService.putAndLoadSysLocaleLanguage();
return ResultBean.success("操作成功").setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode());
}catch(ImppBusiException busExcep){
return ResultBean.fail(busExcep);
@ -210,7 +210,7 @@ public class SysLocaleLanguageController extends CoreBaseController {
sysLocaleLanguageService.deleteSysLocaleLanguageByIds(StringTool.getArrayLong(idsStr));
// 重新加载语言资源
systemInitService.loadSysLocaleLanguage();
systemInitService.putAndLoadSysLocaleLanguage();
return ResultBean.success("操作成功").setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode());
}catch(ImppBusiException busExcep){
return ResultBean.fail(busExcep);

@ -198,7 +198,7 @@ public class SysLocaleResourceController extends CoreBaseController {
sysLocaleResourceService.deleteSysLocaleResourceByIds(StringTool.getArrayLong(idsStr));
// 重新加载资源
systemInitService.loadSysLocaleLanguage();
systemInitService.putAndLoadSysLocaleLanguage();
return ResultBean.success("操作成功").setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode());
}catch(ImppBusiException busExcep){
return ResultBean.fail(busExcep);
@ -227,7 +227,7 @@ public class SysLocaleResourceController extends CoreBaseController {
sysLocaleResourceService.insertSysLocaleResourceList(sysLocaleResourcesList);
// 重新加载资源
systemInitService.loadSysLocaleLanguage();
systemInitService.putAndLoadSysLocaleLanguage();
return ResultBean.success("操作成功").setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode());
}catch(ImppBusiException busExcep){
return ResultBean.fail(busExcep);

@ -51,16 +51,16 @@ public class SystemInitService implements ISystemInitService {
@Override
@ApiOperation(value = "初始化加载所有数据",notes = "初始化加载所有数据")
public void loadAll() {
public void putAndLoadAll() {
type = ImppEnumUtil.SYS_CACHE_TYPE.REDIS.getValue();
loadSysConfig();
loadSysDictionary();
loadSysLocaleLanguage();
putAndLoadSysConfig();
putAndLoadSysDictionary();
putAndLoadSysLocaleLanguage();
}
@Override
@ApiOperation(value = "加载系统配置",notes = "加载系统配置")
public void loadSysConfig() {
public void putAndLoadSysConfig() {
String redisKey = null;
List<SysConfig> list = configRDao.findAll();
for (SysConfig config : list) {
@ -74,7 +74,7 @@ public class SystemInitService implements ISystemInitService {
@Override
@ApiOperation(value = "加载字典数据",notes = "加载字典数据")
public void loadSysDictionary() {
public void putAndLoadSysDictionary() {
try {
List<SysDictionary> list = dictionaryRDao.findAll();
if(list != null && list.size() > 0){
@ -99,7 +99,7 @@ public class SystemInitService implements ISystemInitService {
@Override
@ApiOperation(value = "加载语言数据",notes = "加载语言数据")
public void loadSysLocaleLanguage() {
public void putAndLoadSysLocaleLanguage() {
// Redis 缓存
if(type == ImppEnumUtil.SYS_CACHE_TYPE.REDIS.getValue()){
/**

@ -13,7 +13,9 @@ import cn.estsh.i3plus.pojo.base.tool.HqlPack;
import cn.estsh.i3plus.pojo.platform.bean.SysDepartment;
import cn.estsh.i3plus.pojo.platform.bean.SysOrganize;
import cn.estsh.i3plus.pojo.platform.bean.SysUser;
import cn.estsh.i3plus.pojo.platform.bean.TestTransUser;
import cn.estsh.i3plus.pojo.platform.repository.SysUserRepository;
import cn.estsh.i3plus.pojo.platform.repository.TestTransUserRepository;
import cn.estsh.i3plus.pojo.platform.sqlpack.CoreHqlPack;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
@ -24,6 +26,7 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* @Description :
@ -43,6 +46,9 @@ public class TestService implements ITestService {
@Autowired
private SysUserRepository sysUserRDao;
@Autowired
private TestTransUserRepository testTransUserRepository;
@Override
@ApiOperation(value = "多表查询")
public List<Object> queryToolAndToolType(Pager pager) {
@ -87,4 +93,16 @@ public class TestService implements ITestService {
public List<SysUser> querySysUserByPack(DdlPackBean packBean) {
return sysUserRDao.findByHqlWhere(packBean);
}
@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);
}
}

@ -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
public void testListTranSec(int type,String name) {
//@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
@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());
}
}

@ -58,15 +58,17 @@ spring.datasource.time-between-eviction-runs-millis=18800
##主数据源,读写
#impp.write.datasource.type=com.zaxxer.hikari.HikariDataSource
impp.write.datasource.driver-class-name=com.mysql.jdbc.Driver
impp.write.datasource.jdbc-url=jdbc:mysql://192.168.1.55:3306/impp_i3_core?autoReconnect=true&useSSL=false&characterEncoding=utf-8
impp.write.datasource.jdbc-url=jdbc:mysql://192.168.1.60:3306/impp_i3_core?autoReconnect=true&useSSL=false&characterEncoding=utf-8
#impp.write.datasource.jdbc-url=jdbc:mysql://192.168.1.44:3306/40_impp_i3_core?autoReconnect=true&useSSL=false&characterEncoding=utf-8
impp.write.datasource.username=impp_i3_core_user
impp.write.datasource.password=impp_i3_core_pwd
##辅数据源,只读
#impp.read.datasource.type=com.zaxxer.hikari.HikariDataSource
impp.read.datasource.driver-class-name=com.mysql.jdbc.Driver
impp.read.datasource.jdbc-url=jdbc:mysql://192.168.1.55:3306/impp_i3_core?autoReconnect=true&useSSL=false&characterEncoding=utf-8
impp.read.datasource.username=impp_i3_core_user
impp.read.datasource.jdbc-url=jdbc:mysql://192.168.1.60:3307/impp_i3_core?autoReconnect=true&useSSL=false&characterEncoding=utf-8
#impp.read.datasource.jdbc-url=jdbc:mysql://192.168.1.44:3306/40_impp_i3_core?autoReconnect=true&useSSL=false&characterEncoding=utf-8
impp.read.datasource.username=impp_i3_schedule_user_3307
impp.read.datasource.password=impp_i3_core_pwd
################ 日志数据源 ################

Loading…
Cancel
Save