Redis + CAS,配置自增业务单号
DB 脚本
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for log_czrz
-- ----------------------------
CREATE TABLE `log_czrz`
(
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`SQBM` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '社区编码',
`table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表名',
`table_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表主键',
`table_column` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '医保目录编码',
`xgysbm` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改医生编码',
`xgysmc` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '更改医生名称',
`xgxx` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '修改信息',
`xgrq` int(11) NULL DEFAULT NULL COMMENT '修改日期',
`xgsj` int(11) NULL DEFAULT NULL COMMENT '修改时间',
`machine_ip` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'ip',
`machine_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'ip名称',
`System_version` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '电脑系统版本',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
-- AUTO_INCREMENT = 5135
CHARACTER SET = utf8
COLLATE = utf8_general_ci COMMENT = '药房库存修改药品有效期日志表'
ROW_FORMAT = Compact;
SET FOREIGN_KEY_CHECKS = 1;
-- ----------------------------
-- Table structure for ywdh_config
-- ----------------------------
CREATE TABLE `ywdh_config`
(
`PKYWDHCONFIG` int(11) NOT NULL AUTO_INCREMENT COMMENT '业务单号设置自增主键',
`SQBM` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '社区编码',
`LX` int(2) NULL DEFAULT NULL COMMENT '单号类型(1药库采购、4药库验收、2药库入库、3药库出库...)',
`KSLX` int(5) NULL DEFAULT NULL COMMENT '科室类型(对应zd_ks科室的主键id)',
`JTLX` int(5) NULL DEFAULT NULL COMMENT '具体类型(将单号类型进一步细分的具体类型)',
`CZRYID` int(11) NULL DEFAULT NULL COMMENT '操作人员id',
`DHQZ` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '单号前缀',
`DHCD` int(5) NULL DEFAULT NULL COMMENT '单号长度(不含前缀)',
`DHQSH` int(5) NULL DEFAULT NULL COMMENT '单号起始号',
`DHBC` int(5) NULL DEFAULT NULL COMMENT '单号步长',
`ISOPEN` int(2) NULL DEFAULT 1 COMMENT '是否开启(1开启为递增序列,0不开启为时间戳随机序列)',
`CURRENTTIME` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '时间戳',
`CREATEDAT` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
`UPDATEDAT` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日期',
PRIMARY KEY (`PKYWDHCONFIG`) USING BTREE
) ENGINE = InnoDB
-- AUTO_INCREMENT = 180
CHARACTER SET = utf8
COLLATE = utf8_general_ci COMMENT = '业务单号生成规则配置'
ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for ywdh_redis_pair
-- ----------------------------
CREATE TABLE `ywdh_redis_pair`
(
`PKPAIR` int(11) NOT NULL AUTO_INCREMENT COMMENT '键值对主键pk',
`SQBM` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '社区编码',
`CURRENTTIME` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '时间戳',
`KEYNAME` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '键',
`VALUE` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '值',
PRIMARY KEY (`PKPAIR`) USING BTREE
) ENGINE = InnoDB
-- AUTO_INCREMENT = 214
CHARACTER SET = utf8
COLLATE = utf8_general_ci COMMENT = '业务单号键值对'
ROW_FORMAT = Compact;
SET FOREIGN_KEY_CHECKS = 1;
Entity
YwdhConfig(业务单号配置)
import lombok.Data;
import javax.persistence.*;
import java.util.Date;
/**
* @Author: DengJia
* @Date: 2022/2/14 10:44
* @Description: 业务单号配置
*/
@Data
public class YwdhConfig {
/**
* 药库单号设置自增主键
*/
private Integer pkywdhconfig;
/**
* 社区编码
*/
private String sqbm;
/**
* 单号类型(1药库采购、2药库入库、3药库出库...)
*/
private Integer lx;
/**
* 科室类型(对应zd_ks科室的主键id)
*/
private Integer kslx;
/**
* 具体类型(将单号类型进一步细分的具体类型)
*/
private Integer jtlx;
/**
* 操作人员id
*/
private Integer czryid;
/**
* 单号前缀
*/
private String dhqz;
/**
* 单号长度(不含前缀)
*/
private Integer dhcd;
/**
* 单号起始号
*/
private Integer dhqsh;
/**
* 单号步长
*/
private Integer dhbc;
/**
* 是否开启(1开启为递增序列,0不开启为时间戳随机序列)
*/
private Integer isopen;
/**
* 时间戳
*/
private String currenttime;
private Date createdAt;
private Date updatedAt;
}
YwdhRedisPair(Redis键值对)
import lombok.Data;
import javax.persistence.*;
/**
* @Author: DengJia
* @Date: 2022/2/17 9:25
* @Description: redis键值对
*/
@Data
public class YwdhRedisPair {
private Integer pkpair;
private String currenttime;
private String sqbm;
private String keyname;
private String value;
public YwdhRedisPair() {
}
public YwdhRedisPair(String sqbm, String currenttime) {
this.currenttime = currenttime;
this.sqbm = sqbm;
}
public YwdhRedisPair(Integer pkpair, String currenttime, String sqbm, String keyname, String value) {
this.pkpair = pkpair;
this.currenttime = currenttime;
this.sqbm = sqbm;
this.keyname = keyname;
this.value = value;
}
}
Mapping
YwdhConfig.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.yuanbo.chss.domain.business.YwdhConfig" table="ywdh_config">
<id name="pkywdhconfig" type="java.lang.Integer">
<column name="PKYWDHCONFIG" precision="11" scale="0"/>
<generator class="identity"/>
</id>
<property name="sqbm">
<column name="SQBM" sql-type="varchar(20)" length="20"/>
</property>
<property name="lx" type="java.lang.Integer">
<column name="LX" precision="2" scale="0"/>
</property>
<property name="kslx" type="java.lang.Integer">
<column name="KSLX" precision="5" scale="0"/>
</property>
<property name="jtlx" type="java.lang.Integer">
<column name="JTLX" precision="5" scale="0"/>
</property>
<property name="czryid" type="java.lang.Integer">
<column name="CZRYID" precision="11" scale="0"/>
</property>
<property name="dhqz" type="java.lang.String">
<column name="DHQZ" sql-type="varchar(10)" length="10"/>
</property>
<property name="dhcd" type="java.lang.Integer">
<column name="DHCD" precision="5" scale="0"/>
</property>
<property name="dhqsh" type="java.lang.Integer">
<column name="DHQSH" precision="5" scale="0"/>
</property>
<property name="dhbc" type="java.lang.Integer">
<column name="DHBC" precision="2" scale="0"/>
</property>
<property name="isopen" type="java.lang.Integer">
<column name="ISOPEN" precision="2" scale="0"/>
</property>
<property name="currenttime" type="java.lang.String">
<column name="CURRENTTIME" sql-type="varchar(50)" length="50"/>
</property>
</class>
</hibernate-mapping>
YwdhRedisPair.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.yuanbo.chss.domain.business.YwdhRedisPair" table="ywdh_redis_pair">
<id name="pkpair" type="java.lang.Integer">
<column name="PKPAIR" precision="11" scale="0"/>
<generator class="identity"/>
</id>
<property name="sqbm">
<column name="SQBM" sql-type="varchar(20)" length="20"/>
</property>
<property name="currenttime" type="java.lang.String">
<column name="CURRENTTIME" sql-type="varchar(15)" length="15"/>
</property>
<property name="keyname" type="java.lang.String">
<column name="KEYNAME" sql-type="varchar(100)" length="100"/>
</property>
<property name="value" type="java.lang.String">
<column name="VALUE" sql-type="varchar(20)" length="20"/>
</property>
</class>
</hibernate-mapping>
Enum
YwdhOpsEnum(业务单号操作,枚举类)
import com.yuanbo.common.util.G3GlobalNames;
import java.util.Objects;
import java.util.stream.Stream;
/**
* @Author: DengJia
* @Date: 2022/2/10 11:31
* @Description: 业务单号操作,枚举类
*/
public enum YwdhOpsEnum {
// 药库采购
PURCHASE(G3GlobalNames.YK_CGD0, 1),
// 药库验收
ACCEPTANCE(G3GlobalNames.YK_YSD0, 4),
// 药库入库
INBOUND(G3GlobalNames.YK_RKD0, 2),
// 药库出库
OUTBOUND(G3GlobalNames.YK_CKD0, 3);
// ...
private Long opcode;
private Integer lx;
/**
* 获取对应类型的操作码
*
* @param lx 类型值
* @return 操作码
*/
public static Long getOpcode(Integer lx) {
return Stream.of(YwdhOpsEnum.values())
.filter(e -> Objects.equals(e.getLx(), lx))
.findFirst().map(e -> e.opcode)
// 如果lx不存在,opcode返回无效值:-1L
.orElse(-1L);
}
/**
* 获取操作码的类型
*
* @param opcode 药库操作的编码
* @return 类型值
*/
public static Integer getLx(long opcode) {
return Stream.of(YwdhOpsEnum.values())
.filter(e -> Objects.equals(e.getOpcode(), opcode))
.findFirst().map(e -> e.lx)
// 如果opcode不存在,lx返回无效值:-1
.orElse(-1);
}
YwdhOpsEnum(Long opcode, Integer lx) {
this.opcode = opcode;
this.lx = lx;
}
public Long getOpcode() {
return opcode;
}
public void setOpcode(Long opcode) {
this.opcode = opcode;
}
public Integer getLx() {
return lx;
}
public void setLx(Integer lx) {
this.lx = lx;
}
}
Repository
YwdhConfigRepository(业务单号配置 Repository)
import com.yuanbo.chss.domain.business.YwdhConfig;
import java.util.List;
import java.util.Map;
/**
* @Author: DengJia
* @Date: 2022/2/14 14:30
* @Description: 药库单号配置 Repository
*/
public interface YwdhConfigRepository {
/**
* 查询业务单号配置,入参含主键则通过主键查询,否则按条件查询。
*
* @param dataMap 过滤条件
* @return 配置信息
*/
List<Map<String, Object>> selectYwdhConfig(Map<String, Object> dataMap);
/**
* 用户自定义配置业务单号格式
*
* @param dbBean 原值
* @param paramBean 修改值
*/
void updateYwdhConfig(YwdhConfig dbBean, YwdhConfig paramBean);
/**
* 删除单号配置
* @param ids 待删除单号主键ids
*/
void deleteBusinessNumConfigByIds(List<Integer> ids);
}
YwdhConfigRepositoryImpl(业务单号配置 RepositoryImpl)
import com.yuanbo.chss.domain.business.YwdhConfig;
import com.yuanbo.common.util.LoginHelper;
import com.yuanbo.hap.util.DBAgent;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.yuanbo.hap.util.ParamUtil.beanToMap;
import static com.yuanbo.hap.util.ParamUtil.mapToBean;
/**
* @Author: DengJia
* @Date: 2022/2/14 14:39
* @Description: 业务单号配置 RepositoryImpl
*/
@Repository("YwdhConfigRepository")
public class YwdhConfigRepositoryImpl implements YwdhConfigRepository {
private static final DBAgent DBA = DBAgent.getInstance();
@Override
public List<Map<String, Object>> selectYwdhConfig(Map<String, Object> dataMap) {
StringBuilder querySql = new StringBuilder("select * from ywdh_config where sqbm = ::SQBM ");
if (dataMap.get("PKYWDHCONFIG") != null) {
querySql.append("and pkywdhconfig = ::PKYWDHCONFIG ");
} else {
if (dataMap.get("LX") != null) {
querySql.append("and lx = ::LX ");
}
if (dataMap.get("KSLX") != null) {
querySql.append("and kslx = ::KSLX ");
}
if (dataMap.get("JTLX") != null) {
querySql.append("and jtlx = ::JTLX ");
}
// if (dataMap.get("CZRYID") != null) {
// querySql.append("and czryid = ::CZRYID ");
// }
if (dataMap.get("DHQZ") != null) {
querySql.append("and dhqz = :DHQZ ");
}
if (dataMap.get("DHCD") != null) {
querySql.append("and dhcd = ::DHCD ");
}
if (dataMap.get("DHQSH") != null) {
querySql.append("and dhqsh = ::DHQSH ");
}
if (dataMap.get("DHBC") != null) {
querySql.append("and dhbc = ::DHBC ");
}
if (dataMap.get("ISOPEN") != null) {
querySql.append("and isopen = ::ISOPEN ");
}
if (dataMap.get("CURRENTTIME") != null) {
querySql.append("and currenttime = ::CURRENTTIME ");
}
}
return DBA.querySQL(querySql.toString(), dataMap, null);
}
@Override
public void updateYwdhConfig(YwdhConfig dbBean, YwdhConfig paramBean) {
YwdhConfig config = new YwdhConfig();
// 浅拷贝
BeanUtils.copyProperties(paramBean, config);
if (config.getLx() == null) {
config.setLx(dbBean.getLx());
}
if (config.getKslx() == null) {
config.setKslx(dbBean.getKslx());
}
if (config.getJtlx() == null) {
config.setJtlx(dbBean.getJtlx());
}
if (config.getCzryid() == null) {
config.setCzryid(dbBean.getCzryid());
}
if (config.getDhqz() == null) {
config.setDhqz(dbBean.getDhqz());
}
if (config.getDhcd() == null) {
config.setDhcd(dbBean.getDhcd());
}
if (config.getDhqsh() == null) {
config.setDhqsh(dbBean.getDhqsh());
}
if (config.getDhbc() == null) {
config.setDhbc(dbBean.getDhbc());
}
if (config.getIsopen() == null) {
config.setIsopen(dbBean.getIsopen());
}
if (config.getCurrenttime() == null) {
config.setCurrenttime(dbBean.getCurrenttime());
}
config.setCreatedAt(dbBean.getCreatedAt());
DBA.update(null, config);
}
@Override
public void deleteBusinessNumConfigByIds(List<Integer> ids) {
// 去掉字符串前后中括号
String strIds = org.apache.commons.lang3.StringUtils.strip(ids.toString(), "[]");
DBA.executeProcSql("delete from ywdh_config where pkywdhconfig in ( " + strIds + " )", null);
}
}
YwdhRedisPairRepository(Redis键值对配置 Repository)
import com.yuanbo.chss.domain.business.YwdhRedisPair;
import java.util.List;
public interface YwdhRedisPairRepository {
List<YwdhRedisPair> selectYwdhKeyConfig(YwdhRedisPair ywdhRedisPair);
void insertYwdhRedisPair(YwdhRedisPair ywdhRedisPair);
void updateYwdhKeyConfig(YwdhRedisPair ywdhRedisPair);
void deleteYwdhKeyConfig(YwdhRedisPair ywdhRedisPair);
}
YwdhRedisPairRepositoryImpl(Redis键值对配置 RepositoryImpl)
import com.yuanbo.chss.domain.business.YwdhRedisPair;
import com.yuanbo.hap.util.DBAgent;
import com.yuanbo.hap.util.ParamUtil;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author: DengJia
* @Date: 2022/2/17 11:28
* @Description:
*/
@Repository("YwdhRedisPairRepository")
public class YwdhRedisPairRepositoryImpl implements YwdhRedisPairRepository {
private static final DBAgent DBA = DBAgent.getInstance();
@Override
public List<YwdhRedisPair> selectYwdhKeyConfig(YwdhRedisPair ywdhRedisPair) {
HashMap<String, Object> dataMap = new HashMap<>(4);
ParamUtil.beanToMap(ywdhRedisPair, dataMap, true);
StringBuilder querySql = new StringBuilder("select * from ywdh_redis_pair where sqbm = :sqbm ");
if (dataMap.get("pkpair") != null) {
querySql.append("and pkpair = :pkpair ");
} else {
if (dataMap.get("fkywdhconfig") != null) {
querySql.append("and fkywdhconfig = :fkywdhconfig ");
}
if (dataMap.get("currenttime") != null) {
querySql.append("and currenttime = :currenttime ");
}
if (dataMap.get("keyname") != null) {
querySql.append("and keyname = :keyname ");
}
if (dataMap.get("value") != null) {
querySql.append("and value = :value ");
}
}
List<Map<String, Object>> list = DBA.querySQL(querySql.toString(), dataMap, null);
return ParamUtil.mapsToBeans(list, YwdhRedisPair.class, true);
}
@Override
public void insertYwdhRedisPair(YwdhRedisPair ywdhRedisPair) {
DBA.save(null, ywdhRedisPair);
}
@Override
public void updateYwdhKeyConfig(YwdhRedisPair ywdhRedisPair) {
// Map<String, Object> map = new HashMap<>();
// map.put("SQBM", ywdhRedisPair.getSqbm());
// map.put("KEYNAME", ywdhRedisPair.getKeyname());
// if (ywdhRedisPair.getValue() != null) {
// map.put("VALUE", ywdhRedisPair.getValue());
// }
//
// StringBuilder sb = new StringBuilder("update ywdh_redis_pair set value = 3 ");
//
// sb.append("where sqbm = ::SQBM and keyname = ::KEYNAME");
//
// DBA.executeSQL(sb.toString(), );
DBA.update(null, ywdhRedisPair);
}
@Override
public void deleteYwdhKeyConfig(YwdhRedisPair ywdhRedisPair) {
DBA.delete(null, ywdhRedisPair);
}
}
Service
YwdhConfigBS(业务单号配置 业务接口)
import com.yuanbo.chss.domain.business.YwdhConfig;
import com.yuanbo.hap.webservice.function.FuncResult;
import java.util.Map;
/**
* his业务单号配置 业务接口
*/
public interface YwdhConfigBS {
/**
* 创建单号生成规则的时候,也生成redis键,由于redis未进行持久化配置,同时需要将key记录进mysql。
* 客户端传入的JTLX,代表多条具体类型,以 ',' 逗号分割,分别存储。
*
* @param dataMap 配置信息
* @return 添加成功
*/
FuncResult createBusinessNumConfig(Map<String, Object> dataMap);
/**
* 条件查询业务单号配置
*
* @param dataMap 查询条件
* @return 按条件过滤后的配置信息
*/
FuncResult queryBusinessNumConfig(Map<String, Object> dataMap);
/**
* 按入参TYPE分别进行修改、新增、删除
* 通过时间戳字段(CURRENTTIME)实现乐观锁机制(修改之前查出来的时间戳与数据库的时间戳进行对比,一致方可进行本次修改)
*
* @param dataMap 入参
* @return 修改成功
*/
FuncResult updateBusinessNumConfigByType(Map<String, Object> dataMap);
/**
* 删除业务单号配置
*
* @param dataMap 待删除的配置主键
* @return 删除成功
*/
FuncResult deleteBusinessNumConfigByType(Map<String, Object> dataMap);
}
YwdhConfigBSImpl(业务单号配置 业务类)
import com.yuanbo.chss.domain.business.YwdhConfig;
import com.yuanbo.chss.domain.business.YwdhRedisPair;
import com.yuanbo.chss.domain.log.LogCzrz;
import com.yuanbo.chss.domain.yk.YwdhOpsEnum;
import com.yuanbo.chss.repository.YwdhConfigRepository;
import com.yuanbo.chss.repository.YwdhRedisPairRepository;
import com.yuanbo.common.util.DateTransUtil;
import com.yuanbo.common.util.LoginHelper;
import com.yuanbo.hap.core.exception.AppException;
import com.yuanbo.hap.util.DBAgent;
import com.yuanbo.hap.util.WebServiceUtils;
import com.yuanbo.hap.webservice.function.FuncResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.stream.Collectors;
import static com.yuanbo.hap.util.ParamUtil.*;
import static com.yuanbo.hap.util.ParamUtil.mapToBean;
/**
* @Author: DengJia
* @Date: 2022/2/14 14:30
* @Description: 业务单号配置 业务类
*/
@Service("YwdhConfigBS")
@Transactional
public class YwdhConfigBSImpl implements YwdhConfigBS {
@Autowired
private YwdhConfigRepository ywdhConfigRepository;
@Autowired
private YwdhRedisPairRepository ywdhRedisPairRepository;
@Resource
private RedisTemplate<Object, Object> redisTemplate;
private static final String PREFIX = "INCR";
private static final DBAgent DBA = DBAgent.getInstance();
/**
* 乐观锁机制下执行数据的改动(UPDATE、DELETE)
*/
public static final String OPTIMISTIC_LOCK_UPDATE = "UPDATE";
public static final String OPTIMISTIC_LOCK_DELETE = "DELETE";
@Override
public FuncResult createBusinessNumConfig(Map<String, Object> dataMap) {
// 入参校验
if (dataMap.get("SQBM") == null) {
dataMap.put("SQBM", LoginHelper.getLoginerSQBM());
}
if (dataMap.get("CZRYID") == null) {
dataMap.put("CZRYID", LoginHelper.getLoginerId());
}
if (dataMap.get("LX") == null) {
throw new AppException("LX不可为空!");
}
if (dataMap.get("KSLX") == null) {
throw new AppException("KSLX不可为空!");
}
List<YwdhConfig> configs = new ArrayList<>();
StringBuilder rklxString = new StringBuilder();
List<Integer> rklxList = new ArrayList<>();
if (dataMap.get("JTLX") != null) {
try {
String jtlxString = dataMap.get("JTLX").toString();
if (StringUtils.isNotBlank(jtlxString)) {
String[] jtlxs = jtlxString.split(",");
configs = new ArrayList<>();
for (String jtlx : jtlxs) {
int i = Integer.parseInt(jtlx.trim());
dataMap.put("JTLX", i);
configs.add(getBean(dataMap));
rklxList.add(i);
}
}
} catch (Exception e) {
throw new AppException("请将JTLX以逗号分割传入!");
}
} else {
configs.add(getBean(dataMap));
}
// 检查可行性,及后续操作
configs.forEach(this::checkAvailability);
// 为多个具体类型设置同一套规则(一次添加一套规则)
String nowTimeString = String.valueOf(System.currentTimeMillis());
System.currentTimeMillis();
for (YwdhConfig config : configs) {
config.setCurrenttime(nowTimeString);
// mysql保存自定义的规则
DBA.save(null, config);
}
// 生成key
StringBuilder keyName = new StringBuilder(PREFIX + "_" + dataMap.get("SQBM"));
if (dataMap.get("LX") != null) {
Long dhlx = YwdhOpsEnum.getOpcode(Integer.parseInt(dataMap.get("LX").toString()));
keyName.append("_").append(dhlx);
}
if (dataMap.get("KSLX") != null) {
Integer kslx = Integer.parseInt(dataMap.get("KSLX").toString());
keyName.append("_").append(kslx);
}
if (!rklxList.isEmpty()) {
Collections.sort(rklxList);
rklxList.forEach(rklxString::append);
keyName.append("_").append(rklxString);
}
// mysql保存键
YwdhRedisPair pair = new YwdhRedisPair();
pair.setCurrenttime(nowTimeString);
pair.setSqbm(dataMap.get("SQBM").toString());
pair.setKeyname(keyName.toString());
pair.setValue(dataMap.get("DHQSH").toString());
ywdhRedisPairRepository.insertYwdhRedisPair(pair);
// redis设置键
callRedisToSetKeyAndExpiration(keyName.toString(), Integer.parseInt(dataMap.get("DHQSH").toString()));
return new FuncResult().setMsg("添加成功");
}
@Override
public FuncResult queryBusinessNumConfig(Map<String, Object> dataMap) {
if (dataMap.get("SQBM") == null) {
dataMap.put("SQBM", LoginHelper.getLoginerSQBM());
}
List<Map<String, Object>> list = ywdhConfigRepository.selectYwdhConfig(dataMap);
return new FuncResult().addDataSet("YWDHCONFIG", list);
}
@Override
@Transactional
public FuncResult updateBusinessNumConfigByType(Map<String, Object> dataMap) {
final String currentTimeMillis = String.valueOf(System.currentTimeMillis());
String sqbm = LoginHelper.getLoginerSQBM();
Integer czryid = Integer.parseInt(LoginHelper.getLoginerId().toString());
List[] listArray = (List[]) dataMap.get("YWDHCONFIG");
List<Map<String, Object>> configMapList = listArray[0];
List<String> flagList = listArray[1];
List<YwdhConfig> configBeanList = mapsToBeans(configMapList, YwdhConfig.class, true);
final int dataSize = configMapList.size();
// 设置操作人员
configBeanList.forEach(b -> b.setCzryid(czryid));
List<Integer>
// 之前的具体类型列表
jtlxList0 = new ArrayList<>(),
// 现在的具体类型列表
jtlxList1 = new ArrayList<>();
StringBuilder
// 之前的redis后缀
jtlxStr0 = new StringBuilder(),
// 现在的redis后缀
jtlxStr1 = new StringBuilder();
int addSize = 0, updateSize = 0, deleteSize = 0, unChangedSize = 0;
final String rowOp_unchange = "UnChanged";
for (String flag : flagList) {
switch (flag) {
case WebServiceUtils.rowOp_add:
addSize++;
break;
case WebServiceUtils.rowOp_delete:
deleteSize++;
break;
case WebServiceUtils.rowOp_update:
updateSize++;
break;
case rowOp_unchange:
unChangedSize++;
break;
default:
break;
}
}
boolean
onlyAdd = addSize == dataSize,
onlyDelete = deleteSize == dataSize,
onlyUpdate = updateSize == dataSize,
unChange = unChangedSize == dataSize;
if (unChange) {
return new FuncResult().setMsg("修改成功");
}
if (onlyAdd) {
doOnlyAddAction(configBeanList, jtlxList0, jtlxList1, currentTimeMillis);
} else if (onlyDelete) {
doOnlyDeleteAction(configBeanList, jtlxList0, jtlxList1, currentTimeMillis);
} else {
doElseAction(listArray, jtlxList0, jtlxList1, onlyUpdate, currentTimeMillis);
}
Collections.sort(jtlxList0);
Collections.sort(jtlxList1);
jtlxList0.forEach(jtlxStr0::append);
jtlxList1.forEach(jtlxStr1::append);
// 做好Redis的同步以及MySQL的数据备份
syncAndBackup(configBeanList, jtlxStr0, jtlxStr1, currentTimeMillis);
return new FuncResult().setMsg("修改成功");
}
@Override
public FuncResult deleteBusinessNumConfigByType(Map<String, Object> dataMap) {
if (dataMap.get("YWDHCONFIG") == null) {
throw new AppException("YWDHCONFIG不可为空!");
}
List[] lists = (List[]) dataMap.get("YWDHCONFIG");
List<Map<String, Object>> ywdhConfigs = lists[0];
for (Map<String, Object> ywdhConfigMap : ywdhConfigs) {
// 条件校验
if (ywdhConfigMap.get("SQBM") == null) {
ywdhConfigMap.put("SQBM", LoginHelper.getLoginerSQBM());
}
if (ywdhConfigMap.get("CZRYID") == null) {
ywdhConfigMap.put("CZRYID", LoginHelper.getLoginerId());
}
if (ywdhConfigMap.get("PKYWDHCONFIG") == null) {
throw new AppException("PKYWDHCONFIG不可为空!");
}
}
StringBuilder rklxString = new StringBuilder();
List<Integer> rklxList = new ArrayList<>();
for (Map<String, Object> ywdhConfigMap : ywdhConfigs) {
Map<String, Object> dbYwdhConfigMap = ywdhConfigRepository.selectYwdhConfig(ywdhConfigMap).get(0);
YwdhConfig dbYwdhConfig = getBean(dbYwdhConfigMap);
// 删除配置规则
DBA.delete(null, dbYwdhConfig);
// 记录日志
doLogAction(dbYwdhConfig, null);
if (dbYwdhConfigMap.get("JTLX") != null) {
int jtlx = Integer.parseInt(dbYwdhConfigMap.get("JTLX").toString());
rklxList.add(jtlx);
}
}
// 获取key
Map<String, Object> ywdhConfig = ywdhConfigs.get(0);
StringBuilder keyName = new StringBuilder(PREFIX + "_" + ywdhConfig.get("SQBM"));
if (ywdhConfig.get("LX") != null) {
Long dhlx = YwdhOpsEnum.getOpcode(Integer.parseInt(ywdhConfig.get("LX").toString()));
keyName.append("_").append(dhlx);
}
if (ywdhConfig.get("KSLX") != null) {
Integer kslx = Integer.parseInt(ywdhConfig.get("KSLX").toString());
keyName.append("_").append(kslx);
}
if (!rklxList.isEmpty()) {
List<Integer> sorted = rklxList.stream().sorted().collect(Collectors.toList());
sorted.forEach(rklxString::append);
keyName.append("_").append(rklxString);
}
// 删除redis
redisTemplate.delete(keyName.toString());
// 删除mysql键值
YwdhRedisPair pairCondition = new YwdhRedisPair();
pairCondition.setSqbm(ywdhConfig.get("SQBM").toString());
pairCondition.setKeyname(keyName.toString());
List<YwdhRedisPair> queryResult = ywdhRedisPairRepository.selectYwdhKeyConfig(pairCondition);
if (!queryResult.isEmpty()) {
ywdhRedisPairRepository.deleteYwdhKeyConfig(queryResult.get(0));
}
return new FuncResult().setMsg("删除成功");
}
/**
* 获取Map类型数据的实体类对象
*
* @param dataMap 入参配置信息
* @return 类对象
*/
private YwdhConfig getBean(Map<String, Object> dataMap) {
YwdhConfig bean = new YwdhConfig();
mapToBean(dataMap, bean, true);
return bean;
}
/**
* 针对一次UPDATE里面仅有新增的操作
*
* @param configBeanList 入参配置
* @param jtlxList0 改之前的具体类型列表
* @param jtlxList1 现在的具体类型列表
* @param currentTimeMillis 系统当前时间戳
*/
private void doOnlyAddAction(List<YwdhConfig> configBeanList, List<Integer> jtlxList0, List<Integer> jtlxList1, String currentTimeMillis) {
/*
currenttimeVersion(乐观锁标识),
以时间戳实现乐观锁,只有每次修改前从数据库查出来的时间戳和修改时数据库的数据仍然为此值时,才允许修改数据,
否则已经发生了并行操作,不允许修改。
*/
String currenttimeVersion = "";
YwdhConfig param = configBeanList.get(0);
Map<String, Object> condi = new HashMap<>(4);
condi.put("sqbm", param.getSqbm());
condi.put("dhqz", param.getDhqz());
condi.put("lx", param.getLx());
condi.put("kslx", param.getKslx());
// 记录具体类型id值并且修改时间戳
List<YwdhConfig> queryConfigBeanList = DBA.find(YwdhConfig.class, condi, null);
for (YwdhConfig config : queryConfigBeanList) {
currenttimeVersion = config.getCurrenttime();
jtlxList0.add(config.getJtlx());
config.setCurrenttime(currentTimeMillis);
}
for (YwdhConfig config : configBeanList) {
jtlxList1.add(config.getJtlx());
config.setCurrenttime(currentTimeMillis);
}
jtlxList1.addAll(jtlxList0);
// 乐观锁机制下执行数据修改保存操作
optimisticLockingDataChange(currenttimeVersion, queryConfigBeanList, OPTIMISTIC_LOCK_UPDATE);
DBA.save(null, configBeanList);
}
/**
* 针对一次UPDATE里面仅有删除的操作
*
* @param configBeanList 入参配置
* @param jtlxList0 改之前的具体类型列表
* @param jtlxList1 现在的具体类型列表
* @param currentTimeMillis 系统当前时间戳
*/
private void doOnlyDeleteAction(List<YwdhConfig> configBeanList, List<Integer> jtlxList0, List<Integer> jtlxList1, String currentTimeMillis) {
/*
currenttimeVersion(乐观锁标识),
以时间戳实现乐观锁,只有每次修改前从数据库查出来的时间戳和修改时数据库的数据仍然为此值时,才允许修改数据,
否则已经发生了并行操作,不允许修改。
*/
String currenttimeVersion = "";
YwdhConfig param = configBeanList.get(0);
Map<String, Object> condi = new HashMap<>(4);
condi.put("sqbm", param.getSqbm());
condi.put("dhqz", param.getDhqz());
condi.put("lx", param.getLx());
condi.put("kslx", param.getKslx());
List<YwdhConfig> queryConfigBeanList = DBA.find(YwdhConfig.class, condi, null);
currenttimeVersion = queryConfigBeanList.get(0).getCurrenttime();
// 记录具体类型id值并且修改时间戳
for (YwdhConfig config : queryConfigBeanList) {
jtlxList0.add(config.getJtlx());
}
List<Integer> needDel = configBeanList.stream().map(YwdhConfig::getJtlx).collect(Collectors.toList());
List<YwdhConfig> retainConfigList = queryConfigBeanList.stream().filter(jtlx -> !needDel.contains(jtlx.getJtlx())).collect(Collectors.toList());
List<Integer> retain = retainConfigList.stream().map(YwdhConfig::getJtlx).collect(Collectors.toList());
jtlxList1.addAll(retain);
for (YwdhConfig config : retainConfigList) {
config.setCurrenttime(currentTimeMillis);
}
List<Integer> pkids = configBeanList.stream().map(YwdhConfig::getPkywdhconfig).collect(Collectors.toList());
ywdhConfigRepository.deleteBusinessNumConfigByIds(pkids);
// 乐观锁执行修改
optimisticLockingDataChange(currenttimeVersion, retainConfigList, OPTIMISTIC_LOCK_UPDATE);
// 记录批量删除日志
List<YwdhConfig> deleteSet = queryConfigBeanList.stream().filter(b -> pkids.contains(b.getPkywdhconfig())).collect(Collectors.toList());
deleteSet.forEach(config -> doLogAction(config, null));
}
/**
* 针对一次UPDATE里面不是仅有增加操作或不是仅有删除操作的其他操作
*
* @param listArray 原生列表数组
* @param jtlxList0 改之前的具体类型列表
* @param jtlxList1 现在的具体类型列表
* @param onlyUpdate 仅有修改的操作
* @param currentTimeMillis 系统当前时间戳
*/
private void doElseAction(List[] listArray, List<Integer> jtlxList0, List<Integer> jtlxList1, boolean onlyUpdate, String currentTimeMillis) {
List<Map<String, Object>> configMapList = listArray[0];
List<String> flagList = listArray[1];
List<YwdhConfig> configBeanList = mapsToBeans(configMapList, YwdhConfig.class, true);
final int dataSize = configMapList.size();
Integer czryid = Integer.parseInt(LoginHelper.getLoginerId().toString());
List<YwdhConfig> allDbConfigBeans = new ArrayList<>();
if (!onlyUpdate) {
// 获取所涉及到的所有具体类型的数据库记录
allDbConfigBeans = getYwdhConfigs(configMapList, flagList);
}
// 通过flag类型来进行相应的操作,日志记录等
for (int i = 0; i < dataSize; i++) {
String flag = flagList.get(i);
Map<String, Object> map = configMapList.get(i);
YwdhConfig bean = configBeanList.get(i);
if (WebServiceUtils.rowOp_add.equalsIgnoreCase(flag)) {
bean.setCurrenttime(currentTimeMillis);
bean.setCzryid(czryid);
// 新增
DBA.save(null, bean);
// 记录具体类型id值
jtlxList1.add(bean.getJtlx());
} else if (WebServiceUtils.rowOp_delete.equalsIgnoreCase(flag)) {
YwdhConfig
paramConfig = getBean(map),
dbConfig = getBean(ywdhConfigRepository.selectYwdhConfig(map).get(0));
// 乐观锁机制执行删除
List<YwdhConfig> deleteConfigBeanList = new ArrayList<>();
deleteConfigBeanList.add(paramConfig);
optimisticLockingDataChange(dbConfig.getCurrenttime(), deleteConfigBeanList, OPTIMISTIC_LOCK_DELETE);
// 记录删除日志
doLogAction(dbConfig, null);
// 记录具体类型id值
jtlxList0.add(dbConfig.getJtlx());
} else if (WebServiceUtils.rowOp_update.equalsIgnoreCase(flag)) {
YwdhConfig
paramConfig = getBean(map),
dbConfig = getBean(ywdhConfigRepository.selectYwdhConfig(map).get(0));
paramConfig.setCurrenttime(currentTimeMillis);
paramConfig.setCzryid(czryid);
// 乐观锁机制执行修改
List<YwdhConfig> updateConfigBeanList = new ArrayList<>();
updateConfigBeanList.add(paramConfig);
optimisticLockingDataChange(dbConfig.getCurrenttime(), updateConfigBeanList, OPTIMISTIC_LOCK_UPDATE);
// 记录修改日志
doLogAction(dbConfig, paramConfig);
// 记录具体类型id值
jtlxList0.add(dbConfig.getJtlx());
jtlxList1.add(dbConfig.getJtlx());
}
}
if (!onlyUpdate) {
// 可能有增删和未修改的数据,需要对未修改的数据执行相关操作
doMoreAction(allDbConfigBeans, jtlxList0, jtlxList1, currentTimeMillis);
}
}
/**
* 乐观锁机制执行数据改动(UPDATE、DELETE)
*
* @param currenttimeVersion 乐观锁标识
* @param changeDataList 需要进行改动的数据列表
* @param flag UPDATE or DELETE
*/
private void optimisticLockingDataChange(String currenttimeVersion, List<YwdhConfig> changeDataList, String flag) {
if (OPTIMISTIC_LOCK_UPDATE.equalsIgnoreCase(flag)) {
for (YwdhConfig config : changeDataList) {
StringBuilder spliceSQL = new StringBuilder(" ");
Class<YwdhConfig> c = YwdhConfig.class;
Field[] fields = c.getDeclaredFields();
// 反射拼接更新语句的SET项
for (Field field : fields) {
field.setAccessible(true);
Class<?> type = field.getType();
String name = field.getName();
if ("createdAt".equalsIgnoreCase(name) || "updatedAt".equalsIgnoreCase(name)) {
continue;
}
Object value = null;
try {
value = field.get(config);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (type == String.class) {
spliceSQL.append(name).append("='").append(value).append("',");
} else {
spliceSQL.append(name).append("=").append(value).append(",");
}
}
String sqlToString = spliceSQL.substring(0, spliceSQL.length() - 1);
String updateSQL = "update ywdh_config set " + sqlToString + " where PKYWDHCONFIG=" + config.getPkywdhconfig() + " and CURRENTTIME=" + currenttimeVersion;
if (DBA.executeSQL(updateSQL, null) != 1) {
throw new AppException("当前页面数据已被更改,请刷新页面后再试!");
}
}
} else if (OPTIMISTIC_LOCK_DELETE.equalsIgnoreCase(flag)) {
for (YwdhConfig config : changeDataList) {
String deleteSQL = "delete from ywdh_config where PKYWDHCONFIG=" + config.getPkywdhconfig() + " and CURRENTTIME=" + currenttimeVersion;
if (DBA.executeSQL(deleteSQL, null) != 1) {
throw new AppException("当前页面数据已被更改,请刷新页面后再试!");
}
}
}
}
/**
* 获取所涉及到的所有具体类型的数据库记录
*
* @param configMapList 入参配置集合
* @param flagList 入参标志集合
* @return 所有相关的配置项(即每一个具体类型的数据记录)
*/
private List<YwdhConfig> getYwdhConfigs(List<Map<String, Object>> configMapList, List<String> flagList) {
int dataSize = configMapList.size();
List<YwdhConfig> allDbConfigBeans;
Map<String, Object> oneMap = null;
for (int i = 0; i < dataSize; i++) {
// 随便选择一个修改的或者删除的(为了获取时间戳),通过时间戳查询数据库里的所有config
boolean deleteOrUpdate = WebServiceUtils.rowOp_delete.equalsIgnoreCase(flagList.get(i))
|| WebServiceUtils.rowOp_update.equalsIgnoreCase(flagList.get(i));
if (deleteOrUpdate) {
oneMap = configMapList.get(i);
break;
}
}
String dbTime =
ywdhConfigRepository.selectYwdhConfig(oneMap)
.get(0).get("CURRENTTIME").toString();
Map<String, Object> condi = new HashMap<>(2);
condi.put("SQBM", LoginHelper.getLoginerSQBM());
condi.put("CURRENTTIME", dbTime);
allDbConfigBeans = mapsToBeans(ywdhConfigRepository.selectYwdhConfig(condi),
YwdhConfig.class, true);
return allDbConfigBeans;
}
/**
* 可能有增删和未修改的数据,需要对未修改的数据执行相关操作
*
* @param allDbConfigBeans 涉及到的所有具体类型的业务配置
* @param jtlxList0 改之前的具体类型列表
* @param jtlxList1 现在的具体类型列表
* @param currentTimeMillis 系统当前时间戳
*/
private void doMoreAction(List<YwdhConfig> allDbConfigBeans, List<Integer> jtlxList0, List<Integer> jtlxList1, String currentTimeMillis) {
List<YwdhConfig> unchangedList =
allDbConfigBeans.stream()
.filter(b -> !jtlxList0.contains(b.getJtlx()) && !jtlxList1.contains(b.getJtlx()))
.collect(Collectors.toList());
List<Integer> unchangedJtlxs =
unchangedList.stream()
.map(YwdhConfig::getJtlx).collect(Collectors.toList());
jtlxList0.addAll(unchangedJtlxs);
jtlxList1.addAll(unchangedJtlxs);
unchangedList.forEach(b -> b.setCurrenttime(currentTimeMillis));
DBA.update(null, unchangedList);
}
/**
* 执行Redis的单号起始号改动以及在MySQL做好备份(用作在Redis数据丢失之后通过MySQL找回数据)
*
* @param configBeanList 入参配置
* @param jtlxStr0 改之前的具体类型
* @param jtlxStr1 现在的具体类型
* @param currentTimeMillis 系统当前时间戳
*/
private void syncAndBackup(List<YwdhConfig> configBeanList, StringBuilder jtlxStr0, StringBuilder jtlxStr1, String currentTimeMillis) {
String sqbm = LoginHelper.getLoginerSQBM();
YwdhConfig config = configBeanList.get(0);
// 获取keyName
StringBuilder
keyName0 = new StringBuilder(PREFIX + "_" + sqbm),
keyName1 = new StringBuilder(PREFIX + "_" + sqbm);
if (config.getLx() != null) {
Long dhlx = YwdhOpsEnum.getOpcode(config.getLx());
keyName0.append("_").append(dhlx);
keyName1.append("_").append(dhlx);
}
if (config.getKslx() != null) {
keyName0.append("_").append(config.getKslx());
keyName1.append("_").append(config.getKslx());
}
if (StringUtils.isNotBlank(jtlxStr0) && !Objects.equals("null", jtlxStr0.toString())) {
keyName0.append("_").append(jtlxStr0);
}
if (StringUtils.isNotBlank(jtlxStr1) && !Objects.equals("null", jtlxStr1.toString())) {
keyName1.append("_").append(jtlxStr1);
}
// 删除mysql旧键值
YwdhRedisPair pair0 = new YwdhRedisPair(null, null, sqbm, keyName0.toString(), null);
List<YwdhRedisPair> pairQueryResult = ywdhRedisPairRepository.selectYwdhKeyConfig(pair0);
DBA.delete(null, pairQueryResult);
// 添加mysql新键值
YwdhRedisPair pair1 = new YwdhRedisPair(null, currentTimeMillis, sqbm, keyName1.toString(), config.getDhqsh().toString());
DBA.save(null, pair1);
// 删除旧redis
redisTemplate.delete(keyName0.toString());
// 添加新redis
callRedisToSetKeyAndExpiration(keyName1.toString(), Integer.parseInt(config.getDhqsh().toString()));
}
/**
* 通过反射记录日志
*
* @param from 从什么
* @param to 变成了什么
*/
private void doLogAction(YwdhConfig from, YwdhConfig to) {
boolean
del = from != null && to == null,
mod = from != null && to != null;
DBAgent dba = DBAgent.getInstance();
// 获取所有字段
Field[] fields = YwdhConfig.class.getDeclaredFields();
LogCzrz rz = new LogCzrz();
StringBuilder tableColumn = new StringBuilder();
StringBuilder xgxx = new StringBuilder();
for (Field field : fields) {
// 获取属性名
String attrName = field.getName();
// 将属性名的首字母变为大写,为set/get方法做准备
String methodName = attrName.substring(0, 1).toUpperCase() + attrName.substring(1);
Object result = null;
Object dbObj = null;
try {
// 获取类当前属性的set/getXXX方法(只获取公有方法)
Method method = YwdhConfig.class.getMethod("get" + methodName);
// 执行该方法
if (mod) {
result = method.invoke(to);
}
dbObj = method.invoke(from);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
try {
result = field.get(to);
dbObj = field.get(from);
} catch (IllegalAccessException illegalAccessException) {
illegalAccessException.printStackTrace();
}
e.printStackTrace();
}
// 修改又是字段给的null,这种情况不记录日志,其他都记录
if (!mod || result != null) {
// 判断字段并进行日志记录
if (!Objects.equals(dbObj, result)) {
tableColumn.append(attrName).append(", ");
xgxx.append(attrName).append(": ").append(dbObj).append(" -> ").append(result).append(" | ");
}
}
}
if (tableColumn.length() > 0) {
rz.setTableName("ywdh_config");
rz.setTableId(from.getPkywdhconfig().toString());
rz.setSqbm(LoginHelper.getLoginerSQBM());
rz.setXgysbm(LoginHelper.getLoginerBm());
rz.setXgysmc(LoginHelper.getLoginerName());
rz.setTableColumn(tableColumn.toString());
rz.setXgxx(xgxx.toString());
Map<String, Integer> m = DateTransUtil.getOLEDateFromDate(new Date());
rz.setXgrq(m.get("days"));
rz.setXgsj(m.get("second"));
try {
InetAddress host = InetAddress.getLocalHost();
rz.setMachineIp(host.getHostAddress());
rz.setMachineName(host.getHostName());
} catch (UnknownHostException e) {
rz.setMachineName(null);
rz.setMachineIp(null);
}
dba.save("LogCzrz", rz);
}
}
/**
* 已经进行了业务单号配置的科室将不允许再次设置
* 一个用户不可对同一社区,同一单号类型,同一药库,同一具体操作设置两套不同的规则
*
* @param config 业务单号配置
*/
private void checkAvailability(YwdhConfig config) {
String sqbm = config.getSqbm() == null ? LoginHelper.getLoginerSQBM() : config.getSqbm();
HashMap<String, Object> condition = new HashMap<>(4);
condition.put("SQBM", sqbm);
if (config.getLx() != null) {
condition.put("LX", config.getLx());
}
if (config.getKslx() != null) {
condition.put("KSLX", config.getKslx());
}
if (config.getJtlx() != null) {
condition.put("JTLX", config.getJtlx());
}
List<Map<String, Object>> queryResult = ywdhConfigRepository.selectYwdhConfig(condition);
if (!queryResult.isEmpty()) {
throw new AppException("配置 lx:" + config.getLx() + " kslx:" + config.getKslx() + " jtlx:" + config.getJtlx() + " 已存在!");
}
}
/**
* 设置redis键的同时也设置他的时效性(默认采用当天有效)
*
* @param key 键
* @param value 值
*/
private void callRedisToSetKeyAndExpiration(String key, Object value) {
Calendar calendar = new GregorianCalendar();
// 时
calendar.set(Calendar.HOUR_OF_DAY, 23);
// 分
calendar.set(Calendar.MINUTE, 50);
// 秒
calendar.set(Calendar.SECOND, 0);
// 毫秒
calendar.set(Calendar.MILLISECOND, 0);
redisTemplate.opsForValue().set(key, value);
redisTemplate.expireAt(key, calendar.getTime());
}
}
Util
NumberHelper
public interface NumberHelper {
/**
* 生成药库增序单号
*
* @param ywdhConfig 业务单号生成规则
* @param keyName Redis唯一键:前缀(INCR) + opcode + "_" + sqbm
* @return 业务单号
*/
String generateIncrementSequenceNumber(YwdhConfig ywdhConfig, String keyName);
}
NumberHelperImpl
@Service("NumberHelper")
public class NumberHelperImpl implements NumberHelper {
@Override
public String generateIncrementSequenceNumber(YwdhConfig config, String keyName) {
DBAgent dbAgent = DBAgent.getInstance();
// 单号起始号
long dhqsh = Long.parseLong(config.getDhqsh().toString());
if (redisTemplate.hasKey(keyName)) {
// 单号步长
long dhbc = Long.parseLong(config.getDhbc().toString());
dhqsh = redisTemplate.opsForValue().increment(keyName, dhbc);
} else {
redisTemplate.opsForValue().set(keyName, dhqsh);
}
// 单号长度
Integer dhcd = config.getDhcd();
// 前补零操作
String str = IntStream.range(0, dhcd).mapToObj(i -> "0").collect(Collectors.joining());
DecimalFormat df = new DecimalFormat(str);
String format = df.format(dhqsh);
String s = "select BM from zd_ks where sqbm = ::SQBM and sysid = ::SYSID";
Map<String, Object> map = new HashMap<>();
map.put("SQBM", config.getSqbm());
map.put("SYSID", config.getKslx());
List<Map<String, Object>> result = dbAgent.querySQL(s, map, null);
Object bm = result.get(0).get("BM");
// 拼接单号,比如首单入库将可拼接为:RK0380000000000001
return config.getDhqz() + bm + format;
}
}
具体业务(药库入库)
public FuncResult businessYkrk(Map dataMap) {
DBAgent dba = DBAgent.getInstance();
List[] ykrkd0 = (List[]) dataMap.get("YK_RKD0");
List[] ykrkd1 = (List[]) dataMap.get("YK_RKD1");
Map<String, Object> ykrkd = (Map<String, Object>) ykrkd0[0].get(0);
String sqbm = LoginHelper.getLoginerSQBM();
int czryid = Integer.parseInt(LoginHelper.getLoginerId().toString());
// 通过配置来判断是否递增生成入库单号
YwdhConfig config = null;
boolean isIncrement = false;
// 按客户端页面给的类型来筛查,寻找相应的配置。
Map<String, Object> condi = new HashMap<>(8);
condi.put("SQBM", sqbm);
condi.put("CZRYID", czryid);
condi.put("LX", YwdhOpsEnum.getLx(G3GlobalNames.YK_RKD0));
// 药库类型
if (ykrkd.get("KFID") != null) {
condi.put("KSLX", ykrkd.get("KFID"));
} else if (ykrkd.get("kfid") != null) {
condi.put("KSLX", ykrkd.get("kfid"));
}
// 入库类型
if (ykrkd.get("RKLX") != null) {
condi.put("JTLX", ykrkd.get("RKLX"));
} else if (ykrkd.get("rklx") != null) {
condi.put("JTLX", ykrkd.get("rklx"));
}
// 获取单号的配置规则
List<YwdhConfig> queryBeanResult =
mapsToBeans(ywdhConfigRepository.selectYwdhConfig(condi), YwdhConfig.class, true);
if (!queryBeanResult.isEmpty()) {
config = queryBeanResult.get(0);
isIncrement = Objects.equals(1, config.getIsopen());
}
// redis键
String keyName = null;
// redis键的原值
Object originalObj = null;
// redis键的现值
Object presentObj = null;
if (isIncrement) {
// 通过配置来生成redis的key
YwdhRedisPair pairCondi = new YwdhRedisPair(sqbm, config.getCurrenttime());
List<YwdhRedisPair> pairSelectResult = ywdhRedisPairRepository.selectYwdhKeyConfig(pairCondi);
YwdhRedisPair pair = pairSelectResult.get(0);
keyName = pair.getKeyname();
originalObj = redisTemplate.opsForValue().get(keyName);
// redis未获取到key,从mysql进行手动恢复并为其赋值
if (originalObj == null) {
redisTemplate.opsForValue().set(keyName, Long.parseLong(pair.getValue()));
}
// 入库单号赋值替换
List rkd0s = ykrkd0[0];
List rkd0Flags = ykrkd0[1];
int dataSize = rkd0s.size();
for (int i = 0; i < dataSize; i++) {
Object rkd0Flag = rkd0Flags.get(i);
if (WebServiceUtils.rowOp_add.equalsIgnoreCase(rkd0Flag.toString())) {
Object rkd0 = rkd0s.get(i);
Map<String, Object> rkd = (Map<String, Object>) rkd0;
String presentValue = dhs.generateIncrementSequenceNumber(config, keyName);
if (rkd.get("RKDH") != null) {
rkd.put("RKDH", presentValue);
} else if (rkd.get("rkdh") != null) {
rkd.put("rkdh", presentValue);
}
}
}
presentObj = redisTemplate.opsForValue().get(keyName);
Integer presentVal = Integer.parseInt(presentObj.toString());
// 生成单号之后需要修改配置信息(更新单号起始号)
Map<String, Object> update = new HashMap<>();
update.put("SQBM", sqbm);
update.put("CURRENTTIME", config.getCurrenttime());
List<YwdhConfig> needToUpdateConfigs =
mapsToBeans(ywdhConfigRepository.selectYwdhConfig(update),
YwdhConfig.class, true);
needToUpdateConfigs.forEach(b -> b.setDhqsh(presentVal));
dba.update(null, needToUpdateConfigs);
// 并且修改mysql键值对
pairSelectResult.forEach(b -> b.setValue(presentVal.toString()));
dba.update(null, pairSelectResult);
}
FuncResult funcResult;
try {
// TODO 调用真实的入库业务
funcResult = doRKAction(ykrkd0, ykrkd1);
} catch (Exception e) {
if (isIncrement) {
// 发生异常需要将redis中设置的递增序列手动回滚
if (originalObj == null) {
redisTemplate.delete(keyName);
} else {
redisTemplate.opsForValue().set(keyName, originalObj);
}
}
// 异常抛出用作程序本身的回滚
throw AppException.warn(e.getMessage(), e);
}
return funcResult;
}
DJOSIMON