package com.sinosoft.lis.pubfun; import com.sinosoft.lis.i18n.I18nMessage; import com.sinosoft.lis.db.LockAppDB; import com.sinosoft.lis.schema.LockAppSchema; import com.sinosoft.lis.sql.repository.LockAppSQL; import com.sinosoft.lis.vschema.LockAppSet; import com.sinosoft.persistence.SQLProxy; import com.sinosoft.utility.CError; import com.sinosoft.utility.CErrors; import com.sinosoft.utility.DBConnPool; import com.sinosoft.utility.StrTool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.Connection; import java.util.ArrayList; import java.util.Vector; /** *

* Title:公共加锁程序 *

*

* Description: 防止不同的业务岗位对同一笔业务做互斥的操作,如对与一个投保单,签单和删除动作为互斥的,当该投保单签单的时候就不能做删除 *

*

* Copyright: Copyright (c) 2007 *

*

* Company: SinoSoft *

* * @author Fuqx * @version 1.0 */ public class PubLock { LockAppSQL lockAppSQL = SQLProxy.getInstance(LockAppSQL.class); private static final Logger logger = LoggerFactory.getLogger(PubLock.class); public CErrors mErrors = new CErrors(); // 错误信息 private Connection con; private ArrayList mLockedNos = new ArrayList(); // 同一PubLock对象已经锁定的号码 /** * mflag = true: 传入Connection mflag = false: 不传入Connection */ private boolean mflag = false; private String mReason = "锁定应用模块不明确!"; public PubLock() { } public PubLock(Connection tConnection) { con = tConnection; mflag = true; } public boolean pareLockData(Connection conn, String tOperatedNo, String tReason) { try { LockAppSchema tLockAppSchema = new LockAppSchema(); LockAppSet tLockAppSet = new LockAppSet(); LockAppDB tLockAppDB = new LockAppDB(conn); tLockAppDB.setOperatedNo(tOperatedNo); // 如果不存在任何应用模块对该记录加锁,则直接插入加锁信息 if (!tLockAppDB.getInfo()) { tLockAppSchema.setOperatedNo(tOperatedNo); tLockAppSchema.setState("1"); tLockAppSchema .setReason(StrTool.cTrim(tReason).equals("") ? mReason : tReason); // 当输入的原因为空时,取默认原因 tLockAppSchema.setMakeDate(PubFun.getCurrentDate()); tLockAppSchema.setMakeTime(PubFun.getCurrentTime()); tLockAppSchema.setModifyDate(PubFun.getCurrentDate()); tLockAppSchema.setModifyTime(PubFun.getCurrentTime()); tLockAppDB.setSchema(tLockAppSchema); if (!tLockAppDB.insert()) { this.mErrors.copyAllErrors(tLockAppDB.mErrors); CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "pareLockData"; tError.errorMessage(new I18nMessage("表LockApp插库失败!", "LIS-11175")); this.mErrors.addOneError(tError); conn.rollback(); conn.close(); return false; } } else { tLockAppDB = new LockAppDB(conn); tLockAppSet = lockAppSQL.findAllByOperatedNoForUpdate(tOperatedNo); if (tLockAppSet == null || tLockAppSet.size() == 0) { CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "pareLockData"; tError.errorMessage(new I18nMessage("操作号:{0}对表LockApp中记录加锁失败!", "LIS-11176" , tOperatedNo)); this.mErrors.addOneError(tError); conn.rollback(); conn.close(); return false; } tLockAppSchema = tLockAppSet.get(1); if (!tLockAppSchema.getState().equals("0")) { CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "pareLockData"; tError.errorMessage(new I18nMessage("操作号:{0}已经被其他业务锁定:{1}!", "LIS-11177" , tOperatedNo, tLockAppSchema.getReason())); this.mErrors.addOneError(tError); conn.rollback(); conn.close(); return false; } tLockAppSchema.setState("1"); tLockAppSchema.setMakeDate(PubFun.getCurrentDate()); tLockAppSchema.setMakeTime(PubFun.getCurrentTime()); tLockAppSchema.setModifyDate(PubFun.getCurrentDate()); tLockAppSchema.setModifyTime(PubFun.getCurrentTime()); tLockAppSchema.setReason(StrTool.cTrim(tReason).equals("") ? mReason : tReason); tLockAppDB.setSchema(tLockAppSchema); if (!tLockAppDB.update()) { this.mErrors.copyAllErrors(tLockAppDB.mErrors); CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "pareLockData"; tError.errorMessage(new I18nMessage("表LockApp更新失败!", "LIS-11178")); this.mErrors.addOneError(tError); conn.rollback(); conn.close(); return false; } } } catch (Exception ex) { CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "pareLockData"; tError.errorMessage(new I18nMessage( ex.toString(), null)); this.mErrors.addOneError(tError); try { conn.rollback(); conn.close(); } catch (Exception e) { } return false; } return true; } public boolean pareUnLockData(Connection conn, String tOperatedNo) { try { LockAppSchema tLockAppSchema = new LockAppSchema(); LockAppSet tLockAppSet = new LockAppSet(); LockAppDB tLockAppDB = new LockAppDB(conn); tLockAppDB.setOperatedNo(tOperatedNo); // 如果原来没有加锁信息,直接返回 if (!tLockAppDB.getInfo()) { return true; } else { //mysql 不支持nowait 暂时取消 nowait tLockAppDB = new LockAppDB(conn); tLockAppSet = lockAppSQL.findAllByOperatedNoForUpdate(tOperatedNo); if (tLockAppSet == null || tLockAppSet.size() == 0) { String aa = tLockAppDB.mErrors.getFirstError(); CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "pareUnLockData"; tError.errorMessage(new I18nMessage("操作号:{0}对表LockApp加锁失败!", "LIS-11179" , tOperatedNo)); this.mErrors.addOneError(tError); conn.rollback(); conn.close(); return false; } tLockAppSchema = tLockAppSet.get(1); if (tLockAppSchema.getState().equals("1")) { tLockAppSchema.setState("0"); tLockAppSchema.setModifyDate(PubFun.getCurrentDate()); tLockAppSchema.setModifyTime(PubFun.getCurrentTime()); tLockAppDB.setSchema(tLockAppSchema); if (!tLockAppDB.update()) { this.mErrors.copyAllErrors(tLockAppDB.mErrors); CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "pareUnLockData"; tError.errorMessage(new I18nMessage("表LockApp更新失败!", "LIS-11178")); this.mErrors.addOneError(tError); conn.rollback(); conn.close(); return false; } } } } catch (Exception ex) { CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "pareLockData"; tError.errorMessage(new I18nMessage( ex.toString(), null)); this.mErrors.addOneError(tError); try { conn.rollback(); conn.close(); } catch (Exception e) { } return false; } return true; } /** * 对号码为tOperatedNo(如投保单号)的业务锁定,在解锁之前,除锁定业务外,其他业务不能对该号码做操作 * * @parameter tOperatedNo 需要锁定的号码 * @parameter tReason 加锁理由 * @return 如果加锁成功,返回true;加锁失败,则返回false */ public boolean lock(String tOperatedNo, String tReason) { try { if (mLockedNos.contains(tOperatedNo)) { logger.debug("本批次已经对号码成功锁定:" + tOperatedNo); return true; } if (mflag == false) { con = DBConnPool.getConnection(); } if (con == null) { // @@错误处理 CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "lock"; tError.errorMessage(new I18nMessage("数据库连接失败!", "LIS-06519")); this.mErrors.addOneError(tError); return false; } // 设置为非自动提交 con.setAutoCommit(false); if (!pareLockData(con, tOperatedNo, tReason)) return false; if (mflag == false) { con.commit(); con.close(); mLockedNos.add(tOperatedNo); // 将锁定号码加入到集合中 } } catch (Exception ex) { CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "lock"; tError.errorMessage(new I18nMessage( ex.toString(), null)); this.mErrors.addOneError(tError); try { // 如果发生异常以后,关闭连接 if (mflag == false && !con.isClosed()) { con.rollback(); con.close(); } } catch (Exception e) { } return false; } return true; } /** * 对数组中tArrayNo包含的每一个tOperatedNo号码(如投保单号)的业务锁定,在解锁之前,除锁定业务外,其他业务不能对该号码组做操作 * * @parameter tOperatedNo 需要锁定的号码 * @parameter tReason 加锁理由 * @return 如果所有的号码都加锁成功,返回true;如果其中一个加锁失败,则返回false */ public boolean lock(String[] tArrayNo, String tReason) { try { if (mflag == false) { con = DBConnPool.getConnection(); } if (con == null) { // @@错误处理 CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "lock"; tError.errorMessage(new I18nMessage("数据库连接失败!", "LIS-06519")); this.mErrors.addOneError(tError); return false; } // 设置为非自动提交 con.setAutoCommit(false); for (int i = 0; i < tArrayNo.length; i++) { if (mLockedNos.contains(tArrayNo[i])) { logger.debug("本批次已经对号码成功锁定:" + tArrayNo[i]); continue; } if (!pareLockData(con, tArrayNo[i], tReason)) return false; } if (mflag == false) { con.commit(); con.close(); // 对非传如连接的,保存该批次传入需要锁定 for (int j = 0; j < tArrayNo.length; j++) { if (!mLockedNos.contains(tArrayNo[j])) // 如果号码中不包含这个号,加入集合中 { mLockedNos.add(tArrayNo[j]); } } } } catch (Exception ex) { CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "lock"; tError.errorMessage(new I18nMessage( ex.toString(), null)); this.mErrors.addOneError(tError); try { // 如果发生异常以后,关闭连接 if (mflag == false && !con.isClosed()) { con.rollback(); con.close(); } } catch (Exception e) { } return false; } return true; } /** * 对号码为tOperatedNo(如投保单号)的业务解除锁定,解锁后,允许其他业务对该号码对应的记录做操作 * * @parameter tOperatedNo 需要解锁的号码 * @return 如果解锁成功,返回true;解锁失败,则返回false */ public boolean unLock(String tOperatedNo) { try { if (mflag == false) { con = DBConnPool.getConnection(); } if (con == null) { // @@错误处理 CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "unLock"; tError.errorMessage(new I18nMessage("数据库连接失败!", "LIS-06519")); this.mErrors.addOneError(tError); return false; } // 设置为非自动提交 con.setAutoCommit(false); // 解锁数据准备 if (!pareUnLockData(con, tOperatedNo)) return false; if (mflag == false) { con.commit(); con.close(); // 当解锁成功,删除集合中的号码 if (mLockedNos.contains(tOperatedNo)) { mLockedNos.remove(tOperatedNo); } } } catch (Exception ex) { CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "lock"; tError.errorMessage(new I18nMessage( ex.toString(), null)); this.mErrors.addOneError(tError); try { // 如果发生异常以后,关闭连接 if (mflag == false && !con.isClosed()) { con.rollback(); con.close(); } } catch (Exception e) { } return false; } return true; } /** * */ public boolean unLock(String[] tArrayNo) { try { if (mflag == false) { con = DBConnPool.getConnection(); } if (con == null) { // @@错误处理 CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "unLock"; tError.errorMessage(new I18nMessage("数据库连接失败!", "LIS-06519")); this.mErrors.addOneError(tError); return false; } // 设置为非自动提交 con.setAutoCommit(false); // 解锁数据准备 for (int i = 0; i < tArrayNo.length; i++) { if (!pareUnLockData(con, tArrayNo[i])) return false; } if (mflag == false) { con.commit(); con.close(); for (int j = 0; j < tArrayNo.length; j++) { if (mLockedNos.contains(tArrayNo[j])) { mLockedNos.remove(tArrayNo[j]); } } } } catch (Exception ex) { CError tError = new CError(); tError.moduleName = "PubLock"; tError.functionName = "lock"; tError.errorMessage(new I18nMessage( ex.toString(), null)); this.mErrors.addOneError(tError); try { // 如果发生异常以后,关闭连接 if (mflag == false && !con.isClosed()) { con.rollback(); con.close(); } } catch (Exception e) { } return false; } return true; } }