背景说明:
在处置惩罚复杂业务的时候,特别是研发自测期间,经常会产生很多不必要的垃圾数据。
技能原理:
先将要存入数据库的数据放在缓存中,等所有业务代码实行完后,再同一生存;
代码如下:
  - @Slf4j
- public class BaseService<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements IService<T> {
- /**
- * 构建查询
- * @param e
- * @return
- */
- @SneakyThrows
- public <E extends Object> EntityWrapper<E> wrapperTable(E e, String tableName, Boolean like) {
- EntityWrapper<E> wrapper = new EntityWrapper<>();
- for (String field: JSON.parseObject(JSON.toJSONString(e)).keySet()) {
- Field ld = findField(e.getClass(), field);
- if(ld == null || !checkField(ld)) continue;
- String _s = columnName(ld);
- String m =null;
- if(_s.contains("_")){
- m = StrUtil.toCamelCase("get_"+_s);
- }else {m=StrUtil.genGetter(_s);}
- Object o = e.getClass().getMethod(m).invoke(e);
- if(ObjectUtils.isEmpty(o)) continue;
- if(!ObjectUtils.isEmpty(tableName)) {
- _s = tableName+"."+_s;
- }
- if(like) wrapper.like(_s,o.toString());
- else wrapper.eq(_s , o);
- }
- return wrapper;
- }
- /**
- * 构建查询
- * @param e
- * @return
- */
- @SneakyThrows
- public <E extends Object> EntityWrapper<E> wrapper(E e, Boolean like) {
- return wrapperTable(e,null,like);
- }
- /**
- * 构建查询
- * @param e
- * @return
- */
- @SneakyThrows
- public <E extends Object> EntityWrapper<E> wrapper(E e) {
- return wrapperTable(e,null,false);
- }
- private boolean checkField(Field field) {
- if(!field.isAnnotationPresent(TableId.class) && !field.isAnnotationPresent(TableField.class)) return false;
- if(field.isAnnotationPresent(TableField.class) && !field.getAnnotation(TableField.class).exist()) return false;
- return true;
- }
- private Field findField(Class c,String field) {
- if(c == Object.class) return null;
- try {
- return c.getDeclaredField(field);
- } catch (NoSuchFieldException e) {
- return findField(c.getSuperclass(),field);
- }
- }
- private String columnName(Field field) {
- if(field.isAnnotationPresent(TableId.class) && ObjectUtils.isNotEmpty(field.getAnnotation(TableId.class).value())) return field.getAnnotation(TableId.class).value();
- if(field.isAnnotationPresent(TableField.class) && field.getAnnotation(TableField.class).exist() && ObjectUtils.isNotEmpty(field.getAnnotation(TableField.class).value())) return field.getAnnotation(TableField.class).value();
- return StrUtil.toUnderlineCase(field.getName());
- }
- @Transactional(rollbackFor = Exception.class)
- @Override
- public boolean insertOrUpdate(T entity){
- if(entity instanceof TransacationalEntity) {
- //截流所有 TransacationalEntity 下的新增
- if(((TransacationalEntity) entity).getSqlStatus().equalsIgnoreCase("begin")) {
- return TransactionalUtils.add(this,((TransacationalEntity) entity));
- } else if(((TransacationalEntity) entity).getSqlStatus().equalsIgnoreCase("commit")) {
- return TransactionalUtils.commit(((TransacationalEntity) entity).getSqlVersion());
- } else {
- return super.insertOrUpdate(entity);
- }
- } else {
- return super.insertOrUpdate(entity);
- }
- }
- @SneakyThrows
- @Transactional(rollbackFor = Exception.class)
- @Override
- public boolean insertOrUpdateBatch(List<T> entityList) {
- try {
- this.baseMapper.getClass().getMethod("insertOrUpdateBatch", List.class).invoke(this.baseMapper,entityList);
- } catch (NoSuchMethodException e) {
- log.warn("mapper类{},不存在方法{},替换为service执行",this.baseMapper.getClass(),"insertOrUpdateBatch");
- super.insertOrUpdateBatch(entityList);
- }
- return true;
- }
- }
复制代码 业务父类其他方法可以忽略,都是懒得写xml但是版本又不允许升级,偷懒写的sql条件辅助工具。
主要要关注以下两个方法:
第一个,用于截流原来的生存方法,将要生存的数据存入缓存中。- @Transactional(rollbackFor = Exception.class)
- @Override
- public boolean insertOrUpdate(T entity){
- if(entity instanceof TransacationalEntity) {
- //截流所有 TransacationalEntity 下的新增
- if(((TransacationalEntity) entity).getSqlStatus().equalsIgnoreCase("begin")) {
- return TransactionalUtils.add(this,((TransacationalEntity) entity));
- } else if(((TransacationalEntity) entity).getSqlStatus().equalsIgnoreCase("commit")) {
- return TransactionalUtils.commit(((TransacationalEntity) entity).getSqlVersion());
- } else {
- return super.insertOrUpdate(entity);
- }
- } else {
- return super.insertOrUpdate(entity);
- }
- }
复制代码 第二个,用于末了同一处置惩罚生存,我这里偷懒了,使用了代码生成器,所以xml中已经有了 insertOrupdataBatch.- @SneakyThrows
- @Transactional(rollbackFor = Exception.class)
- @Override
- public boolean insertOrUpdateBatch(List<T> entityList) {
- try {
- this.baseMapper.getClass().getMethod("insertOrUpdateBatch", List.class).invoke(this.baseMapper,entityList);
- } catch (NoSuchMethodException e) {
- log.warn("mapper类{},不存在方法{},替换为service执行",this.baseMapper.getClass(),"insertOrUpdateBatch");
- super.insertOrUpdateBatch(entityList);
- }
- return true;
复制代码- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public class TransacationalEntity {
- /**
- * begin null commit
- */
- @TableField(exist = false)
- @ApiModelProperty(hidden = true)
- private String sqlStatus;
- /**
- * begin null commit
- */
- @TableField(exist = false)
- @ApiModelProperty(hidden = true)
- private String sqlVersion;
- }
复制代码 Pojo父类  - public class TransactionalUtils {
- static volatile ConcurrentHashMap<String, ConcurrentHashMap<BaseService, CopyOnWriteArrayList<Object>>> cMap = new ConcurrentHashMap<>();
- static volatile ConcurrentHashMap<String,Long> tMap = new ConcurrentHashMap<>();
- public static <E extends TransacationalEntity> boolean add(BaseService service, E e) {
- long millis = System.currentTimeMillis();
- synchronized(service.getClass()) {
- ConcurrentHashMap<BaseService, CopyOnWriteArrayList<Object>> map = cMap
- .getOrDefault(e.getSqlVersion(), new ConcurrentHashMap<>());
- CopyOnWriteArrayList<Object> list = map.getOrDefault(service, new CopyOnWriteArrayList<>());
- list.add(e);
- map.put(service, list);
- cMap.put(e.getSqlVersion(), map);
- tMap.put(e.getSqlVersion(),tMap.getOrDefault(e.getSqlVersion(), 0L)+System.currentTimeMillis()-millis) ;
- }
- return true;
- }
- @SneakyThrows
- public static boolean commit(String key) {
- long millis = System.currentTimeMillis();
- int size = 0;
- for (Map.Entry<BaseService, CopyOnWriteArrayList<Object>> entry : cMap.remove(key).entrySet()) {
- entry.getKey().insertOrUpdateBatch(entry.getValue());
- size+=entry.getValue().size();
- }
- System.out.println("批量业务入队总量" + size);
- System.out.println("批量业务入队耗时" + tMap.remove(key));
- System.out.println("批量业务提交耗时" + (System.currentTimeMillis()-millis));
- return true;
- }
- }
复制代码 核心工具类以下是调用示例:- String tranId = IdUtil.simpleUUID();
- Map<String, Object> userMap = new HashMap();
- userMap.put("sqlStatus","begin");
- userMap.put("sqlVersion", tranId);
- propretyDye(beans,userMap);
- insertOrUpdate(Arrays.asList(beans));
- TransactionalUtils.commit(tranId);
复制代码 先给要截流的数据加上版本号和标识,其实只要一个版本号就可以了,sqlStatus这个字段懒得删除了。
版本号主要用来在缓存中分组,隔离其他业务提交。
附带一个参数处置惩罚的小工具,有时候要重复的一层层赋值,太懒了,所以写个工具,让机器本身给我处置惩罚所有数据的值,用法如上面的示例,没仔细检查,偶然会发生栈溢出,但是不影响,应该是项目的全局配置不够造成的:- /**
- * 属性染色
- * 如果对象 o 包含 propreties 的key,则设置key对应的值
- * 处理对象和对象中所有的子对象
- * @param o
- * @param propreties
- * @return
- */
- @SneakyThrows
- public static Object propretyDye(Object o, Map<String,Object> propreties) {
- if(o instanceof Collection) for (Object object : (Collection<?>) o) {
- propretyDye(object,propreties);
- }
- Class<?> aClass = o.getClass();
- while (aClass instanceof Object) {
- for (Field field : aClass.getDeclaredFields()) {
- field.setAccessible(true);
- if(propreties.containsKey(field.getName())) field.set(o,propreties.get(field.getName()));
- if(field.get(o) instanceof Collection) for (Object object : (Collection<?>) field.get(o)) {
- propretyDye(object,propreties);
- }
- if(field.get(o) instanceof Object && BeanUtil.isBean(field.get(o).getClass())) propretyDye(field.get(o),propreties);
- }
- aClass = aClass.getSuperclass();
- }
- return o;
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |