保存和删除增加并发控制
- 技术概要
1.对当前单据增加并发锁
// 存放需要加锁的主键 表头+表体主键
ArrayList<String> lockpks = new ArrayList<>();
// 加并发锁
LockTool.setDynamicLockForPks((String[]) lockpks.toArray(new String[0]), null);
//表头校验ts
// 根据主键查询表头vo
StoreMainVO mainVO = baseDAO.queryVOByPK(StoreMainVO.class, storeMainVO.getPk_stroe_main());
if (!mainVO.getTs().equals(storeMainVO.getTs())) {
throw new BusinessException("数据已被修改,请重新查询");
}
//表体校验ts
//修改之前的ts
ArrayList<UFDateTime> tsList =tsList = new ArrayList<UFDateTime>();
if (tsList != null) {
String condition = sBuilder.toString();
String[] fields = { "ts" };
// 数据库表体ts
List<UFDateTime> lastTs = new ArrayList<>();
Collection<StoreSubVO> lbList = baseDAO.retrieveByClause(StoreSubVO.class, condition, fields);
for (StoreSubVO temp : lbList) {
lastTs.add(temp.getTs());
}
Set<UFDateTime> set1 = new HashSet<>(tsList);
Set<UFDateTime> set2 = new HashSet<>(lastTs);
boolean isEqual = set1.equals(set2);
if (!isEqual) {
throw new BusinessException("数据已被修改,请重新查询");
}
}
2.对当前单据关联的其他对象
//获取加锁单据的主键
//对加锁单据进行加锁
boolean lockPeriod = false;
//如果返回值为false说明,已经被加锁了
lockPeriod = PKLock.getInstance().acquireLock(hsPk, PubEnv.getPk_user(), null);
if (!lockPeriod) {
throw new BusinessException( NCLangResOnserver.getInstance().getStrByID("60131004", "UPP60131004-000303"));
}
//校验时间戳
//进行更新操作
//解锁 放到finally{}里面,这样抛异常不影响解锁
if (lockPeriod)
PKLock.getInstance().releaseLock(hsPk, PubEnv.getPk_user(), null);
两种加锁区别
LockTool.setDynamicLockForPks((String[]) lockpks.toArray(new String[0]), null);
自动加锁自动解锁,只需要传入需要加锁的主键值数组
lockPeriod = PKLock.getInstance().acquireLock(hsPk, PubEnv.getPk_user(), null);
PKLock.getInstance().releaseLock(hsPk, PubEnv.getPk_user(), null);
手动加锁需要手动解锁,传入值为加锁pk,当前登录userId
总代码
package u8c.impl.pe;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jfree.chart.demo.Performance;
import com.ibm.db2.jcc.sqlj.m;
import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.ml.NCLangResOnserver;
import nc.bs.pub.pflock.PfBusinessLock;
import nc.bs.pub.pflock.VOConsistenceCheck;
import nc.bs.pub.pflock.VOLockData;
import nc.bs.uap.lock.PKLock;
import nc.hr.utils.PubEnv;
import nc.hr.utils.ResHelper;
import nc.itf.scm.pub.lock.LockTool;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.ui.hr.frame.persistence.PersitenceDelegator;
import nc.vo.hr.tools.pub.HRAggVO;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.CircularlyAccessibleValueObject;
import nc.vo.pub.SuperVO;
import nc.vo.pub.ValidationException;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import u8c.itf.hr.lb.IOperateData;
import u8c.vo.hr.pe_001.PerformanceVO;
import u8c.vo.pe.AggStoreMainVO;
import u8c.vo.pe.StoreMainVO;
import u8c.vo.pe.StoreSubVO;
public class IOperateDataImpl implements IOperateData {
private BaseDAO baseDao = null;
public BaseDAO getBaseDao() {
if (baseDao == null) {
this.baseDao = new BaseDAO();
}
return baseDao;
}
@Override
public Object saveEditData(Object data, String checkClassMethodName, String lockClassName) throws Exception {
if (data instanceof HRAggVO) {
HRAggVO hrAggVO = (HRAggVO) data;
String hsBackfill="";
StoreMainVO parentVO = (StoreMainVO) hrAggVO.getParentVO();
if (parentVO.getPk_stroe_main() != null) {
addLock(data);
} else {
hsBackfill = hsBackfill(data);
}
parentVO.setVdef1(hsBackfill);
hrAggVO.setParentVO(parentVO);
/**
* 测试并发 UFDouble other = parentVO.getOther(); String string = other.toString();
* if(string.equals("1.00")) { try { Thread.sleep(10000); } catch
* (InterruptedException e) { // 处理中断异常 } }
*/
return PersitenceDelegator.saveAggVO(hrAggVO, checkClassMethodName, lockClassName);
}
if (data instanceof HRAggVO[]) {
HRAggVO[] hrAggVOs = (HRAggVO[]) data;
if (hrAggVOs != null && hrAggVOs.length > 0) {
StoreMainVO parentVO = (StoreMainVO) hrAggVOs[0].getParentVO();
if (parentVO.getPk_stroe_main() != null) {
addLock(data);
}else {
hsBackfill(data);
}
}
// addLock(data);
return PersitenceDelegator.saveAggVOArray(hrAggVOs, checkClassMethodName, lockClassName);
}
return null;
}
public String hsBackfill(Object data) throws Exception {
BaseDAO baseDAO = getBaseDao();
if (data instanceof HRAggVO) {
HRAggVO hrAggVO = (HRAggVO) data;
StoreMainVO storeMainVO = (StoreMainVO) hrAggVO.getParentVO();
String hsPk = storeMainVO.getPk_performance();
String vdef1 = storeMainVO.getVdef1();
boolean lockPeriod = false;
try {
lockPeriod = PKLock.getInstance().acquireLock(hsPk, PubEnv.getPk_user(), null);
if (!lockPeriod) {
throw new BusinessException(
NCLangResOnserver.getInstance().getStrByID("60131004", "UPP60131004-000303"));
}
PerformanceVO performanceVO = baseDAO.queryVOByPK(PerformanceVO.class, storeMainVO.getPk_performance());
if(performanceVO.getTs().equals(new UFDateTime(vdef1))) {
String sql = "update pe_performance set iscite='1' where pk_performance='" + hsPk + "'";
baseDAO.executeUpdate(sql);
String selectTs="select ts from pe_performance where pk_performance='"+ hsPk + "'";
String lastTs=(String)baseDAO.executeQuery(selectTs,new ColumnProcessor());
return lastTs;
}else {
new ValidationException("数据已经被修改,请刷新界面");
}
} finally {
if (lockPeriod)
PKLock.getInstance().releaseLock(hsPk, PubEnv.getPk_user(), null);
}
}
return null;
}
public void hsBackfillDel(Object data) throws BusinessException {
BaseDAO baseDAO = getBaseDao();
if (data instanceof HRAggVO) {
HRAggVO hrAggVO = (HRAggVO) data;
StoreMainVO storeMainVO = (StoreMainVO) hrAggVO.getParentVO();
String hsPk = storeMainVO.getPk_performance();
String vdef1 = storeMainVO.getVdef1();
boolean lockPeriod = false;
try {
lockPeriod = PKLock.getInstance().acquireLock(hsPk, PubEnv.getPk_user(), null);
if (!lockPeriod) {
throw new BusinessException(
NCLangResOnserver.getInstance().getStrByID("60131004", "UPP60131004-000303"));
}
PerformanceVO performanceVO = baseDAO.queryVOByPK(PerformanceVO.class, storeMainVO.getPk_performance());
if(performanceVO.getTs().equals(new UFDateTime(vdef1))) {
String sql = "update pe_performance set iscite='0' where pk_performance='" + hsPk + "'";
baseDAO.executeUpdate(sql);
StoreMainVO delStoreMain = delChangeStates(data);
baseDAO.updateVO(delStoreMain, new String[] { "dr" });
}else {
new ValidationException("数据已经被修改,请刷新界面");
}
} finally {
if (lockPeriod)
PKLock.getInstance().releaseLock(hsPk, PubEnv.getPk_user(), null);
}
} else if (data instanceof HRAggVO[]) {
HRAggVO[] hrAggVOs = (HRAggVO[]) data;
boolean[] lockPeriod = new boolean[hrAggVOs.length];
StringBuilder sBuilder = new StringBuilder("update pe_performance set iscite='0' where pk_performance in(");
StringBuilder queryBuilder = new StringBuilder("pk_performance in(");
boolean flag=true;
ArrayList<String> unLockPk=new ArrayList<String>();
List<UFDateTime> beforeTimes = new ArrayList<>();
ArrayList<UFDateTime> afterTimes = new ArrayList<UFDateTime>();
try {
HRAggVO hrAggVO = null;
for (int i = 0; i < hrAggVOs.length; i++) {
lockPeriod[i]=false;
hrAggVO=hrAggVOs[i];
StoreMainVO storeMainVO = (StoreMainVO) hrAggVO.getParentVO();
String hsPk = storeMainVO.getPk_performance();
String vdef1 = storeMainVO.getVdef1();
beforeTimes.add(new UFDateTime(vdef1));
lockPeriod[i] = PKLock.getInstance().acquireLock(hsPk, PubEnv.getPk_user(), null);
sBuilder.append("'").append(storeMainVO.getPk_performance()).append("',");
queryBuilder.append("'").append(storeMainVO.getPk_performance()).append("',");
if(!lockPeriod[i]) {
flag=false;
}
unLockPk.add(hsPk);
}
sBuilder.setCharAt(sBuilder.length() - 1, ')');
queryBuilder.setCharAt(queryBuilder.length() - 1, ')');
String sql = sBuilder.toString();
if(flag) {
String[] fields = { "ts" };
String condition=queryBuilder.toString();
// 数据库表体ts
Collection<PerformanceVO> afterSubVOs = baseDAO.retrieveByClause(PerformanceVO.class, condition, fields);
for (PerformanceVO temp : afterSubVOs) {
afterTimes.add(temp.getTs());
}
Set<UFDateTime> set1 = new HashSet<>(beforeTimes);
Set<UFDateTime> set2 = new HashSet<>(afterTimes);
boolean isEqual = set1.equals(set2);
if (!isEqual) {
throw new BusinessException("数据已被修改,请重新查询");
}else {
baseDAO.executeUpdate(sql);
StoreMainVO[] afterAggVOs = new StoreMainVO[hrAggVOs.length];
for (int i = 0; i < hrAggVOs.length; i++) {
afterAggVOs[i] = delChangeStates(hrAggVOs[i]);
}
baseDAO.updateVOArray(afterAggVOs, new String[] { "dr" });
}
}else {
throw new BusinessException(
NCLangResOnserver.getInstance().getStrByID("60131004", "UPP60131004-000303"));
}
} finally {
for (int i = 0; i < lockPeriod.length; i++) {
if(lockPeriod[i]) {
PKLock.getInstance().releaseLock(unLockPk.get(i), PubEnv.getPk_user(), null);
}
}
}
}
}
@Override
public boolean deleteData(Object data, String checkClassMethodName, String lockClassName) throws Exception {
BaseDAO baseDAO = getBaseDao();
if (data instanceof HRAggVO) {
addLock(data);
/** 两个单据都进行并发和校验ts以后再进行数据库操作
StoreMainVO hrAggVO = delChangeStates(data);
baseDAO.updateVO(hrAggVO, new String[] { "dr" });
*/
hsBackfillDel(data);
return true;
}
if (data instanceof HRAggVO[]) {
addLock(data);
/**
HRAggVO[] hrAggVOs = (HRAggVO[]) data;
StoreMainVO[] afterAggVOs = new StoreMainVO[hrAggVOs.length];
for (int i = 0; i < hrAggVOs.length; i++) {
afterAggVOs[i] = delChangeStates(hrAggVOs[i]);
}
baseDAO.updateVOArray(afterAggVOs, new String[] { "dr" });
*/
hsBackfillDel(data);
return true;
}
/**
* if (data instanceof SuperVO) { PersitenceDelegator.deleteVO((SuperVO) data,
* checkClassMethodName); return true; } if (data instanceof SuperVO[]) {
* PersitenceDelegator.deleteVOArray((SuperVO[]) data, checkClassMethodName);
* return true; }
*/
return false;
}
@Override
public void importDataSave(StoreSubVO[] storeSubVOs) throws Exception {
BaseDAO baseDAO = getBaseDao();
addLock(storeSubVOs);
// baseDAO.executeUpdate("update pe_store_sub set dr='1' where pk_store_sub='1002ZZ10000000001EXO' ");
baseDAO.updateVOArray(storeSubVOs);
}
private StoreMainVO delChangeStates(Object data) {
if (data instanceof HRAggVO) {
HRAggVO hrAggVO = (HRAggVO) data;
StoreMainVO storeMainVO = (StoreMainVO) hrAggVO.getParentVO();
storeMainVO.setDr(1);
hrAggVO.setParentVO(storeMainVO);
return storeMainVO;
}
return null;
}
// 加锁并且检查时间戳
private void addLock(Object data) throws BusinessException {
if (data instanceof HRAggVO) {
HRAggVO hrAggVO = (HRAggVO) data;
addHRAggVOLock(hrAggVO);
} else if (data instanceof HRAggVO[]) {
HRAggVO[] hrAggVOs = (HRAggVO[]) data;
for (int i = 0; i < hrAggVOs.length; i++) {
addHRAggVOLock(hrAggVOs[i]);
}
} else if (data instanceof SuperVO) {
StoreSubVO storeSubVO = (StoreSubVO) data;
addSuperVOLock(storeSubVO);
} else {
StoreSubVO[] storeSubVOs = (StoreSubVO[]) data;
addSuperVOsLock(storeSubVOs);
}
}
// 加锁并且检查时间戳
private void addHRAggVOLock(HRAggVO aggVO) throws BusinessException {
BaseDAO baseDAO = getBaseDao();
StoreMainVO storeMainVO = (StoreMainVO) aggVO.getParentVO();
// 获取当前单据表体所有数据
CircularlyAccessibleValueObject[] allChildrenVO = aggVO.getAllChildrenVO();
// 存放需要加锁的主键
ArrayList<String> lockpks = new ArrayList<>();
StoreSubVO storeSubVO = null;
// 表头主键
if (!lockpks.contains(storeMainVO.getPk_stroe_main())) {
lockpks.add(storeMainVO.getPk_stroe_main());
}
StringBuilder sBuilder = new StringBuilder("pk_store_sub in(");
ArrayList<UFDateTime> tsList = null;
if (allChildrenVO != null) {
// 存放修改时,表体的时间戳
tsList = new ArrayList<UFDateTime>();
// 表体主键
for (int i = 0; i < allChildrenVO.length; i++) {
storeSubVO = (StoreSubVO) allChildrenVO[i];
if (!lockpks.contains(storeSubVO.getPk_store_sub())) {
lockpks.add(storeSubVO.getPk_store_sub());
}
tsList.add(storeSubVO.getTs());
sBuilder.append("'").append(storeSubVO.getPk_store_sub()).append("',");
}
sBuilder.setCharAt(sBuilder.length() - 1, ')');
}
// 加并发锁
LockTool.setDynamicLockForPks((String[]) lockpks.toArray(new String[0]), null);
// 根据主键查询表头vo
StoreMainVO mainVO = baseDAO.queryVOByPK(StoreMainVO.class, storeMainVO.getPk_stroe_main());
if (!mainVO.getTs().equals(storeMainVO.getTs())) {
throw new BusinessException("数据已被修改,请重新查询");
}
if (tsList != null) {
String condition = sBuilder.toString();
String[] fields = { "ts" };
// 数据库表体ts
List<UFDateTime> lastTs = new ArrayList<>();
Collection<StoreSubVO> lbList = baseDAO.retrieveByClause(StoreSubVO.class, condition, fields);
for (StoreSubVO temp : lbList) {
lastTs.add(temp.getTs());
}
Set<UFDateTime> set1 = new HashSet<>(tsList);
Set<UFDateTime> set2 = new HashSet<>(lastTs);
boolean isEqual = set1.equals(set2);
if (!isEqual) {
throw new BusinessException("数据已被修改,请重新查询");
}
}
}
private void addSuperVOLock(StoreSubVO storeSubVO) throws BusinessException {
// 存放需要加锁的主键
ArrayList<String> lockpks = new ArrayList<>();
// 加并发锁
if (storeSubVO != null) {
lockpks.add(storeSubVO.getPk_store_sub());
}
LockTool.setDynamicLockForPks((String[]) lockpks.toArray(new String[0]), null);
BaseDAO baseDAO = new BaseDAO();
StoreSubVO subVO = (StoreSubVO) baseDAO.retrieveByPK(StoreSubVO.class, storeSubVO.getPk_store_sub());
if (!(storeSubVO.getTs().equals(subVO.getTs()))) {
throw new BusinessException("数据已被修改,请重新查询");
}
}
private void addSuperVOsLock(StoreSubVO[] storeSubVOs) throws BusinessException {
if (storeSubVOs == null || storeSubVOs.length < 1) {
throw new ValidationException("Excel没有任何数据导入");
}
BaseDAO baseDAO = getBaseDao();
// Before and after
List<UFDateTime> beforeTimes = new ArrayList<>();
ArrayList<UFDateTime> afterTimes = new ArrayList<UFDateTime>();
StringBuilder sBuilder = new StringBuilder("pk_store_sub in(");
for (int i = 0; i < storeSubVOs.length; i++) {
StoreSubVO storeSubVO = storeSubVOs[i];
beforeTimes.add(storeSubVO.getTs());
sBuilder.append("'").append(storeSubVO.getPk_store_sub()).append("',");
}
sBuilder.setCharAt(sBuilder.length() - 1, ')');
String condition = sBuilder.toString();
String[] fields = { "ts" };
// 数据库表体ts
Collection<StoreSubVO> afterSubVOs = baseDAO.retrieveByClause(StoreSubVO.class, condition, fields);
for (StoreSubVO temp : afterSubVOs) {
afterTimes.add(temp.getTs());
}
Set<UFDateTime> set1 = new HashSet<>(beforeTimes);
Set<UFDateTime> set2 = new HashSet<>(afterTimes);
boolean isEqual = set1.equals(set2);
if (!isEqual) {
throw new BusinessException("数据已被修改,请重新查询");
}
}
}