1033 lines
37 KiB
Java
1033 lines
37 KiB
Java
package com.pictc.utils;
|
||
|
||
import java.io.Serializable;
|
||
import java.math.BigDecimal;
|
||
import java.math.BigInteger;
|
||
import java.nio.charset.Charset;
|
||
import java.sql.Date;
|
||
import java.sql.ResultSet;
|
||
import java.sql.SQLException;
|
||
import java.sql.Time;
|
||
import java.sql.Timestamp;
|
||
import java.sql.Types;
|
||
import java.time.LocalDate;
|
||
import java.time.LocalDateTime;
|
||
import java.time.LocalTime;
|
||
import java.time.OffsetDateTime;
|
||
import java.time.OffsetTime;
|
||
import java.time.ZoneId;
|
||
import java.time.ZonedDateTime;
|
||
import java.util.ArrayList;
|
||
import java.util.Collections;
|
||
import java.util.Comparator;
|
||
import java.util.HashSet;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
import java.util.Map.Entry;
|
||
import java.util.Objects;
|
||
import java.util.Set;
|
||
import java.util.function.Function;
|
||
import java.util.stream.Collectors;
|
||
|
||
import javax.servlet.http.HttpServletRequest;
|
||
import javax.validation.Valid;
|
||
|
||
import org.springframework.stereotype.Component;
|
||
import org.springframework.web.context.request.RequestContextHolder;
|
||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||
|
||
import com.alibaba.fastjson.JSON;
|
||
import com.alibaba.fastjson.JSONArray;
|
||
import com.alibaba.fastjson.JSONObject;
|
||
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
|
||
import com.alibaba.nacos.shaded.com.google.common.collect.Maps;
|
||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
|
||
import com.esotericsoftware.kryo.kryo5.minlog.Log;
|
||
import com.google.api.client.util.Sets;
|
||
import com.pictc.annotations.datalog.JoinCaseType;
|
||
import com.pictc.annotations.datalog.JoinValueType;
|
||
import com.pictc.annotations.datalog.LogJoin;
|
||
import com.pictc.annotations.datalog.LogJoinColumn;
|
||
import com.pictc.annotations.datalog.ValueDirectionType;
|
||
import com.pictc.converts.ConverUtil;
|
||
import com.pictc.datalog.LogFieldInfo;
|
||
import com.pictc.datalog.LogJoinInfo;
|
||
import com.pictc.datalog.LogTableInfo;
|
||
import com.pictc.enums.BusinessCode;
|
||
import com.pictc.enums.ExceptionCommonCode;
|
||
import com.pictc.exceptions.OrmException;
|
||
import com.pictc.jdbc.JdbcContext;
|
||
import com.pictc.jdbc.ResultSetUtils;
|
||
import com.pictc.jdbc.model.JdbcParam;
|
||
import com.xjrsoft.common.enums.YesOrNoEnum;
|
||
import com.xjrsoft.common.exception.BusinessException;
|
||
import com.xjrsoft.common.utils.SecureUtil;
|
||
import com.xjrsoft.module.datalog.entity.DataChangeLog;
|
||
import com.xjrsoft.module.datalog.entity.json.FieldChange;
|
||
import com.xjrsoft.module.datalog.service.DatalogService;
|
||
import com.xjrsoft.module.datalog.vo.DataChangeLogVo;
|
||
import com.xjrsoft.module.datalog.vo.OperationType;
|
||
import com.xjrsoft.module.organization.dto.UserDto;
|
||
|
||
import cn.hutool.core.bean.BeanUtil;
|
||
import cn.hutool.core.util.IdUtil;
|
||
import lombok.NonNull;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
|
||
@Slf4j
|
||
@SuppressWarnings({"unused","rawtypes","unchecked"})
|
||
@Component
|
||
public class DataLogTools {
|
||
|
||
private static Map<Class<?>,LogTableInfo> annotations = Maps.newHashMap();
|
||
|
||
private static Map<String,Class<?>> entitys = Maps.newHashMap();
|
||
|
||
private static Set<String> logTables = null;
|
||
|
||
private static Object lock = new Object();
|
||
|
||
public static final String SQL_HAS_TABLE = "select count(*) from log_table_info where tbl_name = ?";
|
||
|
||
public static final String SQL_INST_TABLE = "INSERT INTO log_table_info (tbl_name) VALUES (?);";
|
||
|
||
public static final String SQL_LOG_TABLE_LIST = "select tbl_name FROM log_table_info";
|
||
|
||
public static final String SQL_PLACEHOLDER = "\\$\\{TBL_NAME\\}";
|
||
|
||
public static final String[] SQL_CREATE_TABLE = {
|
||
"CREATE TABLE ${TBL_NAME} (\r\n" +
|
||
" id VARCHAR(32) NOT NULL,\r\n" +
|
||
" flow_id VARCHAR(32),\r\n" +
|
||
" pid VARCHAR(32) DEFAULT '#',\r\n" +
|
||
" entity_class_name VARCHAR(255),\r\n" +
|
||
" bus_name VARCHAR(100),\r\n" +
|
||
" entity_id BIGINT,\r\n" +
|
||
" field_changes TEXT,\r\n" +
|
||
" operation_type VARCHAR(20),\r\n" +
|
||
" operator_id BIGINT,\r\n" +
|
||
" operator_name VARCHAR(100),\r\n" +
|
||
" operation_time TIMESTAMPTZ,\r\n" +
|
||
" operation_ip VARCHAR(50),\r\n" +
|
||
" PRIMARY KEY (id)\r\n" +
|
||
" );",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"flow_id\" IS '流水id';",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"pid\" IS '父表ID,根节点#';",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"entity_class_name\" IS '实体类名称(全类名)';",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"bus_name\" IS '业务名称';",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"entity_id\" IS '操作的实体ID(主键值)';",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"field_changes\" IS '属性值记录(JSON格式存储字段变更详情)';",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"operation_type\" IS '操作类型:INSERT-新增,UPDATE-修改,DELETE-删除';",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"operator_id\" IS '操作人ID';",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"operator_name\" IS '操作人姓名';",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"operation_time\" IS '操作时间';",
|
||
"COMMENT ON COLUMN ${TBL_NAME}.\"operation_ip\" IS '操作IP地址';",
|
||
"CREATE INDEX idx_${TBL_NAME}_enityt_id ON ${TBL_NAME} (entity_id)"
|
||
};
|
||
|
||
public static final String SQL_INSERT = "INSERT INTO ${TBL_NAME} (\r\n" +
|
||
" id, flow_id, pid, entity_class_name, bus_name, \r\n" +
|
||
" entity_id, field_changes, operation_type, operator_id, \r\n" +
|
||
" operator_name, operation_time, operation_ip\r\n" +
|
||
") VALUES (?,?,?,?,?,?,?,?,?,?,?,?);";
|
||
|
||
|
||
public static final String SQL_LIST = "SELECT * FROM ${TBL_NAME} WHERE entity_id = ? ORDER BY operation_time DESC, flow_id DESC";
|
||
|
||
public static final Set<String> excludeFields = SetUtils.of("id","tenantId","dataVersion","createUserId","createDate","modifyUserId","modifyDate","modifyDate","deleteMark");
|
||
|
||
|
||
public static DataChangeLog createLog(Class<?> klazz,OperationType type) {
|
||
DataChangeLog createLog = createLog(klazz, type, null);
|
||
return createLog.setFlowId(IdUtil.getSnowflakeNextIdStr());
|
||
}
|
||
|
||
public static DataChangeLog createLog(Class<?> klazz,OperationType type,DataChangeLog parent) {
|
||
UserDto currentUser = SecureUtil.getCurrentUser();
|
||
LogTableInfo annotation = getAnnotation(klazz);
|
||
//变更人的IP地址
|
||
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
||
String ipAddress = request.getRemoteAddr();
|
||
DataChangeLog changeLog = new DataChangeLog()
|
||
.setEntityClassName(klazz.getCanonicalName())
|
||
.setBusName(annotation.getName())
|
||
.setId(IdUtil.getSnowflakeNextIdStr())
|
||
.setOperationIp(ipAddress)
|
||
.setOperationType(type)
|
||
.setOperatorId(currentUser.getId())
|
||
.setOperatorName(currentUser.getName())
|
||
.setOperationTime(LocalDateTime.now());
|
||
if(parent!=null) {
|
||
changeLog.setFlowId(parent.getFlowId());
|
||
changeLog.setPid(parent.getId());
|
||
}
|
||
return changeLog;
|
||
}
|
||
|
||
public static LogTableInfo getAnnotation(Class<?> klazz) {
|
||
synchronized (lock) {
|
||
if(annotations.containsKey(klazz)) {
|
||
return annotations.get(klazz);
|
||
}
|
||
LogTableInfo tableInfo = new LogTableInfo(klazz);
|
||
if(tableInfo.isValid()) {
|
||
annotations.put(klazz,tableInfo);
|
||
return tableInfo;
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
|
||
public static <T>T insert(T entity) {
|
||
Class<? extends Object> klazz = entity.getClass();
|
||
List<DataChangeLog> logs = CollectionUtils.newArrayList();
|
||
DataChangeLog datalog = createLog(klazz,OperationType.INSERT);
|
||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||
initJoinValue(entity,tabInfo,null);
|
||
Long idValue = tabInfo.getIdValue(entity);
|
||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||
mapper.insert(BeanUtil.toBean(entity,tabInfo.getEntityType()));
|
||
datalog.setEntityId(idValue);
|
||
buildFields(datalog,tabInfo,entity,null);
|
||
logs.add(datalog);
|
||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||
if(CollectionUtils.isNotEmpty(joins)) {
|
||
for (LogJoinInfo join : joins) {
|
||
if(join.getJoin().caseType()==JoinCaseType.FULL) {
|
||
buildJoins(logs,datalog,OperationType.INSERT,tabInfo,join,entity);
|
||
}
|
||
}
|
||
}
|
||
saveLogs(tabInfo,logs);
|
||
return entity;
|
||
}
|
||
|
||
|
||
public static <T>T update(T dto) {
|
||
Class<? extends Object> klazz = dto.getClass();
|
||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||
|
||
Long idValue = tabInfo.getIdValue(dto);
|
||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||
Object old = findById(klazz, idValue);
|
||
if(old!=null) {
|
||
List<DataChangeLog> logs = CollectionUtils.newArrayList();
|
||
DataChangeLog datalog = createLog(klazz,OperationType.UPDATE);
|
||
initJoinValue(dto,tabInfo,null);
|
||
|
||
mapper.updateById(tabInfo.toEntity(dto));
|
||
datalog.setEntityId(idValue);
|
||
buildFields(datalog,tabInfo,dto,old);
|
||
logs.add(datalog);
|
||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||
if(!CollectionUtils.isNotEmpty(joins)) {
|
||
for (LogJoinInfo join : joins) {
|
||
if(join.getJoin().caseType()==JoinCaseType.FULL) {
|
||
buildJoins(logs,datalog,OperationType.UPDATE,tabInfo,join,dto);
|
||
}
|
||
}
|
||
}
|
||
saveLogs(tabInfo,logs);
|
||
}else {
|
||
throw new OrmException("数据不存在");
|
||
}
|
||
return dto;
|
||
}
|
||
|
||
|
||
public static <T>T delete(T entity) {
|
||
Class<? extends Object> klazz = entity.getClass();
|
||
List<DataChangeLog> logs = CollectionUtils.newArrayList();
|
||
|
||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||
Long idValue = tabInfo.getIdValue(entity);
|
||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||
DataChangeLog datalog = createLog(klazz,OperationType.DELETE);
|
||
datalog.setEntityId(idValue);
|
||
buildFields(datalog,tabInfo,entity,null);
|
||
logs.add(datalog);
|
||
delete(entity, tabInfo, mapper);
|
||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||
if(!CollectionUtils.isNotEmpty(joins)) {
|
||
for (LogJoinInfo join : joins) {
|
||
if(join.getJoin().caseType()==JoinCaseType.FULL) {
|
||
buildJoins(logs,datalog,OperationType.DELETE,tabInfo,join,entity);
|
||
}
|
||
}
|
||
}
|
||
saveLogs(tabInfo,logs);
|
||
return entity;
|
||
}
|
||
|
||
|
||
public static boolean deleteByIds(Class<?> klazz, @Valid List<Long> ids) {
|
||
for (Long id : ids) {
|
||
deleteById(klazz, id);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
public static <T>T deleteById(Class<T> klazz,Long id) {
|
||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||
T entity = findById(klazz, id);
|
||
if(entity==null) return null;
|
||
List<DataChangeLog> logs = CollectionUtils.newArrayList();
|
||
|
||
delete(entity, tabInfo, mapper);
|
||
DataChangeLog datalog = createLog(klazz,OperationType.DELETE);
|
||
datalog.setEntityId(id);
|
||
buildFields(datalog,tabInfo,entity,null);
|
||
logs.add(datalog);
|
||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||
if(!CollectionUtils.isNotEmpty(joins)) {
|
||
for (LogJoinInfo join : joins) {
|
||
if(join.getJoin().caseType()==JoinCaseType.FULL) {
|
||
buildJoins(logs,datalog,OperationType.DELETE,tabInfo,join,entity);
|
||
}
|
||
}
|
||
}
|
||
saveLogs(tabInfo,logs);
|
||
return entity;
|
||
}
|
||
|
||
private static void delete(Object entity,LogTableInfo tableinfo,BaseMapper mapper){
|
||
Long idValue = tableinfo.getIdValue(entity);
|
||
if(idValue!=null && idValue > 0) {
|
||
mapper.deleteById(idValue);
|
||
}else {
|
||
throw new BusinessException(BusinessCode.ofArgs(ExceptionCommonCode.DATA_DEL_ID_IS_NULL,tableinfo.getTableName()));
|
||
}
|
||
}
|
||
|
||
public static boolean enable(Class<?> klazz, @Valid List<Long> ids) {
|
||
for (Long id : ids) {
|
||
enableById(klazz, id);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
public static <T>T enableById(Class<T> klazz,Long id) {
|
||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||
Object entity = findNativeById(klazz, id);
|
||
if(entity==null) return null;
|
||
T old = BeanUtils.newInstance(klazz);
|
||
BeanUtil.copyProperties(entity,old,true);
|
||
List<DataChangeLog> logs = CollectionUtils.newArrayList();
|
||
BeanUtils.setFieldValue("valid", YesOrNoEnum.YES.getTextCode(), entity);
|
||
mapper.updateById(entity);
|
||
T dto = (T)tabInfo.toDto(entity);
|
||
DataChangeLog datalog = createLog(klazz,OperationType.UPDATE);
|
||
datalog.setEntityId(id);
|
||
buildFields(datalog,tabInfo,dto,tabInfo.toDto(old));
|
||
logs.add(datalog);
|
||
saveLogs(tabInfo,logs);
|
||
return dto;
|
||
}
|
||
|
||
public static boolean disable(Class<?> klazz, @Valid List<Long> ids) {
|
||
for (Long id : ids) {
|
||
disableById(klazz, id);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
public static <T>T disableById(Class<T> klazz,Long id) {
|
||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||
Object entity = findNativeById(klazz, id);
|
||
if(entity==null) return null;
|
||
T old = BeanUtils.newInstance(klazz);
|
||
BeanUtil.copyProperties(entity,old,true);
|
||
List<DataChangeLog> logs = CollectionUtils.newArrayList();
|
||
BeanUtils.setFieldValue("valid",YesOrNoEnum.NO.getTextCode(), entity);
|
||
mapper.updateById(entity);
|
||
T dto = (T)tabInfo.toDto(entity);
|
||
DataChangeLog datalog = createLog(klazz,OperationType.UPDATE);
|
||
datalog.setEntityId(id);
|
||
buildFields(datalog,tabInfo,dto,tabInfo.toDto(old));
|
||
logs.add(datalog);
|
||
saveLogs(tabInfo,logs);
|
||
return dto;
|
||
}
|
||
|
||
|
||
public static <T>T findById(Class<T> klazz,Serializable id){
|
||
return findById(klazz,id,false);
|
||
}
|
||
|
||
public static <T>T findById(Class<T> klazz,Serializable id,boolean full){
|
||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||
Object old = mapper.selectById(id);
|
||
if(old==null) return null;
|
||
T dto = (T) tabInfo.toDto(old);
|
||
initJoinValues(tabInfo,dto,SetUtils.of(klazz), full);
|
||
return dto;
|
||
}
|
||
|
||
|
||
private static Object findNativeById(Class<?> klazz, Serializable id) {
|
||
LogTableInfo tabInfo = getAnnotation(klazz);
|
||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||
return mapper.selectById(id);
|
||
}
|
||
|
||
public static void initJoinValues(LogTableInfo tabInfo,Object entity,Set<Class<?>> classPath,boolean full){
|
||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||
BaseMapper mapper = MybatisTools.getMapper(tabInfo.getEntityType());
|
||
if(!CollectionUtils.isNotEmpty(joins)) {
|
||
for (LogJoinInfo join : joins) {
|
||
LogTableInfo joinTable = join.getTableInfo();
|
||
if(full) {
|
||
if(join.isList()) {
|
||
List joinList = getJoinList(joinTable,join, mapper,tabInfo,entity);
|
||
if(CollectionUtils.isNotEmpty(joinList)) {
|
||
List listVal = new ArrayList();
|
||
for (Object item : joinList) {
|
||
Object voOjb = BeanUtil.toBean(item,joinTable.getKlazz());
|
||
if(!classPath.contains(joinTable.getKlazz())) {
|
||
Set<Class<?>> classes = SetUtils.ofCollection(classPath);
|
||
classes.add(joinTable.getKlazz());
|
||
initJoinValues(joinTable,voOjb,classes,full);
|
||
}
|
||
listVal.add(voOjb);
|
||
}
|
||
tabInfo.setFieldValue(entity,join.getField(),listVal);
|
||
}
|
||
}else {
|
||
Object objVal = getJoinObj(joinTable,join, mapper,tabInfo,entity);
|
||
Object voOjb = BeanUtil.toBean(objVal,joinTable.getKlazz());
|
||
if(!classPath.contains(joinTable.getKlazz())) {
|
||
Set<Class<?>> classes = SetUtils.ofCollection(classPath);
|
||
classes.add(joinTable.getKlazz());
|
||
initJoinValues(joinTable,voOjb,classes,full);
|
||
}
|
||
tabInfo.setFieldValue(entity,join.getField(),voOjb);
|
||
}
|
||
}else {
|
||
if(join.getJoin().caseType()==JoinCaseType.FULL) {
|
||
if(join.isList()) {
|
||
List joinList = getJoinList(joinTable,join, mapper,tabInfo,entity);
|
||
if(CollectionUtils.isNotEmpty(joinList)) {
|
||
List listVal = new ArrayList();
|
||
for (Object item : joinList) {
|
||
Object voOjb = BeanUtil.toBean(item,joinTable.getKlazz());
|
||
if(!classPath.contains(joinTable.getKlazz())) {
|
||
Set<Class<?>> classes = SetUtils.ofCollection(classPath);
|
||
classes.add(joinTable.getKlazz());
|
||
initJoinValues(joinTable,voOjb,classes,full);
|
||
}
|
||
listVal.add(voOjb);
|
||
}
|
||
tabInfo.setFieldValue(entity,join.getField(),listVal);
|
||
}
|
||
}else {
|
||
Object objVal = getJoinObj(joinTable,join, mapper,tabInfo,entity);
|
||
Object voOjb = BeanUtil.toBean(objVal,joinTable.getKlazz());
|
||
if(!classPath.contains(joinTable.getKlazz())) {
|
||
Set<Class<?>> classes = SetUtils.ofCollection(classPath);
|
||
classes.add(joinTable.getKlazz());
|
||
initJoinValues(joinTable,voOjb,classes,full);
|
||
}
|
||
tabInfo.setFieldValue(entity,join.getField(),voOjb);
|
||
}
|
||
}
|
||
}
|
||
classPath.add(joinTable.getKlazz());
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
private static <T>void initJoinValue(T entity,LogTableInfo tabInfo,Set<Class<?>> classes) {
|
||
if(classes==null) {
|
||
classes = CollectionUtils.newHashSet();
|
||
}
|
||
if(classes.contains(tabInfo.getEntityType())) return ;
|
||
List<LogJoinInfo> joins = tabInfo.getJoins();
|
||
Long idValue = tabInfo.getIdValue(entity);
|
||
if(idValue == null || idValue <=0) {
|
||
idValue = IdWorker.getId();
|
||
tabInfo.setIdValue(entity,idValue);
|
||
}
|
||
classes.add(tabInfo.getEntityType());
|
||
if(!CollectionUtils.isNotEmpty(joins)) {
|
||
for (LogJoinInfo join : joins) {
|
||
LogJoinColumn[] columns = join.getJoin().columns();
|
||
LogTableInfo joinTable = join.getTableInfo();
|
||
if(classes.contains(joinTable.getEntityType())) {
|
||
continue;
|
||
}
|
||
Object joinValue = tabInfo.getFieldValue(entity, join.getField());
|
||
if(joinValue!=null && joinValue instanceof List) {
|
||
List listValue = (List) joinValue;
|
||
for (LogJoinColumn joinColumn : columns) {
|
||
if (joinColumn.valueType() == JoinValueType.FEILD
|
||
&& joinColumn.valueDirection() == ValueDirectionType.RIGHT) {
|
||
Object joinFieldValue = tabInfo.getFieldValue(entity, joinColumn.field());
|
||
for (Object item : listValue) {
|
||
Long idValue2 = joinTable.getIdValue(item);
|
||
if(idValue2==null || idValue2 <=0) {
|
||
joinTable.setIdValue(joinValue, IdWorker.getId());
|
||
}
|
||
joinTable.setFieldValue(item, joinColumn.relatedField(), joinFieldValue);
|
||
Set<Class<?>> joinClasses = SetUtils.ofCollection(classes);
|
||
initJoinValue(item,joinTable,joinClasses);
|
||
}
|
||
}
|
||
}
|
||
}else {
|
||
Long idValue2 = joinTable.getIdValue(joinValue);
|
||
if(idValue2==null || idValue2 <=0) {
|
||
joinTable.setIdValue(joinValue,idValue2);
|
||
}
|
||
for (LogJoinColumn joinColumn : columns) {
|
||
if(joinColumn.valueType()==JoinValueType.FEILD && joinColumn.valueDirection()==ValueDirectionType.LEFT) {
|
||
Object joinFieldValue = joinTable.getFieldValue(joinValue, joinColumn.relatedField());
|
||
tabInfo.setFieldValue(entity, joinColumn.field(),joinFieldValue);
|
||
}else {
|
||
Object joinFieldValue = tabInfo.getFieldValue(entity, joinColumn.field());
|
||
joinTable.setFieldValue(joinValue, joinColumn.relatedField(), joinFieldValue);
|
||
}
|
||
}
|
||
Set<Class<?>> joinClasses = SetUtils.ofCollection(classes);
|
||
initJoinValue(joinValue,joinTable,joinClasses);
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
private static <T>void buildJoins(List<DataChangeLog> logs,DataChangeLog parent,OperationType type,LogTableInfo parentInfo, LogJoinInfo join, T entity) {
|
||
LogTableInfo joinTable = join.getTableInfo();
|
||
BaseMapper mapper = MybatisTools.getMapper(joinTable.getEntityType());
|
||
if(joinTable!=null) {
|
||
if(join.isList()) {
|
||
List listValue = BeanUtils.getFieldValue(join.getField(),entity);
|
||
if(CollectionUtils.isNotEmpty(listValue)) {
|
||
if(type==OperationType.INSERT || type==OperationType.DELETE) {
|
||
if(type==OperationType.INSERT) {
|
||
for (Object item : listValue) {
|
||
Long idValue = joinTable.getIdValue(item);
|
||
DataChangeLog datalog = createLog(join.getTargetClass(),type,parent);
|
||
datalog.setEntityId(idValue);
|
||
Object bean = BeanUtil.toBean(item,joinTable.getEntityType());
|
||
mapper.insert(bean);
|
||
buildFields(datalog,joinTable,item,null);
|
||
logs.add(datalog);
|
||
}
|
||
}else {
|
||
for (Object item : listValue) {
|
||
Long idValue = joinTable.getIdValue(item);
|
||
Object voOjb = BeanUtil.toBean(item,joinTable.getKlazz());
|
||
DataChangeLog datalog = createLog(join.getTargetClass(),type,parent);
|
||
datalog.setEntityId(idValue);
|
||
delete(voOjb, joinTable, mapper);
|
||
buildFields(datalog,joinTable,voOjb,null);
|
||
logs.add(datalog);
|
||
}
|
||
}
|
||
}else {
|
||
for (Object item : listValue) {
|
||
Long idValue = joinTable.getIdValue(item);
|
||
Object nval = BeanUtil.toBean(item,joinTable.getKlazz());
|
||
DataChangeLog datalog = createLog(join.getTargetClass(),type,parent);
|
||
datalog.setEntityId(idValue);
|
||
Object old = findById(join.getTargetClass(), idValue);
|
||
mapper.updateById(nval);
|
||
buildFields(datalog,joinTable,nval,old);
|
||
logs.add(datalog);
|
||
}
|
||
}
|
||
} else if(type==OperationType.UPDATE || type==OperationType.DELETE){
|
||
//进行修改或者删除时,级联对象为空时,需要删除旧数据
|
||
List oldList = getJoinList(joinTable, join, mapper, parentInfo, entity);
|
||
if(oldList!=null) {
|
||
for (Object item : oldList) {
|
||
Object voOjb = BeanUtil.toBean(item,joinTable.getKlazz());
|
||
Long idValue = joinTable.getIdValue(item);
|
||
DataChangeLog datalog = createLog(join.getTargetClass(),OperationType.DELETE,parent);
|
||
datalog.setEntityId(idValue);
|
||
delete(voOjb, joinTable, mapper);
|
||
buildFields(datalog,joinTable,voOjb,null);
|
||
logs.add(datalog);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
Object val = BeanUtils.getFieldValue(join.getField(),entity);
|
||
if(val!=null) {
|
||
Long idValue = joinTable.getIdValue(val);
|
||
DataChangeLog datalog = createLog(join.getTargetClass(),type,parent);
|
||
logs.add(datalog);
|
||
datalog.setEntityId(idValue);
|
||
if(type==OperationType.INSERT || type==OperationType.DELETE) {
|
||
if(type==OperationType.INSERT) {
|
||
mapper.insert(val);
|
||
}else {
|
||
delete(val, joinTable, mapper);
|
||
}
|
||
buildFields(datalog,joinTable, val, null);
|
||
}else {
|
||
Object old = mapper.selectById(idValue);
|
||
buildFields(datalog,joinTable,val,old);
|
||
Object bean = BeanUtil.toBean(val,joinTable.getEntityType());
|
||
mapper.updateById(bean);
|
||
}
|
||
} else if(type==OperationType.UPDATE || type==OperationType.DELETE){
|
||
//进行修改或者删除时,级联对象为空时,需要删除旧数据
|
||
Object old = getJoinObj(joinTable, join, mapper, parentInfo, entity);
|
||
if(old!=null) {
|
||
Object voOjb = BeanUtil.toBean(old,joinTable.getKlazz());
|
||
Long idValue = joinTable.getIdValue(old);
|
||
DataChangeLog datalog = createLog(join.getTargetClass(),OperationType.DELETE,parent);
|
||
datalog.setEntityId(idValue);
|
||
delete(voOjb, joinTable, mapper);
|
||
buildFields(datalog,joinTable,voOjb,null);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private static List getJoinList(LogTableInfo joinTable, LogJoinInfo join, BaseMapper mapper,
|
||
LogTableInfo parentInfo,Object parent) {
|
||
LogJoin joinAnnotation = join.getJoin();
|
||
LogJoinColumn[] columns = joinAnnotation.columns();
|
||
QueryChainWrapper queryWrapper = new QueryChainWrapper(mapper);
|
||
for (LogJoinColumn joinCol : columns) {
|
||
if(joinCol.valueType()==JoinValueType.FEILD) {
|
||
Object value = parentInfo.getFieldValue(parent,joinCol.field());
|
||
if(value==null) return null;
|
||
queryWrapper.eq(joinTable.getColumn(joinCol.relatedField()),value);
|
||
}else {
|
||
if(StringUtils.isNotEmpty(joinCol.relatedField())) {
|
||
queryWrapper.eq(joinTable.getColumn(joinCol.relatedField()),ConverUtil.jsonToValue(joinCol.staticType(),joinCol.staticValue()));
|
||
}
|
||
}
|
||
}
|
||
return mapper.selectList(queryWrapper);
|
||
}
|
||
|
||
private static Object getJoinObj(LogTableInfo joinTable,LogJoinInfo join,BaseMapper mapper,LogTableInfo parentInfo,Object parent) {
|
||
LogJoin joinAnnotation = join.getJoin();
|
||
LogJoinColumn[] columns = joinAnnotation.columns();
|
||
QueryChainWrapper query = new QueryChainWrapper(mapper);
|
||
for (LogJoinColumn joinCol : columns) {
|
||
if(joinCol.valueType()==JoinValueType.FEILD) {
|
||
Object value = parentInfo.getFieldValue(parent,joinCol.field());
|
||
if(value==null) return null;
|
||
query.eq(joinTable.getColumn(joinCol.relatedField()),value);
|
||
}else {
|
||
if(StringUtils.isNotEmpty(joinCol.relatedField())) {
|
||
query.eq(joinTable.getColumn(joinCol.relatedField()),ConverUtil.jsonToValue(joinCol.staticType(),joinCol.staticValue()));
|
||
}
|
||
}
|
||
}
|
||
return mapper.selectObjs(query);
|
||
}
|
||
|
||
|
||
private static <T>void buildFields(DataChangeLog datalog,LogTableInfo tableInfo,T entity,T old) {
|
||
List<LogFieldInfo> fields = tableInfo.getFields();
|
||
for (LogFieldInfo item : fields) {
|
||
if(excludeFields.contains(item.getFieldName())) {
|
||
continue;
|
||
}
|
||
FieldChange change = new FieldChange();
|
||
change.setField(item.getFieldName());
|
||
change.setName(item.getName());
|
||
if(old!=null) {
|
||
Object newVal = BeanUtils.getFieldValue(item.getField(),entity);
|
||
Object oldVal = BeanUtils.getFieldValue(item.getField(),old);
|
||
boolean flag = false;
|
||
boolean isString = String.class.equals(item.getJavaType());
|
||
if(newVal==null && oldVal!=null) {
|
||
flag = isString?StringUtils.isNotEmpty((String)oldVal):true;
|
||
}else if(newVal!=null && oldVal==null) {
|
||
flag = isString?StringUtils.isNotEmpty((String)newVal):true;
|
||
}else if(newVal!=null && oldVal!=null && !newVal.equals(oldVal)) {
|
||
flag = true;
|
||
}
|
||
change.setOldValue(parseValue(oldVal,item.getJavaType()));
|
||
change.setNewValue(parseValue(newVal,item.getJavaType()));
|
||
if(flag) {
|
||
datalog.addFiledChnage(change);
|
||
}
|
||
}else {
|
||
change.setNewValue(parseValue(BeanUtils.getFieldValue(item.getField(),entity),item.getField().getType()));
|
||
datalog.addFiledChnage(change);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
private static String parseValue(Object val,Class<?> type) {
|
||
if(val==null) return null;
|
||
if (type.equals(String.class)) {
|
||
return String.class.cast(val);
|
||
|
||
} else if (type.equals(BigDecimal.class)) {
|
||
return BigDecimal.class.cast(val).toString();
|
||
|
||
} else if (type.equals(BigInteger.class)) {
|
||
return BigInteger.class.cast(val).toString();
|
||
|
||
} else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)
|
||
|| type.equals(Integer.class) || type.equals(Integer.TYPE)
|
||
|| type.equals(Long.class) || type.equals(Long.TYPE)
|
||
|| type.equals(Float.class) || type.equals(Float.TYPE)
|
||
|| type.equals(Double.class) || type.equals(Double.TYPE)
|
||
) {
|
||
return val.toString();
|
||
|
||
} else if (type.equals(byte[].class)) {
|
||
byte[] buf = (byte[])val;
|
||
return new String(buf, Charset.forName("UTF-8"));
|
||
|
||
} else if (type.equals(Date.class) || type.equals(Time.class) || type.equals(Timestamp.class) || type.equals(java.util.Date.class)) {
|
||
String fmt = null;
|
||
if(type.equals(Date.class)) {
|
||
fmt = DateUtils.GENERAL;
|
||
}else if(type.equals(Time.class)) {
|
||
fmt = DateUtils.FMT_TIME;
|
||
}else {
|
||
fmt = DateUtils.LONG_FORMAT;
|
||
}
|
||
return DateUtils.format(java.util.Date.class.cast(val),fmt);
|
||
}else if (type.equals(LocalDate.class)) {
|
||
return DateUtils.format(LocalDate.class.cast(val));
|
||
|
||
} else if (type.equals(LocalDateTime.class)) {
|
||
return DateUtils.format(LocalDateTime.class.cast(val));
|
||
|
||
} else if (type.equals(LocalTime.class)) {
|
||
return DateUtils.format(LocalDateTime.class.cast(val));
|
||
} else if (type.equals(OffsetDateTime.class)) {
|
||
return DateUtils.format(OffsetDateTime.class.cast(val));
|
||
|
||
} else if (type.equals(OffsetTime.class)) {
|
||
return DateUtils.format(OffsetTime.class.cast(val));
|
||
}else if(type.isEnum()) {
|
||
return val.toString();
|
||
}
|
||
return null;
|
||
}
|
||
|
||
|
||
/**
|
||
* @Description: 保存数据日志
|
||
* @param logs 日志记录对象
|
||
* @return void 返回类型
|
||
*/
|
||
public static void saveLogs(LogTableInfo tableInfo,List<DataChangeLog> logs) {
|
||
String tableName = parseLogTableName(tableInfo);
|
||
initTable(tableName);
|
||
String sql = parseSql(SQL_INSERT, tableName);
|
||
List<List<JdbcParam>> batchParams = CollectionUtils.newArrayList();
|
||
for (DataChangeLog log : logs) {
|
||
List<JdbcParam> params = CollectionUtils.newArrayList();
|
||
params.add(JdbcParam.of(Types.VARCHAR,String.class, log.getId()));
|
||
params.add(JdbcParam.of(Types.VARCHAR,String.class, log.getFlowId()));
|
||
params.add(JdbcParam.of(Types.VARCHAR,String.class, log.getPid()));
|
||
params.add(JdbcParam.of(Types.VARCHAR,String.class, log.getEntityClassName()));
|
||
params.add(JdbcParam.of(Types.VARCHAR,String.class, log.getBusName()));
|
||
params.add(JdbcParam.of(Types.BIGINT,long.class, log.getEntityId()));
|
||
params.add(JdbcParam.of(Types.VARCHAR,String.class,JSON.toJSONString(log.getFieldChanges())));
|
||
params.add(JdbcParam.of(Types.VARCHAR,String.class,log.getOperationType().name()));
|
||
params.add(JdbcParam.of(Types.VARCHAR,long.class,log.getOperatorId()));
|
||
params.add(JdbcParam.of(Types.VARCHAR,String.class,log.getOperatorName()));
|
||
params.add(JdbcParam.of(Types.TIMESTAMP,Timestamp.class,log.getOperationTime()));
|
||
params.add(JdbcParam.of(Types.VARCHAR,String.class,log.getOperationIp()));
|
||
batchParams.add(params);
|
||
}
|
||
executeBatch(sql, batchParams);
|
||
}
|
||
|
||
/**
|
||
* @Description: 初始化日志表
|
||
* @param tableName
|
||
* @return void 返回类型
|
||
*/
|
||
private synchronized static boolean initTable(String tableName) {
|
||
synchronized (lock) {
|
||
//如果没有日志表时,重新创建
|
||
if(!hasTable(tableName)) {
|
||
for (int i = 0; i < SQL_CREATE_TABLE.length; i++) {
|
||
execute(parseSql(SQL_CREATE_TABLE[i], tableName));
|
||
}
|
||
//将表名进行记录
|
||
executeUpdate(SQL_INST_TABLE,ListUtils.ofArray(JdbcParam.ofString(tableName)));
|
||
logTables.add(tableName);
|
||
log.info("新增数据日志表:{}",tableName);
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
private static String parseSql(String sql,String tableName) {
|
||
return sql.replaceAll(SQL_PLACEHOLDER,tableName);
|
||
}
|
||
|
||
private static boolean hasTable(String tableName) {
|
||
synchronized (lock) {
|
||
if(logTables==null) {
|
||
List<String> tabs = queryListPrimitive(SQL_LOG_TABLE_LIST,String.class, null);
|
||
logTables = new HashSet<String>(tabs);
|
||
}
|
||
if(logTables.contains(tableName)) return true;
|
||
Long count = queryPrimitive(SQL_HAS_TABLE,long.class,Lists.newArrayList(JdbcParam.ofString(tableName)));
|
||
boolean flag = count!=null && count > 0;
|
||
if(flag) {
|
||
logTables.add(tableName);
|
||
}
|
||
return flag;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @Description: TODO(这里用一句话描述这个方法的作用)
|
||
* @param clazz
|
||
* @param dataId
|
||
* @return List<DataChangeLog> 返回类型
|
||
*/
|
||
public static <T>List<DataChangeLogVo> findLogsByEntityId(Class<?> clazz,@NonNull Long dataId) {
|
||
LogTableInfo tabInfo = getAnnotation(clazz);
|
||
String tableName = parseLogTableName(tabInfo);
|
||
return findLogsByEntityId(tableName, dataId);
|
||
}
|
||
|
||
|
||
/**
|
||
* @Description: 根据数据id获取操作日志
|
||
* @param tableName 表名
|
||
* @param dataId 数据id
|
||
* @return List<DataChangeLog> 返回类型
|
||
*/
|
||
public static <T>List<DataChangeLogVo> findLogsByEntityId(String tableName,@NonNull Long dataId) {
|
||
if(initTable(tableName)) {
|
||
return null;
|
||
}
|
||
List<DataChangeLog> result = CollectionUtils.newArrayList();
|
||
String sql = parseSql(SQL_LIST, tableName);
|
||
JdbcContext context = null;
|
||
try {
|
||
context = new JdbcContext(true,true);
|
||
context.init(sql);
|
||
context.setParams(ListUtils.ofArray(JdbcParam.ofLong(dataId)));
|
||
ResultSet set = context.executeQuery();
|
||
Map<String, String> names = ResultSetUtils.getMapColumns(set);
|
||
while (set.next()) {
|
||
DataChangeLog log = new DataChangeLog();
|
||
log.setId(set.getString("id"));
|
||
log.setFlowId(set.getString("flow_id"));
|
||
log.setPid(set.getString("pid"));
|
||
log.setEntityClassName(set.getString("entity_class_name"));
|
||
log.setBusName(set.getString("bus_name"));
|
||
log.setEntityId(set.getLong("entity_id"));
|
||
log.setOperationType(OperationType.valueOf(set.getString("operation_type")));
|
||
log.setOperationIp(set.getString("operation_ip"));
|
||
log.setOperatorId(set.getLong("operator_id"));
|
||
log.setOperatorName(set.getString("operator_name"));
|
||
log.setOperationTime(ResultSetUtils.getObject(set,"operation_time",LocalDateTime.class));
|
||
String json = set.getString("field_changes");
|
||
if(StringUtils.isNotEmpty(json)) {
|
||
log.setFieldChanges(JSON.parseArray(json).toJavaList(FieldChange.class));
|
||
}
|
||
result.add(log);
|
||
}
|
||
return toVo(result);
|
||
} catch (SQLException e) {
|
||
throw context.createException(e);
|
||
} finally {
|
||
context.end();
|
||
}
|
||
}
|
||
|
||
private static List<DataChangeLogVo> toVo(List<DataChangeLog> list){
|
||
List<DataChangeLogVo> result = CollectionUtils.newArrayList();
|
||
if(CollectionUtils.isNotEmpty(list)) {
|
||
Map<String, List<DataChangeLog>> flowGroup = list.stream().collect(Collectors.groupingBy(DataChangeLog::getFlowId));
|
||
for (Entry<String, List<DataChangeLog>> entry : flowGroup.entrySet()) {
|
||
Map<String, List<DataChangeLog>> pidMap = entry.getValue().stream().collect(Collectors.groupingBy(DataChangeLog::getPid));
|
||
DataChangeLog root = pidMap.get("#").get(0);
|
||
DataChangeLogVo vo = toVo(root);
|
||
addChildVo(root,vo,pidMap);
|
||
result.add(vo);
|
||
}
|
||
}
|
||
Collections.sort(result,new Comparator<DataChangeLogVo>() {
|
||
@Override
|
||
public int compare(DataChangeLogVo o1, DataChangeLogVo o2) {
|
||
return Long.valueOf(o2.getSort()-o1.getSort()).intValue();
|
||
}
|
||
});
|
||
return result;
|
||
}
|
||
|
||
private static void addChildVo(DataChangeLog current,DataChangeLogVo parentVo,Map<String, List<DataChangeLog>> pidMap){
|
||
List<DataChangeLog> childs = pidMap.get(current.getId());
|
||
if(CollectionUtils.isNotEmpty(childs)) {
|
||
for (DataChangeLog item : childs) {
|
||
DataChangeLogVo logVo = toVo(item,parentVo.getId());
|
||
parentVo.addChild(logVo);
|
||
addChildVo(item, logVo, pidMap);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
private static DataChangeLogVo toVo(DataChangeLog obj){
|
||
return toVo(obj, obj.getPid());
|
||
}
|
||
|
||
private static long toMills(LocalDateTime datetime) {
|
||
ZonedDateTime systemZoned = datetime.atZone(ZoneId.systemDefault());
|
||
return systemZoned.toInstant().toEpochMilli();
|
||
}
|
||
|
||
private static DataChangeLogVo toVo(DataChangeLog obj,String pid){
|
||
DataChangeLogVo vo = new DataChangeLogVo();
|
||
vo.setId(obj.getId());
|
||
vo.setPid(pid);
|
||
vo.setTableName(obj.getBusName());
|
||
vo.setOperationType(obj.getOperationType());
|
||
vo.setOperatorName(obj.getOperatorName());
|
||
vo.setOperationIp(obj.getOperationIp());
|
||
vo.setOperationTime(DateUtils.format(obj.getOperationTime()));
|
||
vo.setSort(toMills(obj.getOperationTime()));
|
||
|
||
List<FieldChange> fieldChanges = obj.getFieldChanges();
|
||
for (FieldChange fieldChange : fieldChanges) {
|
||
DataChangeLogVo fvo = new DataChangeLogVo();
|
||
fvo.setId(obj.getId()+"_"+fieldChange.getField());
|
||
fvo.setPid(obj.getId());
|
||
fvo.setName(fieldChange.getName());
|
||
fvo.setOldValue(fieldChange.getOldValue());
|
||
fvo.setNewValue(fieldChange.getNewValue());
|
||
|
||
fvo.setOperationType(obj.getOperationType());
|
||
fvo.setOperatorName(obj.getOperatorName());
|
||
fvo.setOperationIp(obj.getOperationIp());
|
||
fvo.setOperationTime(DateUtils.format(obj.getOperationTime()));
|
||
|
||
vo.addChild(fvo);
|
||
}
|
||
return vo;
|
||
}
|
||
|
||
private static String parseLogTableName(LogTableInfo tableInfo) {
|
||
String name = tableInfo.getTableName();
|
||
return "datalog_"+name;
|
||
}
|
||
|
||
/**
|
||
* 执行ddl语句
|
||
* */
|
||
public static boolean execute(String sql){
|
||
JdbcContext context = null;
|
||
try {
|
||
context = new JdbcContext(true,true);
|
||
context.init(sql);
|
||
return context.execute();
|
||
} catch (SQLException e) {
|
||
throw context.createException(e);
|
||
}finally {
|
||
context.end();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 修改操作
|
||
* */
|
||
public static int executeUpdate(String sql,List<JdbcParam> params){
|
||
JdbcContext context = null;
|
||
try {
|
||
context = new JdbcContext(true,true);
|
||
context.init(sql);
|
||
context.setParams(params);
|
||
return context.executeUpdate();
|
||
} catch (SQLException e) {
|
||
throw context.createException(e);
|
||
}finally {
|
||
context.end();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 批量操作
|
||
* */
|
||
public static int executeBatch(String sql,List<List<JdbcParam>> batchParams){
|
||
JdbcContext context = null;
|
||
try {
|
||
context = new JdbcContext(true,true);
|
||
context.init(sql);
|
||
context.setBatchParams(batchParams);
|
||
return context.executeBatch(-1);
|
||
} catch (SQLException e) {
|
||
throw context.createException(e);
|
||
}finally {
|
||
context.end();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 查询基础数据类型
|
||
* */
|
||
public static <T>T queryPrimitive(String sql,Class<T> type,List<JdbcParam> params){
|
||
JdbcContext context = null;
|
||
try {
|
||
context = new JdbcContext(true,true);
|
||
context.init(sql);
|
||
context.setParams(params);
|
||
ResultSet set = context.executeQuery();
|
||
while (set.next()) {
|
||
return ResultSetUtils.getObject(set,1,type);
|
||
}
|
||
} catch (SQLException e) {
|
||
throw context.createException(e);
|
||
}finally {
|
||
context.end();
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 查询基础数据类型
|
||
* */
|
||
public static <T>List<T> queryListPrimitive(String sql,Class<T> type,List<JdbcParam> params){
|
||
JdbcContext context = null;
|
||
try {
|
||
context = new JdbcContext(true,true);
|
||
context.init(sql);
|
||
context.setParams(params);
|
||
ResultSet set = context.executeQuery();
|
||
List<T> res = CollectionUtils.newArrayList();
|
||
while (set.next()) {
|
||
res.add(ResultSetUtils.getObject(set,1,type));
|
||
}
|
||
return res;
|
||
} catch (SQLException e) {
|
||
throw context.createException(e);
|
||
}finally {
|
||
context.end();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
}
|