---初始化项目

This commit is contained in:
2025-10-10 09:20:48 +08:00
parent a8e0f1c377
commit 7f74c186da
203 changed files with 14674 additions and 0 deletions

View File

@ -0,0 +1,16 @@
package com.pictc.cache;
public abstract class AbstractCache<K,V> implements TanukiCache<K,V>{
private final String cache_name;
public AbstractCache(String name) {
this.cache_name=name;
}
@Override
public String getCacheName() {
return cache_name;
}
}

View File

@ -0,0 +1,13 @@
package com.pictc.cache;
public class CacheFactory{
public static final String PROVIDER="provider-name";
public static final String PROVIDER_CLASS="provider-classpath";
public static <K, V> TanukiCache<K, V> factory(String cacheName) {
return new DefaultCacheProvider<K, V>(cacheName);
}
}

View File

@ -0,0 +1,109 @@
package com.pictc.cache;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class DefaultCacheProvider<K,V> extends AbstractCache<K,V> implements TanukiCache<K,V>{
private final HashMap<K, V> cache;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
public DefaultCacheProvider(String cache_name) {
super(cache_name);
cache = new HashMap<K, V>();
}
@Override
public void save(K key, V value) {
writeLock.lock();
try {
if(cache.containsKey(key)) cache.remove(key);
cache.put(key, value);
} finally {
writeLock.unlock();
}
}
@Override
public void remove(K key) {
writeLock.lock();
try {
cache.remove(key);
} finally {
writeLock.unlock();
}
}
@Override
public V get(K key) {
readLock.lock();
try {
return cache.get(key);
} finally {
readLock.unlock();
}
}
@Override
public boolean containsKey(K key) {
readLock.lock();
try {
return cache.containsKey(key);
} finally {
readLock.unlock();
}
}
@Override
public void clear() {
writeLock.lock();
try {
cache.clear();
} finally {
writeLock.unlock();
}
}
@Override
public List<V> values() {
return new ArrayList<V>(cache.values());
}
@Override
public void save(K key, V value, long time, TimeUnit unit) {
writeLock.lock();
try {
cache.put(key, value);
setExpire(key, time, unit);
} finally {
writeLock.unlock();
}
}
@Override
public Set<K> keys() {
return cache.keySet();
}
@Override
public boolean setExpire(K key, long time, TimeUnit unit) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -0,0 +1,29 @@
package com.pictc.cache;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public interface TanukiCache<K,V>{
String getCacheName();
void save(K key,V value);
void save(K key,V value,long time,TimeUnit unit);
boolean setExpire(K key,long time,TimeUnit unit);
void remove(K key);
V get(K key);
boolean containsKey(K key);
List<V> values();
Set<K> keys();
void clear();
}

View File

@ -0,0 +1,19 @@
package com.pictc.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Data;
@ConfigurationProperties("datalog.db")
@Data
public class DataLogDbConfig {
private String url;
private String username;
private String password;
private String driverClassName;
}

View File

@ -0,0 +1,66 @@
package com.pictc.config;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.pool.DruidDataSource;
import com.pictc.jdbc.JdbcContextUtils;
import com.pictc.utils.StringUtils;
@Configuration
public class JdbcConfig {
@Value("${spring.datasource.dynamic.datasource.master.username:itc_dne}")
private String globalUsername;
@Value("${spring.datasource.dynamic.datasource.master.password:itc_dne}")
private String globalPassword;
@Value("${spring.datasource.dynamic.datasource.master.driver-class-name:com.kingbase8.Driver}")
private String globalDriver;
@Bean
public JdbcContextUtils jdbcContextUtils() throws SQLException {
JdbcContextUtils contextUtils = new JdbcContextUtils();
contextUtils.setLogSource(logDataSource());
return contextUtils;
}
@Bean
public DataLogDbConfig logDataDbConfig() {
return new DataLogDbConfig();
}
/**
* 额外的日志数据源配置
*/
public DataSource logDataSource() throws SQLException {
DruidDataSource dataSource = new DruidDataSource();
DataLogDbConfig dbConfig = logDataDbConfig();
// 日志数据库连接信息
dataSource.setUrl(dbConfig.getUrl());
dataSource.setUsername(StringUtils.opt(dbConfig.getUsername(),globalUsername));
dataSource.setPassword(StringUtils.opt(dbConfig.getPassword(),globalPassword));
dataSource.setDriverClassName(StringUtils.opt(dbConfig.getDriverClassName(),globalDriver));
// 日志库连接池参数(可独立配置)
dataSource.setInitialSize(5);
dataSource.setMinIdle(3);
dataSource.setMaxActive(20);
dataSource.setMaxWait(20000);
dataSource.setTimeBetweenEvictionRunsMillis(45000);
dataSource.setMinEvictableIdleTimeMillis(1200000);
// 连接验证
dataSource.setValidationQuery("SELECT 1");
dataSource.setTestWhileIdle(true);
return dataSource;
}
}

View File

@ -0,0 +1,30 @@
package com.pictc.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.pictc.utils.DataLogTools;
import com.pictc.utils.MybatisTools;
import com.pictc.utils.SpringTools;
@Configuration
public class PcitcAutoConfig {
@Bean
public SpringTools springTools() {
return new SpringTools();
}
@Bean
public MybatisTools mapperManager() {
return new MybatisTools();
}
@Bean
public DataLogTools dataLogTools() {
return new DataLogTools();
}
}

View File

@ -0,0 +1,87 @@
package com.pictc.config;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.Properties;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ScanConfig {
public static final String AUTO_FILE_NAME="auto-scan.txt";
private static final String FILE_PROCOTOL="file";
private static final String JAR_PROCOTOL="jar";
private static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
}
catch (Throwable ex) {}
if (cl == null) {
cl = ScanConfig.class.getClassLoader();
if (cl == null) {
try {
cl = ClassLoader.getSystemClassLoader();
}
catch (Throwable ex) {}
}
}
return cl;
}
public static void scan(String name,ScanFilter filter) {
try {
Enumeration<URL> dirs = getDefaultClassLoader().getResources(name);
if(dirs!=null) {
while(dirs.hasMoreElements()) {
URL url = dirs.nextElement();
if(FILE_PROCOTOL.equals(url.getProtocol())) {
filter.accept(readConf(url.openStream()));
}else if(JAR_PROCOTOL.equals(url.getProtocol())) {
JarFile jarFile = ((JarURLConnection)url.openConnection()).getJarFile();
ZipEntry entry = jarFile.getEntry(name);
if(entry!=null) {
filter.accept(readConf(jarFile.getInputStream(entry)));
}
}
}
}else {
log.info("没有扫描到任何东西!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static Properties readConf(InputStream in) {
Properties pro = new Properties();
try {
pro.load(in);
} catch (IOException e) {
e.printStackTrace();
log.info("读取配置文件错误");
}
return pro;
}
public static void scanConfig(ScanFilter filter) {
scan(AUTO_FILE_NAME,filter);
}
public interface ScanFilter{
public void accept(Properties conf);
}
}

View File

@ -0,0 +1,12 @@
package com.pictc.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
public class UniqueNameGenerator extends AnnotationBeanNameGenerator {
@Override
protected String buildDefaultBeanName(BeanDefinition definition) {
return definition.getBeanClassName();
}
}

View File

@ -0,0 +1,105 @@
package com.pictc.converts;
import java.util.HashMap;
import java.util.Map;
import com.pictc.converts.date.DateHandler;
import com.pictc.converts.date.LocalDateHandler;
import com.pictc.converts.date.LocalDateTimeHandler;
import com.pictc.converts.date.LocalTimeHandler;
import com.pictc.converts.date.TimeHandler;
import com.pictc.converts.date.TimestampHandler;
import com.pictc.converts.primitive.BigDecimalHandler;
import com.pictc.converts.primitive.BigIntegerHandler;
import com.pictc.converts.primitive.BooleanHandler;
import com.pictc.converts.primitive.ByteHandler;
import com.pictc.converts.primitive.CharacterHandler;
import com.pictc.converts.primitive.DoubleHandler;
import com.pictc.converts.primitive.EnumHandler;
import com.pictc.converts.primitive.FloatHandler;
import com.pictc.converts.primitive.IntegerHandler;
import com.pictc.converts.primitive.LongHandler;
import com.pictc.converts.primitive.ShortHandler;
import com.pictc.converts.primitive.StringHandler;
import com.pictc.utils.BeanUtils;
import com.pictc.utils.ClassUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ConverUtil {
private static Map<Class<?>, SuperHandler> handlers = new HashMap<Class<?>,SuperHandler>();
static {
Class<?>[] hcls = new Class<?>[] { DateHandler.class,TimestampHandler.class,TimeHandler.class,
LocalDateTimeHandler.class,LocalDateHandler.class,LocalTimeHandler.class,
BooleanHandler.class, ByteHandler.class,
DoubleHandler.class, FloatHandler.class,
IntegerHandler.class, LongHandler.class, ShortHandler.class,
StringHandler.class,CharacterHandler.class,
BigIntegerHandler.class,BigDecimalHandler.class };
for (int i = 0; i < hcls.length; i++) {
try {
SuperHandler handler = BeanUtils.newInstance(hcls[i]);
Class<?>[] classes = handler.getConverts();
for (int j = 0; j < classes.length; j++) {
handlers.put(classes[j], handler);
}
} catch (Exception e) {
log.error("类型转换器初始化异常",e);
}
}
}
public static void register(Class<?> cls) {
if (handlers.containsKey(cls)) {
return;
}
if(cls.isEnum()) {
handlers.put(cls, new EnumHandler(cls));
return;
}
if (!ClassUtils.hashClass(cls, SuperHandler.class)) {
return;
}
TypeHandler<?> handler;
try {
handler = BeanUtils.newInstance(cls);
handlers.put(cls, handler);
} catch (Exception e) {
log.error("注册类型转换器异常",e);
}
}
@SuppressWarnings("unchecked")
public static <T> TypeHandler<T> geTypeHandler(Class<T> cls) {
if (!handlers.containsKey(cls)) {
register(cls);
}
return (TypeHandler<T>) handlers.get(cls);
}
//字符串
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Object toJsonValue(Class<?> klass,Object val){
TypeHandler handler = geTypeHandler(klass);
return handler!=null?handler.convert(val):val;
}
//字符串
@SuppressWarnings("unchecked")
public static <T>T jsonToValue(Class<T> klass,Object val){
TypeHandler<T> handler = geTypeHandler(klass);
return handler!=null?handler.valueToObject(val):(T) val;
}
}

View File

@ -0,0 +1,22 @@
package com.pictc.converts;
public class ConvertException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 1L;
public ConvertException(String message) {
super(message);
}
public ConvertException(Class<?> from,Object val,Class<?> to) {
super(from.getName() + "类型 "+(val==null?"null":val.toString())+" 无法转换至-->" + to.getName());
}
public ConvertException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,30 @@
package com.pictc.converts;
public class ObjectHandler implements TypeHandler<Object> {
private Class<?>[] converts = new Class<?>[] { Object.class };
@Override
public Object convert(Object value) {
return value;
}
@Override
public Object valueToObject(Object val) {
if (val == null) {
return null;
}
return val;
}
@Override
public boolean isType(Class<?> type) {
return Object.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
}

View File

@ -0,0 +1,10 @@
package com.pictc.converts;
public interface SuperHandler {
boolean isType(Class<?> type);
Class<?>[] getConverts();
}

View File

@ -0,0 +1,23 @@
package com.pictc.converts;
public interface TypeHandler<T> extends SuperHandler{
boolean isType(Class<?> type);
Class<?>[] getConverts();
/**
* 转换json时调用
* @param <T>
*/
Object convert(T value);
/**
* json转换对象是调用
* @param <T>
*/
T valueToObject(Object val);
public abstract class TypeHandlerVoid implements TypeHandler<Object>{}
}

View File

@ -0,0 +1,49 @@
package com.pictc.converts.date;
import java.util.Date;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class DateHandler implements TypeHandler<Date>{
private Class<?>[] converts=new Class<?>[] {Date.class};
@Override
public boolean isType(Class<?> type) {
return Date.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
@Override
public Object convert(Date value) {
if(value==null) {
return null;
}
return value.getTime();
}
@Override
public Date valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return Date.class.cast(val);
}else {
try {
return new Date(Long.valueOf(val.toString()));
} catch (Exception e) {
throw new ConvertException(vcs,val,Date.class);
}
}
}
}

View File

@ -0,0 +1,50 @@
package com.pictc.converts.date;
import java.time.LocalDate;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
import com.pictc.utils.DateUtils;
public class LocalDateHandler implements TypeHandler<LocalDate>{
private Class<?>[] converts=new Class<?>[] {LocalDate.class};
@Override
public boolean isType(Class<?> type) {
return LocalDate.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
@Override
public Object convert(LocalDate value) {
if(value==null) {
return null;
}
return DateUtils.format(value);
}
@Override
public LocalDate valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return LocalDate.class.cast(val);
}else {
try {
return DateUtils.toLocalDate(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,LocalDate.class);
}
}
}
}

View File

@ -0,0 +1,50 @@
package com.pictc.converts.date;
import java.time.LocalDateTime;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
import com.pictc.utils.DateUtils;
public class LocalDateTimeHandler implements TypeHandler<LocalDateTime>{
private Class<?>[] converts=new Class<?>[] {LocalDateTime.class};
@Override
public boolean isType(Class<?> type) {
return LocalDateTime.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
@Override
public Object convert(LocalDateTime value) {
if(value==null) {
return null;
}
return DateUtils.format(value);
}
@Override
public LocalDateTime valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return LocalDateTime.class.cast(val);
}else {
try {
return DateUtils.toLocalDateTime(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,LocalDateTime.class);
}
}
}
}

View File

@ -0,0 +1,50 @@
package com.pictc.converts.date;
import java.time.LocalTime;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
import com.pictc.utils.DateUtils;
public class LocalTimeHandler implements TypeHandler<LocalTime>{
private Class<?>[] converts=new Class<?>[] {LocalTime.class};
@Override
public boolean isType(Class<?> type) {
return LocalTime.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
@Override
public Object convert(LocalTime value) {
if(value==null) {
return null;
}
return DateUtils.format(value);
}
@Override
public LocalTime valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return LocalTime.class.cast(val);
}else {
try {
return DateUtils.toLocalTime(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,LocalTime.class);
}
}
}
}

View File

@ -0,0 +1,43 @@
package com.pictc.converts.date;
import java.sql.Time;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class TimeHandler implements TypeHandler<Time>{
private Class<?>[] converts=new Class<?>[] {Time.class};
@Override
public boolean isType(Class<?> type) {
return Time.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
@Override
public Object convert(Time value) {
return value.toString();
}
@Override
public Time valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return Time.class.cast(val);
}else {
try {
return new Time(Long.valueOf(val.toString()));
} catch (Exception e) {
throw new ConvertException(vcs,val,Time.class);
}
}
}
}

View File

@ -0,0 +1,76 @@
package com.pictc.converts.date;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
import com.pictc.utils.ClassUtils;
import com.pictc.utils.DateUtils;
import com.pictc.utils.StringUtils;
public class TimestampHandler implements TypeHandler<Timestamp> {
private Class<?>[] converts = new Class<?>[] { Timestamp.class };
@Override
public boolean isType(Class<?> type) {
return Timestamp.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
@Override
public Object convert(Timestamp value) {
if (value == null) {
return null;
}
String str = value.toString();
if (str.contains(".")) {
str = str.split("\\.")[0];
}
return str;
}
@Override
public Timestamp valueToObject(Object val) {
if (val == null) {
return null;
}
Class<?> vcs = val.getClass();
if (isType(vcs)) {
return Timestamp.class.cast(val);
} else if (val instanceof String) {
String str = (String) val;
if (str.matches("^\\d+$")) {
return new Timestamp(Long.valueOf(str));
}else if(str.matches("^.*T.*\\+.*$")) {
LocalDateTime date = LocalDateTime.parse(str,DateTimeFormatter.ISO_OFFSET_DATE_TIME);
return DateUtils.toTimestamp(date);
} else if (StringUtils.isEmpty(str)) {
return null;
} else {
throw new ConvertException(vcs, val, Timestamp.class);
}
}else if(ClassUtils.isDate(vcs)) {
return new Timestamp(((Date)val).getTime());
}else if(Long.class.equals(vcs) || long.class.equals(vcs)) {
return new Timestamp(Long.class.cast(val));
}else if(LocalDateTime.class.equals(vcs)){
return DateUtils.toTimestamp(LocalDateTime.class.cast(val));
} else {
throw new ConvertException(vcs, val, Timestamp.class);
}
}
}

View File

@ -0,0 +1,52 @@
package com.pictc.converts.primitive;
import java.math.BigDecimal;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
import com.pictc.utils.StringUtils;
public class BigDecimalHandler implements TypeHandler<BigDecimal>{
private Class<?>[] converts=new Class<?>[] {BigDecimal.class};
@Override
public boolean isType(Class<?> type) {
return BigDecimal.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
@Override
public String convert(BigDecimal value) {
if(value==null) {
return null;
}
return value.toString();
}
@Override
public BigDecimal valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return BigDecimal.class.cast(val);
}else {
try {
String strVal=val.toString();
if(!StringUtils.isEmpty(strVal)) {
return new BigDecimal(strVal);
}
return null;
} catch (Exception e) {
throw new ConvertException(vcs,val,BigDecimal.class);
}
}
}
}

View File

@ -0,0 +1,47 @@
package com.pictc.converts.primitive;
import java.math.BigInteger;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class BigIntegerHandler implements TypeHandler<BigInteger>{
private Class<?>[] converts=new Class<?>[] {BigInteger.class};
@Override
public boolean isType(Class<?> type) {
return BigInteger.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
@Override
public Object convert(BigInteger value) {
if(value==null) {
return null;
}
return value.toString();
}
@Override
public BigInteger valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return BigInteger.class.cast(val);
}else {
try {
return new BigInteger(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,BigInteger.class);
}
}
}
}

View File

@ -0,0 +1,43 @@
package com.pictc.converts.primitive;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class BooleanHandler implements TypeHandler<Boolean>{
private Class<?>[] converts=new Class<?>[] {Boolean.class,boolean.class};
@Override
public boolean isType(Class<?> type) {
return Boolean.class.equals(type)||boolean.class.equals(type);
}
@Override
public Object convert(Boolean value) {
return value;
}
@Override
public Boolean valueToObject(Object val) {
if(val==null) {
return false;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return Boolean.class.cast(val);
}else {
try {
return Boolean.valueOf(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,Boolean.class);
}
}
}
@Override
public Class<?>[] getConverts() {
return converts;
}
}

View File

@ -0,0 +1,47 @@
package com.pictc.converts.primitive;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class ByteHandler implements TypeHandler<Byte>{
private Class<?>[] converts=new Class<?>[] {Byte.class,byte.class};
@Override
public boolean isType(Class<?> type) {
return Byte.class.equals(type)||byte.class.equals(type);
}
@Override
public Object convert(Byte value) {
return value;
}
@Override
public Byte valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return Byte.class.cast(val);
}else if(Number.class.equals(vcs)) {
return Number.class.cast(val).byteValue();
}else {
try {
return Byte.valueOf(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,Byte.class);
}
}
}
@Override
public Class<?>[] getConverts() {
return converts;
}
}

View File

@ -0,0 +1,42 @@
package com.pictc.converts.primitive;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class CharacterHandler implements TypeHandler<Character>{
private Class<?>[] converts=new Class<?>[] {Character.class,char.class};
@Override
public boolean isType(Class<?> type) {
return Character.class.equals(type)|| char.class.equals(type);
}
@Override
public Object convert(Character value) {
return value;
}
@Override
public Character valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return Character.class.cast(val);
}else {
try {
return val.toString().charAt(0);
} catch (Exception e) {
throw new ConvertException(vcs,val,Character.class);
}
}
}
@Override
public Class<?>[] getConverts() {
return converts;
}
}

View File

@ -0,0 +1,60 @@
package com.pictc.converts.primitive;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class DoubleHandler implements TypeHandler<Double>{
private Class<?>[] converts=new Class<?>[] {Double.class,double.class};
@Override
public boolean isType(Class<?> type) {
return Double.class.equals(type) || double.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
@Override
public Object convert(Double value) {
return doubleToString(value);
}
@Override
public Double valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return Double.class.cast(val);
}else if(Number.class.equals(vcs)) {
return Number.class.cast(val).doubleValue();
}else {
try {
return Double.valueOf(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,Double.class);
}
}
}
public static String doubleToString(double d) {
if (Double.isInfinite(d) || Double.isNaN(d)) {
return "null";
}
String string = Double.toString(d);
if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && string.indexOf('E') < 0) {
while (string.endsWith("0")) {
string = string.substring(0, string.length() - 1);
}
if (string.endsWith(".")) {
string = string.substring(0, string.length() - 1);
}
}
return string;
}
}

View File

@ -0,0 +1,69 @@
package com.pictc.converts.primitive;
import java.lang.reflect.Method;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class EnumHandler implements TypeHandler<Enum<?>>{
private Class<?> klazz;
public EnumHandler(Class<?> klazz) {
super();
this.klazz = klazz;
}
@Override
public boolean isType(Class<?> type) {
return type.isEnum();
}
@Override
public Class<?>[] getConverts() {
return null;
}
@Override
public Object convert(Enum<?> value) {
if(value==null) {
return null;
}
return value.toString();
}
@SuppressWarnings("unchecked")
public <T>T valueToObject(Class<T> clazz,Object val) {
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return (T)val;
}else {
try {
Method method=clazz.getMethod("valueOf", String.class);
return (T) method.invoke(null,val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,Enum.class);
}
}
}
@Override
public Enum<?> valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return (Enum<?>) val;
}else {
try {
Method method=klazz.getMethod("valueOf", String.class);
return (Enum<?>)method.invoke(null,val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,klazz);
}
}
}
}

View File

@ -0,0 +1,44 @@
package com.pictc.converts.primitive;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class FloatHandler implements TypeHandler<Float>{
private Class<?>[] converts=new Class<?>[] {Float.class,float.class};
@Override
public boolean isType(Class<?> type) {
return Float.class.equals(type)|| float.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
@Override
public Object convert(Float value) {
return value;
}
@Override
public Float valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return Float.class.cast(val);
}else if(Number.class.equals(vcs)) {
return Number.class.cast(val).floatValue();
}else {
try {
return Float.valueOf(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,Float.class);
}
}
}
}

View File

@ -0,0 +1,47 @@
package com.pictc.converts.primitive;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class IntegerHandler implements TypeHandler<Integer>{
private Class<?>[] converts=new Class<?>[] {Integer.class,int.class};
@Override
public Object convert(Integer value) {
return value;
}
@Override
public Integer valueToObject(Object val){
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return Integer.class.cast(val);
}else if(Number.class.equals(vcs)) {
return Number.class.cast(val).intValue();
}else {
try {
return Integer.valueOf(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,Integer.class);
}
}
}
@Override
public boolean isType(Class<?> type) {
return Integer.class.equals(type)|| int.class.equals(type);
}
@Override
public Class<?>[] getConverts() {
return converts;
}
}

View File

@ -0,0 +1,45 @@
package com.pictc.converts.primitive;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class LongHandler implements TypeHandler<Long>{
private Class<?>[] converts=new Class<?>[] {Long.class,long.class};
@Override
public boolean isType(Class<?> type) {
return Long.class.equals(type)||long.class.equals(type);
}
@Override
public Object convert(Long value) {
return value;
}
@Override
public Long valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return Long.class.cast(val);
}else if(Number.class.equals(vcs)) {
return Number.class.cast(val).longValue();
}else {
try {
return Long.valueOf(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,Long.class);
}
}
}
@Override
public Class<?>[] getConverts() {
return converts;
}
}

View File

@ -0,0 +1,45 @@
package com.pictc.converts.primitive;
import com.pictc.converts.ConvertException;
import com.pictc.converts.TypeHandler;
public class ShortHandler implements TypeHandler<Short>{
private Class<?>[] converts=new Class<?>[] {Short.class,short.class};
@Override
public boolean isType(Class<?> type) {
return Short.class.equals(type)|| short.class.equals(type);
}
@Override
public Object convert(Short value) {
return value;
}
@Override
public Short valueToObject(Object val) {
if(val==null) {
return null;
}
Class<?> vcs=val.getClass();
if(isType(vcs)) {
return Short.class.cast(vcs);
}else if(Number.class.equals(vcs)) {
return Number.class.cast(val).shortValue();
}else {
try {
return Short.valueOf(val.toString());
} catch (Exception e) {
throw new ConvertException(vcs,val,Short.class);
}
}
}
@Override
public Class<?>[] getConverts() {
return converts;
}
}

View File

@ -0,0 +1,34 @@
package com.pictc.converts.primitive;
import com.pictc.converts.TypeHandler;
public class StringHandler implements TypeHandler<String>{
private Class<?>[] converts=new Class<?>[] {String.class};
@Override
public boolean isType(Class<?> type) {
return String.class.equals(type);
}
@Override
public Object convert(String value) {
return value;
}
@Override
public String valueToObject(Object val) {
if(val==null) {
return null;
}
return val.toString();
}
@Override
public Class<?>[] getConverts() {
return converts;
}
}

View File

@ -0,0 +1,49 @@
package com.pictc.datalog;
import java.lang.reflect.Field;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.pictc.annotations.datalog.LogField;
import com.pictc.jdbc.JdbcContextUtils;
import com.pictc.utils.SpringAnnotationUtils;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class LogFieldInfo implements Comparable<LogFieldInfo>{
private LogField annotation;
private Field field;
private TableFieldInfo fieldInfo;
public static LogFieldInfo ofField(Field field) {
return new LogFieldInfo().setField(field).setAnnotation(SpringAnnotationUtils.findAnnotation(field, LogField.class));
}
@Override
public int compareTo(LogFieldInfo o) {
return annotation.index() - o.annotation.index();
}
public String getFieldName() {
return field.getName();
}
public String getName() {
return annotation.name();
}
public String getColumn() {
return fieldInfo!=null?fieldInfo.getColumn():JdbcContextUtils.fieldToColumn(field.getName());
}
public Class<?> getJavaType(){
return field.getType();
}
}

View File

@ -0,0 +1,37 @@
package com.pictc.datalog;
import java.lang.reflect.Field;
import com.pictc.annotations.datalog.JoinType;
import com.pictc.annotations.datalog.LogJoin;
import com.pictc.utils.DataLogTools;
import com.pictc.utils.SpringAnnotationUtils;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class LogJoinInfo {
private Field field;
private LogJoin join;
public static LogJoinInfo ofAnnotation(Class<?> klazz,Field field) {
return new LogJoinInfo().setJoin(SpringAnnotationUtils.findAnnotation(field, LogJoin.class)).setField(field);
}
public LogTableInfo getTableInfo() {
return DataLogTools.getAnnotation(join.target());
}
public boolean isList() {
return join.type()==JoinType.MANY;
}
public Class<?> getTargetClass() {
return join.target();
}
}

View File

@ -0,0 +1,165 @@
package com.pictc.datalog;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.pictc.annotations.datalog.LogField;
import com.pictc.annotations.datalog.LogJoin;
import com.pictc.annotations.datalog.LogTable;
import com.pictc.utils.BeanUtils;
import com.pictc.utils.CollectionUtils;
import com.pictc.utils.MybatisTools;
import com.pictc.utils.SpringAnnotationUtils;
import com.pictc.utils.StringUtils;
import cn.hutool.core.bean.BeanUtil;
import lombok.Data;
@Data
public class LogTableInfo {
private LogTable table;
private Field idField;
private TableInfo info;
private List<LogFieldInfo> fields = CollectionUtils.newArrayList();
private Map<String,LogFieldInfo> fieldMap = CollectionUtils.newConcurrentHashMap();
private Map<String,LogFieldInfo> columnMap = CollectionUtils.newConcurrentHashMap();
private List<LogJoinInfo> joins = CollectionUtils.newArrayList();
private Class<?> klazz;
public LogTableInfo(Class<?> klazz) {
super();
this.klazz = klazz;
table = SpringAnnotationUtils.findAnnotation(klazz, LogTable.class);
info = MybatisTools.getTableInfo(table.source());
initId();
initFields();
initJoins();
}
public String getName() {
return table.name();
}
public boolean isValid() {
return table!=null;
}
private void initId() {
String idKey = info.getKeyProperty();
if(StringUtils.isEmpty(idKey)) {
idKey = "id";
}
idField = BeanUtils.getField(idKey,klazz);
}
private void initFields() {
if(isValid()) {
List<Field> _fields = BeanUtils.getFields(klazz, LogField.class);
if(CollectionUtils.isNotEmpty(_fields)) {
Map<String, TableFieldInfo> fieldMap = null;
if(info!=null) {
fieldMap = info.getFieldList().stream().collect(Collectors.toMap(TableFieldInfo::getProperty,Function.identity()));
}
for (Field field : _fields) {
LogFieldInfo fieldInfo = LogFieldInfo.ofField(field);
if(fieldMap!=null) fieldInfo.setFieldInfo(fieldMap.get(field.getName()));
fields.add(fieldInfo);
}
Collections.sort(fields);
this.fieldMap = fields.stream().collect(Collectors.toMap(LogFieldInfo::getFieldName,Function.identity()));
this.columnMap = fields.stream().collect(Collectors.toMap(LogFieldInfo::getColumn,Function.identity()));
}
}
}
private void initJoins() {
if(isValid()) {
List<Field> _fields = BeanUtils.getFields(klazz, LogJoin.class);
if(CollectionUtils.isNotEmpty(_fields)) {
for (Field field : _fields) {
fields.add(LogFieldInfo.ofField(field));
joins.add(LogJoinInfo.ofAnnotation(klazz, field));
}
}
}
}
public Long getIdValue(Object obj) {
return BeanUtils.getFieldValue(idField,obj);
}
public void setIdValue(Object entity, Long id) {
if(entity==null) return;
BeanUtils.setFieldValue(idField,id,entity);
}
public Object getFieldValue(Object entity,String field) {
if(entity==null) return null;
LogFieldInfo fieldInfo = this.fieldMap.get(field);
return BeanUtils.getFieldValue(fieldInfo.getField(),entity);
}
public Object getFieldValue(Object entity,Field field) {
if(entity==null) return null;
return BeanUtils.getFieldValue(field,entity);
}
public void setFieldValue(Object entity,String field,Object value) {
if(entity==null) return;
LogFieldInfo fieldInfo = this.fieldMap.get(field);
BeanUtils.setFieldValue(fieldInfo.getField(),value,entity);
}
public void setFieldValue(Object entity,Field field,Object value) {
if(entity==null) return;
BeanUtils.setFieldValue(field,value,entity);
}
public String getColumn(String field) {
LogFieldInfo fieldInfo = this.fieldMap.get(field);
return fieldInfo.getColumn();
}
public String getIdColumn() {
LogFieldInfo fieldInfo = this.fieldMap.get(idField.getName());
return fieldInfo.getColumn();
}
public Class<?> getEntityType() {
return info.getEntityType();
}
public Object toEntity(Object dto) {
return BeanUtil.toBean(dto, info.getEntityType());
}
public Object toDto(Object entity) {
return BeanUtil.toBean(entity,klazz);
}
public String getTableName() {
return info.getTableName();
}
}

View File

@ -0,0 +1,37 @@
package com.pictc.exceptions;
/**
* @author 张福财
* @date 2025年9月16日 下午3:43:37
* @Description: 数据操作异常
*/
public class OrmException extends RuntimeException{
/**
* @Fields {todo}(用一句话描述这个变量表示什么)
*/
private static final long serialVersionUID = 1L;
public OrmException() {
super();
}
public OrmException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public OrmException(String message, Throwable cause) {
super(message, cause);
}
public OrmException(String message) {
super(message);
}
public OrmException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,33 @@
package com.pictc.exceptions;
public class TFieldException extends RuntimeException{
/**
* @Fields {todo}(用一句话描述这个变量表示什么)
*/
private static final long serialVersionUID = 1L;
public TFieldException() {
super();
}
public TFieldException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public TFieldException(String message, Throwable cause) {
super(message, cause);
}
public TFieldException(String message) {
super(message);
}
public TFieldException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,33 @@
package com.pictc.exceptions;
public class TMethodException extends RuntimeException{
/**
* @Fields {todo}(用一句话描述这个变量表示什么)
*/
private static final long serialVersionUID = 1L;
public TMethodException() {
super();
}
public TMethodException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public TMethodException(String message, Throwable cause) {
super(message, cause);
}
public TMethodException(String message) {
super(message);
}
public TMethodException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,258 @@
package com.pictc.jdbc;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.support.JdbcUtils;
import com.pictc.jdbc.model.JdbcParam;
import com.pictc.utils.CollectionUtils;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Getter
@Setter
public class JdbcContext {
public static final int DEF_STEP = 1000;
private JdbcTemplate jdbc;
private DataSource source;
private DataSource logSource;
private Connection conn;
private PreparedStatement stmt;
private CallableStatement ctmt;
private long start;
private int size = 0;
private boolean isQuery = false;
private boolean isCall = false;
private boolean datalog = false;
private String sql;
private List<JdbcParam> params;
private List<List<JdbcParam>> batchParams;
public JdbcContext(boolean isQuery) throws SQLException {
this(isQuery, false);
}
public JdbcContext(boolean isQuery,boolean datalog) throws SQLException {
super();
this.isQuery = isQuery;
this.datalog = datalog;
this.start = System.currentTimeMillis();
this.source = JdbcContextUtils.getSource();
this.logSource = JdbcContextUtils.getLogSource();
this.jdbc = JdbcContextUtils.getJdbc();
this.conn = datalog?DataSourceUtils.getConnection(this.logSource):DataSourceUtils.getConnection(this.source);
}
public JdbcContext init(String sql) throws SQLException {
this.sql = sql;
this.stmt = (PreparedStatement) getStatement(this.conn,sql);
return this;
}
public DataSource getReleaseSource() {
return datalog?logSource:source;
}
public JdbcContext initCall(String sql) throws SQLException {
this.sql = sql;
this.isCall = true;
this.ctmt = (CallableStatement) getStatement(this.conn,sql);
return this;
}
public JdbcContext addParam(int jdbc,Object val) {
if(params==null) {
params = CollectionUtils.newArrayList();
}
params.add(new JdbcParam().setJdbc(jdbc).setVal(val));
return this;
}
public JdbcContext addBatchParam(int index,int jdbc,Object val) {
if(batchParams==null) {
batchParams = CollectionUtils.newArrayList();
}
if(batchParams.size() <=index) {
batchParams.add(CollectionUtils.newArrayList());
}
List<JdbcParam> bpam = batchParams.get(index);
bpam.add(new JdbcParam().setJdbc(jdbc).setVal(val));
return this;
}
private Statement getStatement(Connection conn,String sql) throws SQLException {
Statement stmt = null;
if(this.isCall) {
stmt = conn.prepareCall(sql);
}else if(this.isQuery) {
stmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
}else {
stmt = conn.prepareStatement(sql);
}
int fetchSize = jdbc.getFetchSize();
if (fetchSize >= 0) {
stmt.setFetchSize(fetchSize);
}
int maxRows = jdbc.getMaxRows();
if (maxRows >= 0) {
stmt.setMaxRows(maxRows);
}
DataSourceUtils.applyTimeout(stmt,getReleaseSource(),jdbc.getQueryTimeout());
return stmt;
}
private void executeParams() throws SQLException {
if(params!=null) {
for (int i = 0; i < params.size(); i++) {
JdbcParam parameter = params.get(i);
int index = i+1;
if(parameter.isOut()) {
ctmt.registerOutParameter(index,parameter.getJdbc());
continue;
}
this.setParameter(index,parameter.getJdbc(),parameter.getVal());
}
}
}
public int executeUpdate() throws SQLException {
executeParams();
size = this._executeUpdate();
return size;
}
public boolean execute() throws SQLException {
executeParams();
return this._execute();
}
public int executeBatch() throws SQLException {
return executeBatch(DEF_STEP);
}
public int executeBatch(int step) throws SQLException {
int rows = 0;
step = step <=0?DEF_STEP:step;
if(batchParams!=null && !batchParams.isEmpty()) {
int j = 0;
for (List<JdbcParam> list : batchParams) {
for (int i = 0; i < list.size(); i++) {
JdbcParam parameter = list.get(i);
setParameter(i+1, parameter.getJdbc(),parameter.getVal());
}
this.addBatch();
j++;
if(j%step==0) {
rows=countRow(rows,this._executeBatch());
}
}
}
rows=countRow(rows,this._executeBatch());
size = rows;
return rows;
}
public ResultSet executeQuery() throws SQLException {
executeParams();
ResultSet rset = this._executeQuery();
rset.last();
size = rset.getRow(); //获得ResultSet的总行数
rset.beforeFirst();
return rset;
}
private ResultSet _executeQuery() throws SQLException {
return getStatement().executeQuery();
}
private PreparedStatement getStatement() {
return this.isCall?ctmt:stmt;
}
private void setParameter(int index,int jdbc,Object val) throws SQLException {
PreparedStatement _stmt = getStatement();
if(val==null) {
_stmt.setNull(index,jdbc);
}else {
_stmt.setObject(index,val,jdbc);
}
}
private void addBatch() throws SQLException {
getStatement().addBatch();
}
private int[] _executeBatch() throws SQLException {
return getStatement().executeBatch();
}
private int _executeUpdate() throws SQLException {
return getStatement().executeUpdate();
}
private boolean _execute() throws SQLException {
return getStatement().execute();
}
private int countRow(int rows,int[] rowArray) {
if(rowArray!=null) {
for (int i = 0; i < rowArray.length; i++) {
rows+=rowArray[i];
}
}
return rows;
}
public DataAccessException createException(SQLException e) {
return jdbc.getExceptionTranslator().translate(sql,null,e);
}
public void end() {
JdbcUtils.closeStatement(getStatement());
if(conn!=null) {
DataSourceUtils.releaseConnection(conn,getReleaseSource());
}
log.info(" Statement: 【{}】",sql);
if(params!=null && !params.isEmpty()) {
log.info("Parameters: {}",params.toString());
}
long con = System.currentTimeMillis()-start;
if(!this.isQuery) {
log.info(" consuming: 【{} ms】--- 数据:【{}条】--- 效率:【{} ms/条】",con,size,size>0?(con/size):con);
}else {
log.info(" total: {}",size);
log.info(" consuming: 【{} ms】",con);
}
log.info("-----------------------------------------------------------------------------------");
}
}

View File

@ -0,0 +1,63 @@
package com.pictc.jdbc;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
public class JdbcContextUtils {
private static JdbcTemplate jdbc;
private static DataSource source;
private static DataSource logSource;
@Autowired
public void setJdbc(JdbcTemplate jdbc) {
JdbcContextUtils.jdbc = jdbc;
}
@Autowired
public void setSource(DataSource source) {
JdbcContextUtils.source = source;
}
public void setLogSource(DataSource source) {
JdbcContextUtils.logSource = source;
}
public static JdbcTemplate getJdbc() {
return JdbcContextUtils.jdbc;
}
public static DataSource getSource() {
return source;
}
public static DataSource getLogSource() {
return logSource;
}
/**
* 将驼峰命名的字符串转为下划线
* */
public static String fieldToColumn(String str) {
StringBuilder result=new StringBuilder();
char[] chars=str.toCharArray();
for (int i = 0; i < chars.length; i++) {
if(Character.isUpperCase(chars[i])) {
if(i>0) {
result.append('_');
}
result.append(Character.toLowerCase(chars[i]));
continue;
}
result.append(chars[i]);
}
return result.toString();
}
}

View File

@ -0,0 +1,315 @@
package com.pictc.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pictc.jdbc.model.JdbcParam;
import com.pictc.jdbc.model.QueryParameter;
import com.pictc.utils.CollectionUtils;
public class JdbcTools {
/**
* 执行增删改sql
* */
public static int execute(String sql) {
return execute(sql, null);
}
/**
* 执行增删改sql
* */
public static int execute(String sql,List<JdbcParam> params){
JdbcContext context = null;
try {
context = new JdbcContext(true,false);
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) {
return executeBatch(sql,-1, batchParams);
}
/**
* 批量操作
* */
public static int executeBatch(String sql,int step,List<List<JdbcParam>> batchParams){
JdbcContext context = null;
try {
context = new JdbcContext(true,false);
context.init(sql);
context.setBatchParams(batchParams);
return context.executeBatch(step);
} 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,false);
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,false);
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();
}
}
/**
* 查询对象
* */
public static JSONObject queryObj(String sql,List<JdbcParam> params){
JdbcContext context = null;
try {
context = new JdbcContext(true,false);
context.init(sql);
context.setParams(params);
ResultSet set = context.executeQuery();
Map<String, String> names = ResultSetUtils.getMapColumns(set);
while (set.next()) {
JSONObject obj = new JSONObject();
for (String key : names.keySet()) {
obj.put(names.get(key),set.getObject(key));
}
return obj;
}
return null;
} catch (SQLException e) {
throw context.createException(e);
}finally {
context.end();
}
}
/**
* 查询集合
* */
public static JSONArray queryArray(String sql,List<JdbcParam> params){
JdbcContext context = null;
try {
context = new JdbcContext(true,false);
context.init(sql);
context.setParams(params);
ResultSet set = context.executeQuery();
Map<String, String> names = ResultSetUtils.getMapColumns(set);
JSONArray result = new JSONArray();
while (set.next()) {
JSONObject obj = new JSONObject();
for (String key : names.keySet()) {
obj.put(names.get(key),set.getObject(key));
}
result.add(obj);
}
return result;
} catch (SQLException e) {
throw context.createException(e);
} finally {
context.end();
}
}
/**
* 执行存储过程返回基础数据类型
* */
public static <T>T callPrimitive(String sql,Class<T> type,List<JdbcParam> params){
JdbcContext context = null;
try {
context = new JdbcContext(true);
context.initCall(sql);
context.setParams(params);
ResultSet set = context.executeQuery();
while (set.next()) {
return ResultSetUtils.getObject(set,1,type);
}
return null;
} catch (SQLException e) {
throw context.createException(e);
}finally {
context.end();
}
}
/**
* 执行存储过程返回基础数据类型
* */
public static <T>List<T> callListPrimitive(String sql,Class<T> type,List<JdbcParam> params){
JdbcContext context = null;
try {
context = new JdbcContext(true);
context.initCall(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();
}
}
/**
* 执行存储过程返回对象
* */
public static JSONObject callObj(String sql,List<JdbcParam> params){
JdbcContext context = null;
try {
context = new JdbcContext(true);
context.initCall(sql);
context.setParams(params);
ResultSet set = context.executeQuery();
Map<String, String> names = ResultSetUtils.getMapColumns(set);
while (set.next()) {
JSONObject obj = new JSONObject();
for (String key : names.keySet()) {
obj.put(names.get(key),set.getObject(key));
}
return obj;
}
return null;
} catch (SQLException e) {
throw context.createException(e);
}finally {
context.end();
}
}
/**
* 执行存储过程,返回集合
* */
public static JSONArray callArray(String sql,List<JdbcParam> params){
JdbcContext context = null;
try {
context = new JdbcContext(true);
context.initCall(sql);
context.setParams(params);
ResultSet set = context.executeQuery();
Map<String, String> names = ResultSetUtils.getMapColumns(set);
JSONArray result = new JSONArray();
while (set.next()) {
JSONObject obj = new JSONObject();
for (String key : names.keySet()) {
obj.put(names.get(key),set.getObject(key));
}
result.add(obj);
}
return result;
} catch (SQLException e) {
throw context.createException(e);
}finally {
context.end();
}
}
//IPage<DemoCustomer>
public static IPage<JSONObject> queryPage(String baseSql,QueryParameter param) {
SqlBuilder sql = new SqlBuilder();
sql.append(baseSql);
List<JdbcParam> params = QueryParameterUtils.toJdbcParams(sql, param.getAllCriterias());
SqlBuilder countSql = new SqlBuilder();
countSql.select().append(" count(*) ").from().leftBracket().append(sql).rightBracket().as().append("TMP_CT");
Long total = queryPrimitive(countSql.toString(),Long.class,params);
List<JdbcParam> pageParams = CollectionUtils.newArrayList();
for (JdbcParam item : params) {
pageParams.add(item);
}
int start = (param.getIndex()-1)*param.getSize();
pageParams.add(new JdbcParam().setVal(param.getSize()).setJdbc(Types.INTEGER).setJavaType(Integer.class));
pageParams.add(new JdbcParam().setVal(start).setJdbc(Types.INTEGER).setJavaType(Integer.class));
QueryParameterUtils.parseOrders(sql, param.getOrders());
SqlBuilder pageSql = new SqlBuilder();
pageSql.append(sql.toString());
pageSql.limitFull();
JSONArray list = queryArray(pageSql.toString(), pageParams);
List<JSONObject> records = CollectionUtils.newArrayList();
if(list!=null) {
for (int i = 0; i < list.size(); i++) {
records.add(list.getJSONObject(i));
}
}
Page<JSONObject> page = new Page<>(param.getIndex(),param.getSize(),total);
page.setRecords(records);
return page;
}
public static JSONArray query(String baseSql,QueryParameter param){
SqlBuilder sql = new SqlBuilder();
sql.append(baseSql);
List<JdbcParam> params = QueryParameterUtils.toJdbcParams(sql, param.getAllCriterias());
QueryParameterUtils.parseOrders(sql, param.getOrders());
return queryArray(sql.toString(), params);
}
public static JSONObject queryObj(String baseSql,QueryParameter param){
SqlBuilder sql = new SqlBuilder();
sql.append(baseSql);
List<JdbcParam> params = QueryParameterUtils.toJdbcParams(sql, param.getAllCriterias());
QueryParameterUtils.parseOrders(sql, param.getOrders());
return queryObj(sql.toString(), params);
}
}

View File

@ -0,0 +1,175 @@
package com.pictc.jdbc;
import java.util.ArrayList;
import java.util.List;
import com.pictc.jdbc.model.Criteria;
import com.pictc.jdbc.model.CriteriaGroup;
import com.pictc.jdbc.model.JdbcParam;
import com.pictc.jdbc.model.JdbcType;
import com.pictc.jdbc.model.Link;
import com.pictc.jdbc.model.QueryOrder;
import com.pictc.jdbc.model.Criteria.DataType;
import com.pictc.jdbc.model.QueryOrder.QueryOrderType;
import com.pictc.utils.StringUtils;
public class QueryParameterUtils {
private static final String TBL_ALIAS = "t";
public static List<JdbcParam> toJdbcParams(SqlBuilder sql,List<CriteriaGroup> groups) {
List<JdbcParam> params = new ArrayList<JdbcParam>();
boolean hasWhere = false;
if(groups!=null && !groups.isEmpty()) {
for (CriteriaGroup group : groups) {
List<Criteria> cris = group.getCriterias();
if(cris==null || cris.isEmpty()) {
continue;
}
if(!hasWhere) {
hasWhere = true;
sql.where();
}else {
if(group.getLink()==Link.AND) {
sql.and();
}else {
sql.or();
}
}
sql.leftBracket();
boolean c_flag = false;
for (Criteria criteria : cris) {
if(!c_flag) {
c_flag = true;
}else {
if(criteria.getLink()==Link.AND) {
sql.and();
}else {
sql.or();
}
}
if(criteria.isNot()) {
sql.not();
}
String col = convertHump(criteria.getField());
if(criteria.getDataType()==DataType.STRING) {
sql.append("IFNULL(");
sql.append(TBL_ALIAS).dot().appendSeparator(col);
sql.append(",'')");
}else {
sql.append(TBL_ALIAS).dot().appendSeparator(col);
}
JdbcType jdbc = criteria.getJdbc();
int valueType = 0;
switch (criteria.getType()) {
case NULL:
valueType = -1;
sql.isNull();
break;
case EQ:
sql.eq().placeholder();
break;
case LIKE:
sql.like().placeholder();
break;
case GT:
sql.gt().placeholder();
break;
case EQ_GT:
sql.gtEq().placeholder();
break;
case LT:
sql.lt().placeholder();
break;
case EQ_LT:
sql.ltEq().placeholder();
break;
case BETWEEN:
valueType = 1;
if(criteria.getVal()==null || criteria.getSecondVal()==null) {
throw new RuntimeException(StringUtils.format("filed:[{0}] --> 条件BETWEEN 值不能为空!", criteria.getField()));
}
sql.between().placeholder().and().placeholder();
params.add(new JdbcParam().setJdbc(jdbc.getJdbc()).setJavaType(jdbc.getJavaClass()).setVal(criteria.getVal()));
params.add(new JdbcParam().setJdbc(jdbc.getJdbc()).setJavaType(jdbc.getJavaClass()).setVal(criteria.getSecondVal()));
break;
case IN:
valueType = 2;
//criteria.getListVal()
if(criteria.getListVal()==null || criteria.getListVal().isEmpty()) {
throw new RuntimeException(StringUtils.format("filed:[{0}] --> 条件IN 值不能为空!", criteria.getField()));
}
sql.inStart();
boolean inFlag = false;
for (Object val : criteria.getListVal()) {
if(!inFlag) {
inFlag = true;
}else {
sql.comma();
}
sql.placeholder();
params.add(new JdbcParam().setJdbc(jdbc.getJdbc()).setJavaType(jdbc.getJavaClass()).setVal(val));
}
sql.inEnd();
break;
default:
break;
}
if(valueType==0) {
params.add(new JdbcParam().setJdbc(jdbc.getJdbc()).setJavaType(jdbc.getJavaClass()).setVal(criteria.getVal()));
}
}
sql.rightBracket();
}
}
return params;
}
public static void parseOrders(SqlBuilder builder,List<QueryOrder> orders) {
if(orders!=null) {
boolean flag = false;
for (QueryOrder order : orders) {
if(order.getType()==QueryOrderType.NONE) {
continue;
}
if(!flag) {
builder.orderBy();
flag = true;
}else {
builder.comma();
}
String col = convertHump(order.getField());
builder.space().append(TBL_ALIAS).dot().appendSeparator(col);
if(order.getType()==QueryOrderType.ASC) {
builder.asc();
}else {
builder.desc();
}
}
}
}
/**
* 将驼峰命名的字符串转为下划线
* */
public static String convertHump(String str) {
StringBuilder result=new StringBuilder();
char[] chars=str.toCharArray();
for (int i = 0; i < chars.length; i++) {
if(Character.isUpperCase(chars[i])) {
if(i>0) {
result.append('_');
}
result.append(Character.toLowerCase(chars[i]));
continue;
}
result.append(chars[i]);
}
return result.toString();
}
}

View File

@ -0,0 +1,359 @@
package com.pictc.jdbc;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.sql.Array;
import java.sql.Date;
import java.sql.NClob;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLXML;
import java.sql.Struct;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.format.DateTimeParseException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.pictc.utils.StringUtils;
public class ResultSetUtils {
private static Pattern linePattern = Pattern.compile("_(\\w)");
@SuppressWarnings("unchecked")
public static <T> T getObject(ResultSet res,int columnIndex,Class<T> type) throws SQLException {
if (type.equals(String.class)) {
return (T) res.getString(columnIndex);
} else if (type.equals(BigDecimal.class)) {
return (T) res.getBigDecimal(columnIndex);
} else if (type.equals(BigInteger.class)) {
return (T) getBigInteger(res, columnIndex);
} else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)) {
return (T) Boolean.valueOf(res.getBoolean(columnIndex));
} else if (type.equals(Integer.class) || type.equals(Integer.TYPE)) {
return (T) Integer.valueOf(res.getInt(columnIndex));
} else if (type.equals(Long.class) || type.equals(Long.TYPE)) {
return (T) Long.valueOf(res.getLong(columnIndex));
} else if (type.equals(Float.class) || type.equals(Float.TYPE)) {
return (T) Float.valueOf(res.getFloat(columnIndex));
} else if (type.equals(Double.class) || type.equals(Double.TYPE)) {
return (T) Double.valueOf(res.getDouble(columnIndex));
} else if (type.equals(byte[].class)) {
return (T) res.getBytes(columnIndex);
} else if (type.equals(Date.class)) {
return (T) res.getDate(columnIndex);
} else if (type.equals(Time.class)) {
return (T) res.getTime(columnIndex);
} else if (type.equals(Timestamp.class)) {
return (T) res.getTimestamp(columnIndex);
} else if (type.equals(java.sql.Clob.class)) {
return (T) res.getClob(columnIndex);
} else if (type.equals(java.sql.Blob.class)) {
return (T) res.getBlob(columnIndex);
} else if (type.equals(Array.class)) {
return (T) res.getArray(columnIndex);
} else if (type.equals(Ref.class)) {
return (T) res.getRef(columnIndex);
} else if (type.equals(URL.class)) {
return (T) res.getURL(columnIndex);
} else if (type.equals(Struct.class)) {
throw new SQLFeatureNotSupportedException();
} else if (type.equals(RowId.class)) {
return (T) res.getRowId(columnIndex);
} else if (type.equals(NClob.class)) {
return (T) res.getNClob(columnIndex);
} else if (type.equals(SQLXML.class)) {
return (T) res.getSQLXML(columnIndex);
} else if (type.equals(LocalDate.class)) {
return (T) getLocalDate(res,columnIndex);
} else if (type.equals(LocalDateTime.class)) {
return (T) getLocalDateTime(res,columnIndex);
} else if (type.equals(LocalTime.class)) {
return (T) getLocalTime(res,columnIndex);
} else if (type.equals(OffsetDateTime.class)) {
try {
String odt = res.getString(columnIndex);
return odt == null ? null : (T) OffsetDateTime.parse(odt);
} catch (DateTimeParseException e) {
// Let it continue and try by object deserialization.
}
} else if (type.equals(OffsetTime.class)) {
try {
String ot = res.getString(columnIndex);
return ot == null ? null : (T) OffsetTime.parse(ot);
} catch (DateTimeParseException e) {}
}else if(type.isEnum()) {
try {
String _vl = res.getString(columnIndex);
if(!StringUtils.isEmpty(_vl)) {
Method method=Enum.class.getMethod("valueOf", String.class);
return (T) method.invoke(null,_vl);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return (T) res.getObject(columnIndex);
}
private static LocalDate getLocalDate(ResultSet res,int columnIndex) throws SQLException {
Date date = res.getDate(columnIndex);
if(date!=null) {
return date.toLocalDate();
}
return null;
}
private static LocalDateTime getLocalDateTime(ResultSet res,int columnIndex) throws SQLException {
Timestamp date = res.getTimestamp(columnIndex);
if(date!=null) {
return date.toLocalDateTime();
}
return null;
}
private static LocalTime getLocalTime(ResultSet res,int columnIndex) throws SQLException {
Time date = res.getTime(columnIndex);
if(date!=null) {
return date.toLocalTime();
}
return null;
}
private static BigInteger getBigInteger(ResultSet res,int columnIndex) throws SQLException {
String stringVal = res.getString(columnIndex);
if (stringVal == null) {
return null;
}
try {
return new BigInteger(stringVal);
} catch (NumberFormatException nfe) {
throw new RuntimeException("ResultSet.Bad_format_for_BigInteger");
}
}
@SuppressWarnings("unchecked")
public static <T> T getObject(ResultSet res,String name,Class<T> type) throws SQLException {
if (type.equals(String.class)) {
return (T) res.getString(name);
} else if (type.equals(BigDecimal.class)) {
return (T) res.getBigDecimal(name);
} else if (type.equals(BigInteger.class)) {
return (T) getBigInteger(res, name);
} else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)) {
return (T) Boolean.valueOf(res.getBoolean(name));
} else if (type.equals(Integer.class) || type.equals(Integer.TYPE)) {
return (T) Integer.valueOf(res.getInt(name));
} else if (type.equals(Long.class) || type.equals(Long.TYPE)) {
return (T) Long.valueOf(res.getLong(name));
} else if (type.equals(Float.class) || type.equals(Float.TYPE)) {
return (T) Float.valueOf(res.getFloat(name));
} else if (type.equals(Double.class) || type.equals(Double.TYPE)) {
return (T) Double.valueOf(res.getDouble(name));
} else if (type.equals(byte[].class)) {
return (T) res.getBytes(name);
} else if (type.equals(Date.class)) {
return (T) res.getDate(name);
} else if (type.equals(Time.class)) {
return (T) res.getTime(name);
} else if (type.equals(java.util.Date.class) || type.equals(Timestamp.class)) {
return (T) res.getTimestamp(name);
} else if (type.equals(java.sql.Clob.class)) {
return (T) res.getClob(name);
} else if (type.equals(java.sql.Blob.class)) {
return (T) res.getBlob(name);
} else if (type.equals(Array.class)) {
return (T) res.getArray(name);
} else if (type.equals(Ref.class)) {
return (T) res.getRef(name);
} else if (type.equals(URL.class)) {
return (T) res.getURL(name);
} else if (type.equals(Struct.class)) {
throw new SQLFeatureNotSupportedException();
} else if (type.equals(RowId.class)) {
return (T) res.getRowId(name);
} else if (type.equals(NClob.class)) {
return (T) res.getNClob(name);
} else if (type.equals(SQLXML.class)) {
return (T) res.getSQLXML(name);
} else if (type.equals(LocalDate.class)) {
return (T) getLocalDate(res,name);
} else if (type.equals(LocalDateTime.class)) {
return (T) getLocalDateTime(res,name);
} else if (type.equals(LocalTime.class)) {
return (T) getLocalTime(res,name);
} else if (type.equals(OffsetDateTime.class)) {
try {
String odt = res.getString(name);
return odt == null ? null : (T) OffsetDateTime.parse(odt);
} catch (DateTimeParseException e) {
// Let it continue and try by object deserialization.
}
} else if (type.equals(OffsetTime.class)) {
try {
String ot = res.getString(name);
return ot == null ? null : (T) OffsetTime.parse(ot);
} catch (DateTimeParseException e) {}
}else if(type.isEnum()) {
try {
String _vl = res.getString(name);
if(!StringUtils.isEmpty(_vl)) {
Method method=Enum.class.getMethod("valueOf", String.class);
return (T) method.invoke(null,_vl);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return (T) res.getObject(name);
}
private static LocalDate getLocalDate(ResultSet res,String name) throws SQLException {
Date date = res.getDate(name);
if(date!=null) {
return date.toLocalDate();
}
return null;
}
private static LocalDateTime getLocalDateTime(ResultSet res,String name) throws SQLException {
Timestamp date = res.getTimestamp(name);
if(date!=null) {
return date.toLocalDateTime();
}
return null;
}
private static LocalTime getLocalTime(ResultSet res,String name) throws SQLException {
Time date = res.getTime(name);
if(date!=null) {
return date.toLocalTime();
}
return null;
}
private static BigInteger getBigInteger(ResultSet res,String name) throws SQLException {
String stringVal = res.getString(name);
if (stringVal == null) {
return null;
}
try {
return new BigInteger(stringVal);
} catch (NumberFormatException nfe) {
throw new RuntimeException("ResultSet.Bad_format_for_BigInteger");
}
}
public static <T>T getSingleValue(ResultSet res,Class<T> klass) throws SQLException{
if(res.next()) {
return getObject(res,1, klass);
}
return null;
}
/**
* 获取结果集的标题名称
* */
public static Map<String,String> getMapColumns(ResultSet set) throws SQLException{
ResultSetMetaData meta=set.getMetaData();
Map<String,String> result=new HashMap<>();
for (int i = 1; i <= meta.getColumnCount(); i++) {
result.put(meta.getColumnLabel(i), parseKey(meta.getColumnLabel(i)));
}
return result;
}
/**
* 获取结果集的标题名称
* */
public static Set<String> getResultColumns(ResultSet set) throws SQLException{
ResultSetMetaData meta=set.getMetaData();
Set<String> result=new HashSet<>(meta.getColumnCount());
for (int i = 1; i <= meta.getColumnCount(); i++) {
result.add(meta.getColumnLabel(i));
}
return result;
}
public static String parseKey(String str) {
str = str.toLowerCase();
Matcher matcher = linePattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
}
matcher.appendTail(sb);
return sb.toString();
}
}

View File

@ -0,0 +1,433 @@
package com.pictc.jdbc;
import org.springframework.util.Assert;
public class SqlBuilder {
public static final String MysqlSeparator="`";
public static final String KBaseSeparator="\"";
public static final String OracleSeparator="\"";
public static final String strSeparator="'";
public static final String space=" ";
public static final String dot=".";
public static final String comma=",";
public static final String enter="\n\t\t";
public static final String leftBracket="(";
public static final String rightBracket=")";
public static final String placeholder="?";
public static final String as=" AS ";
public static final String select="SELECT ";
public static final String distinct=" DISTINCT";
public static final String from=" FROM ";
public static final String leftJoin=" LEFT JOIN ";
public static final String rightJoin=" RIGHT JOIN ";
public static final String innerJoin=" INNER JOIN ";
public static final String on=" ON ";
public static final String where=" WHERE ";
public static final String AND =" AND ";
public static final String OR =" OR ";
public static final String not=" NOT ";
public static final String eq=" = ";
public static final String notEq=" <> ";
public static final String between=" BETWEEN ";
public static final String exists=" EXISTS ";
public static final String in=" IN(";
public static final String gt=" > ";
public static final String gtEq=" >= ";
public static final String lt=" < ";
public static final String ltEq=" <= ";
public static final String like=" LIKE ";
public static final String isNull=" IS NULL ";
public static final String isNotNull=" IS NOT NULL ";
public static final String groupBy=" GROUP BY";
public static final String having=" HAVING ";
public static final String orderBy=" ORDER BY ";
public static final String orderAsc=" ASC ";
public static final String orderDesc=" DESC ";
public static final String avg=" AVG";
public static final String min=" MIN";
public static final String max=" MAX";
public static final String count=" COUNT";
public static final String sum=" SUM";
public static final String insert="INSERT INTO ";
public static final String values=" VALUES";
public static final String update="UPDATE ";
public static final String set=" SET ";
public static final String delete="DELETE ";
public static final String limit=" LIMIT ";
public static final String offset=" OFFSET ";
private StringBuilder builder = new StringBuilder();
private String separator = KBaseSeparator;
public SqlBuilder() {
}
public SqlBuilder(String separator) {
this.separator = separator;
}
public static SqlBuilder mysql() {
return new SqlBuilder(MysqlSeparator);
}
public static SqlBuilder oracle() {
return new SqlBuilder(OracleSeparator);
}
public static SqlBuilder kbase() {
return new SqlBuilder(KBaseSeparator);
}
public String getSeparator() {
return separator;
}
public SqlBuilder space() {
builder.append(space);
return this;
}
public SqlBuilder dot() {
builder.append(dot);
return this;
}
public SqlBuilder comma() {
builder.append(comma);
return this;
}
public SqlBuilder enter() {
builder.append(enter);
return this;
}
public SqlBuilder leftBracket() {
builder.append(leftBracket);
return this;
}
public SqlBuilder rightBracket() {
builder.append(rightBracket);
return this;
}
public SqlBuilder leftJoin() {
builder.append(leftJoin);
return this;
}
public SqlBuilder rightJoin() {
builder.append(rightJoin);
return this;
}
public SqlBuilder innerJoin() {
builder.append(innerJoin);
return this;
}
public SqlBuilder on() {
builder.append(on);
return this;
}
public SqlBuilder append(Object obj) {
builder.append(obj);
return this;
}
public SqlBuilder appendSeparator(String... names) {
Assert.isTrue(!(names==null || names.length==0),"参数不能为空!");
boolean flag = false;
for (int i = 0; i < names.length; i++) {
if(names[i]!=null) {
if(!flag) {
flag = true;
}else {
dot();
}
builder.append(separator);
builder.append(names[i]);
builder.append(separator);
}
}
return this;
}
public SqlBuilder appendStrSeparator(String... names) {
Assert.isTrue(!(names==null || names.length==0),"参数不能为空!");
boolean flag = false;
for (int i = 0; i < names.length; i++) {
if(names[i]!=null) {
if(!flag) {
flag = true;
}else {
dot();
}
builder.append(strSeparator);
builder.append(names[i]);
builder.append(strSeparator);
}
}
return this;
}
public StringBuilder stringBuilder() {
return builder;
}
@Override
public String toString() {
return builder.toString();
}
public SqlBuilder where() {
builder.append(where);
return this;
}
public SqlBuilder and() {
builder.append(AND);
return this;
}
public SqlBuilder or() {
builder.append(OR);
return this;
}
public SqlBuilder not() {
builder.append(not);
return this;
}
public SqlBuilder eq() {
builder.append(eq);
return this;
}
public SqlBuilder notEq() {
builder.append(notEq);
return this;
}
public SqlBuilder between() {
builder.append(between);
return this;
}
public SqlBuilder exists() {
builder.append(exists);
return this;
}
public SqlBuilder inStart() {
builder.append(in);
return this;
}
public SqlBuilder inEnd() {
builder.append(rightBracket);
return this;
}
public SqlBuilder gt() {
builder.append(gt);
return this;
}
public SqlBuilder gtEq() {
builder.append(gtEq);
return this;
}
public SqlBuilder lt() {
builder.append(lt);
return this;
}
public SqlBuilder ltEq() {
builder.append(ltEq);
return this;
}
public SqlBuilder like() {
builder.append(like);
return this;
}
public SqlBuilder isNull() {
builder.append(isNull);
return this;
}
public SqlBuilder isNotNull() {
builder.append(isNotNull);
return this;
}
public SqlBuilder groupBy() {
builder.append(groupBy);
return this;
}
public SqlBuilder having() {
builder.append(having);
return this;
}
public SqlBuilder orderBy() {
builder.append(orderBy);
return this;
}
public SqlBuilder asc() {
builder.append(orderAsc);
return this;
}
public SqlBuilder desc() {
builder.append(orderDesc);
return this;
}
public SqlBuilder avg() {
builder.append(avg);
return this;
}
public SqlBuilder min() {
builder.append(min);
return this;
}
public SqlBuilder max() {
builder.append(max);
return this;
}
public SqlBuilder count() {
builder.append(count);
return this;
}
public SqlBuilder sum() {
builder.append(sum);
return this;
}
public SqlBuilder insertInto() {
builder.append(insert);
return this;
}
public SqlBuilder values() {
builder.append(values);
return this;
}
public SqlBuilder update() {
builder.append(update);
return this;
}
public SqlBuilder set() {
builder.append(set);
return this;
}
public SqlBuilder delete() {
builder.append(delete);
return this;
}
public SqlBuilder placeholder() {
builder.append(placeholder);
return this;
}
public SqlBuilder as() {
builder.append(as);
return this;
}
public SqlBuilder select() {
builder.append(select);
return this;
}
public SqlBuilder distinct() {
builder.append(distinct);
return this;
}
public SqlBuilder from() {
builder.append(from);
return this;
}
public SqlBuilder limit() {
builder.append(limit);
return this;
}
public SqlBuilder limitFull() {
builder.append(limit).append(placeholder).append(offset).append(placeholder);
return this;
}
}

View File

@ -0,0 +1,5 @@
package com.pictc.jdbc.model;
public class AliasManager {
}

View File

@ -0,0 +1,186 @@
package com.pictc.jdbc.model;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.apache.commons.compress.utils.Sets;
import com.pictc.utils.DateUtils;
import com.pictc.utils.StringUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
@ApiModel
@Data
@Accessors(chain = true)
public class Criteria implements Serializable{
private static final long serialVersionUID = 1L;
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final Set<Class<?>> DoubleClass = Sets.newHashSet(Double.class,double.class,float.class,Float.class,BigDecimal.class);
private static final Set<Class<?>> DateClass = Sets.newHashSet(Date.class,Timestamp.class,java.sql.Date.class,Time.class);
private static final Set<Class<?>> IntClass = Sets.newHashSet(int.class,Integer.class,byte.class,Byte.class,short.class,Short.class,long.class,Long.class,BigInteger.class);
public enum Type{
EQ("="),LIKE("LIKE"),GT(">"),EQ_GT(">="),LT("<"),EQ_LT("<="),
BETWEEN("BETWEEN"),IN("IN"),NULL("IS NULL");
private String sql;
private Type(String sql) {
this.sql = sql;
}
public String getSql() {
return sql;
}
}
public enum DataType{
DATE,INTEGER,DOUBLE,STRING
}
@ApiModelProperty(name = "条件连接条件默认为AND")
private Link link = Link.AND;
@ApiModelProperty(name = "条件是否取反")
private boolean not;
@ApiModelProperty(name = "属性名")
private String field;
@ApiModelProperty(name = "条件操作符默认为EQ")
private Type type = Type.EQ;
private DataType dataType = null; //数据类型
@ApiModelProperty(name = "条件值")
private Object val;
@ApiModelProperty(name = "条件第二值")
private Object secondVal;
@ApiModelProperty(name = "条件in的List值")
private List<Object> listVal;
private String sql;
public JdbcType getJdbc() {
switch (dataType) {
case DATE: return JdbcType.TIMESTAMP;
case INTEGER: return JdbcType.INTEGER;
case DOUBLE: return JdbcType.DECIMAL;
default: return JdbcType.VARCHAR;
}
}
public Object getVal() {
if(val!=null) {
return parseVal(val);
}
return null;
}
public Criteria setVal(Object val) {
this.val = val;
parseDataType(val);
return this;
}
public Object getSecondVal() {
if(secondVal!=null) {
return parseVal(secondVal);
}
return null;
}
public List<Object> getListVal() {
if(listVal!=null && !listVal.isEmpty()) {
List<Object> res = new ArrayList<Object>(listVal.size());
for (Object _lval : listVal) {
res.add(parseVal(_lval));
}
return res;
}
return null;
}
public Criteria setListVal(List<Object> listVal) {
this.listVal = listVal;
if(listVal!=null && !listVal.isEmpty()) {
Object object = listVal.get(0);
parseDataType(object);
}
return this;
}
private void parseDataType(Object _val) {
if(dataType==null) {
if(_val!=null) {
Class<?> clazz = _val.getClass();
if(DoubleClass.contains(clazz)) {
dataType = DataType.DOUBLE;
}else if(DateClass.contains(clazz)) {
dataType = DataType.DATE;
}else if(IntClass.contains(clazz)) {
dataType = DataType.INTEGER;
}else {
dataType = DataType.STRING;
}
}
}
}
private Object parseVal(Object _val) {
String _str = _val.toString();
if(StringUtils.isEmpty(_str)) return null;
if(dataType==DataType.DATE) {
if(_val instanceof Timestamp || _val instanceof Date) {
return _val;
}else if(_str.matches("^\\d+$")) {
return new Timestamp(Long.valueOf(_str));
}
return Timestamp.from(DateUtils.stringToDate(_str,DATE_FORMAT).toInstant());
}else if(dataType==DataType.DOUBLE) {
if(_val instanceof BigDecimal) {
return _val;
}
return new BigDecimal(_str);
}else if(dataType==DataType.INTEGER) {
if(_val instanceof Integer) {
return _val;
}
return Integer.valueOf(_str);
}
return _str;
}
public boolean isBetween() {
return type==Type.BETWEEN;
}
public boolean isNull() {
return type==Type.NULL;
}
public boolean isListValue() {
return type==Type.IN;
}
public boolean hasSql() {
return !StringUtils.isEmpty(sql);
}
}

View File

@ -0,0 +1,143 @@
package com.pictc.jdbc.model;
import java.io.Serializable;
import java.util.List;
import com.pictc.jdbc.model.Criteria.Type;
import com.pictc.utils.CollectionUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
@ApiModel
@Accessors(chain = true)
@Data
public class CriteriaGroup implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@ApiModelProperty(name = "条件组")
private List<Criteria> criterias = CollectionUtils.newArrayList();
@ApiModelProperty(name = "条件组之间的连接方式默认为AND")
private Link link = Link.AND;
public boolean hasCriteria() {
return criterias!=null && !criterias.isEmpty();
}
public CriteriaGroup andSql(String sql,Object val) {
return sql(Link.AND, sql, val);
}
public CriteriaGroup orSql(String sql,Object val) {
return sql(Link.OR, sql, val);
}
public CriteriaGroup sql(Link link,String sql,Object val) {
criterias.add(new Criteria().setLink(link).setType(Type.EQ).setSql(sql).setVal(val));
return this;
}
public CriteriaGroup add(Criteria criteria) {
criterias.add(criteria);
return this;
}
public CriteriaGroup andEq(String field,Object val) {
return eq(Link.AND, field, val);
}
public CriteriaGroup orEq(String field,Object val) {
return eq(Link.OR, field, val);
}
public CriteriaGroup eq(Link link,String field,Object val) {
criterias.add(new Criteria().setLink(link).setType(Type.EQ).setField(field).setVal(val));
return this;
}
public CriteriaGroup andLike(String field,Object val) {
return like(Link.AND, field, val);
}
public CriteriaGroup orLike(String field,Object val) {
return like(Link.OR, field, val);
}
public CriteriaGroup like(Link link,String field,Object val) {
criterias.add(new Criteria().setLink(link).setType(Type.LIKE).setField(field).setVal(val));
return this;
}
public CriteriaGroup andGt(String field,Object val) {
return gt(Link.AND, field, val);
}
public CriteriaGroup orGt(String field,Object val) {
return gt(Link.OR, field, val);
}
public CriteriaGroup gt(Link link,String field,Object val) {
criterias.add(new Criteria().setLink(link).setType(Type.GT).setField(field).setVal(val));
return this;
}
public CriteriaGroup andEqLt(String field,Object val) {
return eqLt(Link.AND, field, val);
}
public CriteriaGroup orEqLt(String field,Object val) {
return eqLt(Link.OR, field, val);
}
public CriteriaGroup eqLt(Link link,String field,Object val) {
criterias.add(new Criteria().setLink(link).setType(Type.EQ_LT).setField(field).setVal(val));
return this;
}
public CriteriaGroup andEqGt(String field,Object val) {
return eqGt(Link.AND, field, val);
}
public CriteriaGroup orEqGt(String field,Object val) {
return eqGt(Link.OR, field, val);
}
public CriteriaGroup eqGt(Link link,String field,Object val) {
criterias.add(new Criteria().setLink(link).setType(Type.EQ_GT).setField(field).setVal(val));
return this;
}
public CriteriaGroup andBetween(String field,Object val,Object secondVal) {
return between(Link.AND, field, val, secondVal);
}
public CriteriaGroup orBetween(String field,Object val,Object secondVal) {
return between(Link.OR, field, val, secondVal);
}
public CriteriaGroup between(Link link,String field,Object val,Object secondVal) {
criterias.add(new Criteria().setLink(link).setType(Type.BETWEEN).setField(field).setVal(val).setSecondVal(secondVal));
return this;
}
public CriteriaGroup andIn(String field,List<Object> listVal) {
return in(Link.AND, field, listVal);
}
public CriteriaGroup orIn(String field,List<Object> listVal) {
return in(Link.OR, field, listVal);
}
public CriteriaGroup in(Link link,String field,List<Object> listVal) {
criterias.add(new Criteria().setLink(link).setType(Type.IN).setField(field).setListVal(listVal));
return this;
}
}

View File

@ -0,0 +1,20 @@
package com.pictc.jdbc.model;
import lombok.Data;
/**
* @Description TODO(这里用一句话描述这个类的作用)
* @author zhangfucai
* @Date 2023年7月17日 上午9:33:16
* @version 1.0.0
*/
@Data
public class ExportColumn {
private String field;
private String title;
private int width;
}

View File

@ -0,0 +1,30 @@
package com.pictc.jdbc.model;
import java.io.Serializable;
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
/**
* @Description TODO(这里用一句话描述这个类的作用)
* @author zhangfucai
* @Date 2023年7月17日 上午9:32:42
* @version 1.0.0
*/
@Data
public class ExportParam implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private List<ExportColumn> columns;
private JSONObject filters;
private String sqlId;
private CriteriaGroup criterias;
}

View File

@ -0,0 +1,165 @@
package com.pictc.jdbc.model;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class JdbcParam implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int jdbc;
private Object val;
private boolean out;
private Class<?> javaType;
@Override
public String toString() {
return val+"("+JdbcType.valueOf(jdbc).name()+")";
}
public static JdbcParam ofOut(int jdbc,Class<?> javaType) {
return new JdbcParam().setJdbc(jdbc).setJavaType(javaType).setOut(true);
}
public static JdbcParam of(int jdbc,Class<?> javaType,Object val) {
return new JdbcParam().setJdbc(jdbc).setJavaType(javaType).setVal(val);
}
public static JdbcParam ofString(String val) {
return new JdbcParam().setJdbc(Types.VARCHAR).setJavaType(String.class).setVal(val);
}
// 整数类型
public static JdbcParam ofInt(Integer val) {
return new JdbcParam()
.setJdbc(Types.INTEGER)
.setJavaType(Integer.class)
.setVal(val);
}
// 长整数类型
public static JdbcParam ofLong(Long val) {
return new JdbcParam()
.setJdbc(Types.BIGINT)
.setJavaType(Long.class)
.setVal(val);
}
// 布尔类型
public static JdbcParam ofBoolean(Boolean val) {
return new JdbcParam()
.setJdbc(Types.BOOLEAN)
.setJavaType(Boolean.class)
.setVal(val);
}
// 浮点类型
public static JdbcParam ofFloat(Float val) {
return new JdbcParam()
.setJdbc(Types.FLOAT)
.setJavaType(Float.class)
.setVal(val);
}
// 双精度浮点类型
public static JdbcParam ofDouble(Double val) {
return new JdbcParam()
.setJdbc(Types.DOUBLE)
.setJavaType(Double.class)
.setVal(val);
}
// 字节类型
public static JdbcParam ofByte(Byte val) {
return new JdbcParam()
.setJdbc(Types.TINYINT)
.setJavaType(Byte.class)
.setVal(val);
}
// 短整数类型
public static JdbcParam ofShort(Short val) {
return new JdbcParam()
.setJdbc(Types.SMALLINT)
.setJavaType(Short.class)
.setVal(val);
}
// 日期类型
public static JdbcParam ofDate(Date val) {
return new JdbcParam()
.setJdbc(Types.DATE)
.setJavaType(Date.class)
.setVal(val);
}
// 时间戳类型
public static JdbcParam ofTimestamp(Timestamp val) {
return new JdbcParam()
.setJdbc(Types.TIMESTAMP)
.setJavaType(java.sql.Timestamp.class)
.setVal(val);
}
// 高精度小数类型
public static JdbcParam ofBigDecimal(BigDecimal val) {
return new JdbcParam()
.setJdbc(Types.DECIMAL)
.setJavaType(BigDecimal.class)
.setVal(val);
}
// 大整数类型
public static JdbcParam ofBigInteger(BigInteger val) {
return new JdbcParam()
.setJdbc(Types.NUMERIC)
.setJavaType(BigInteger.class)
.setVal(val);
}
// Java 8 本地日期类型 (仅日期)
public static JdbcParam ofLocalDate(LocalDate val) {
return new JdbcParam()
.setJdbc(Types.DATE)
.setJavaType(LocalDate.class)
.setVal(val);
}
// Java 8 本地时间类型 (仅时间)
public static JdbcParam ofLocalTime(LocalTime val) {
return new JdbcParam()
.setJdbc(Types.TIME)
.setJavaType(LocalTime.class)
.setVal(val);
}
// Java 8 本地日期时间类型 (日期+时间)
public static JdbcParam ofLocalDateTime(LocalDateTime val) {
return new JdbcParam()
.setJdbc(Types.TIMESTAMP)
.setJavaType(LocalDateTime.class)
.setVal(val);
}
}

View File

@ -0,0 +1,72 @@
package com.pictc.jdbc.model;
import java.sql.Types;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
public enum JdbcType {
CHAR(Types.CHAR,"CHAR",String.class,false,1,null),VARCHAR(Types.VARCHAR,"VARCHAR",String.class,false,255,null),
INTEGER(Types.INTEGER,"INTEGER",Integer.class,true,7,null),BIGINT(Types.BIGINT,"BIGINT",Long.class,true,12,null),
DECIMAL(Types.DECIMAL,"DECIMAL",java.math.BigDecimal.class,true,60,30),
FLOAT(Types.FLOAT,"FLOAT",float.class,true,10,5),DOUBLE(Types.DOUBLE,"DOUBLE",double.class,true,30,10),
DATE(Types.DATE,"DATE",java.sql.Date.class,false,null,null),TIMESTAMP(Types.TIMESTAMP,"DATETIME",java.sql.Timestamp.class,false,null,null),
CLOB(Types.CLOB,"CLOB",java.sql.Clob.class,false,null,null),
JSONOBJ(Types.LONGVARCHAR,"JSON",com.alibaba.fastjson.JSONObject.class,false,null,null),
JSONLIST(Types.LONGVARCHAR,"JSON",com.alibaba.fastjson.JSONArray.class,false,null,null);
private Integer jdbc;
private Class<?> javaClass;
private boolean isDecimal;
private String nativeName;
private Integer leng;
private Integer digits;
private JdbcType(int jdbcType,String nativeName,Class<?> javaClass, boolean isDecimal,Integer leng,Integer digits) {
this.jdbc = jdbcType;
this.javaClass = javaClass;
this.isDecimal = isDecimal;
this.nativeName = nativeName;
this.leng = leng;
this.digits = digits;
}
public boolean isDate() {
return this == DATE || this==TIMESTAMP;
}
public static JdbcType valueOf(int jdbc) {
JdbcType[] values = JdbcType.values();
for (int i = 0; i < values.length; i++) {
JdbcType item = values[i];
if(item.getJdbc()==jdbc) {
return item;
}
}
return JdbcType.VARCHAR;
}
public static JdbcType valueOf(Class<?> java) {
JdbcType[] values = JdbcType.values();
for (int i = 0; i < values.length; i++) {
JdbcType item = values[i];
if(item.getJavaClass().equals(java)) {
return item;
}
}
return JdbcType.VARCHAR;
}
}

View File

@ -0,0 +1,7 @@
package com.pictc.jdbc.model;
public enum Link {
AND,OR
}

View File

@ -0,0 +1,80 @@
package com.pictc.jdbc.model;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
import com.pictc.jdbc.model.Criteria.DataType;
import com.pictc.utils.DateUtils;
import com.pictc.utils.StringUtils;
import lombok.Data;
/**
* @Description TODO(这里用一句话描述这个类的作用)
* @author zhangfucai
* @Date 2022年12月13日 上午11:44:58
* @version 1.0.0
*/
@Data
public class ParamItem implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private DataType dataType; //数据类型
private Object val;
public JdbcParam toParam() {
JdbcType jdbc = getJdbc();
return new JdbcParam().setJavaType(jdbc.getJavaClass()).setJdbc(jdbc.getJdbc()).setVal(parseVal(val));
}
public JdbcType getJdbc() {
switch (dataType) {
case DATE: return JdbcType.TIMESTAMP;
case INTEGER: return JdbcType.INTEGER;
case DOUBLE: return JdbcType.DECIMAL;
default: return JdbcType.VARCHAR;
}
}
public Class<?> getJavaType(){
switch (dataType) {
case DATE: return Timestamp.class;
case INTEGER: return Integer.class;
case DOUBLE: return Double.class;
default: return String.class;
}
}
private Object parseVal(Object _val) {
String _str = _val.toString();
if(StringUtils.isEmpty(_str)) return null;
if(dataType==DataType.DATE) {
if(_val instanceof Timestamp || _val instanceof Date) {
return _val;
}else if(_str.matches("^\\d+$")) {
return new Timestamp(Long.valueOf(_str));
}
return Timestamp.from(DateUtils.stringToDate(_str,DATE_FORMAT).toInstant());
}else if(dataType==DataType.DOUBLE) {
if(_val instanceof BigDecimal) {
return _val;
}
return new BigDecimal(_str);
}else if(dataType==DataType.INTEGER) {
if(_val instanceof Integer) {
return _val;
}
return Integer.valueOf(_str);
}
return _str;
}
}

View File

@ -0,0 +1,30 @@
package com.pictc.jdbc.model;
import java.io.Serializable;
import java.util.List;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @Description TODO(这里用一句话描述这个类的作用)
* @author zhangfucai
* @Date 2022年12月13日 上午11:42:00
* @version 1.0.0
*/
@ApiModel
@Accessors(chain = true)
@Data
public class ParamQueryBo implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String queryId;
private List<ParamItem> params;
}

View File

@ -0,0 +1,30 @@
package com.pictc.jdbc.model;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
@ApiModel
@Accessors(chain = true)
@Data
public class QueryOrder implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@ApiModelProperty(name = "属性")
private String field;
@ApiModelProperty(name = "排序方式ASC,DESC,NONE,默认 ASC")
private QueryOrderType type = QueryOrderType.ASC;
public enum QueryOrderType{
ASC,DESC,NONE
}
}

View File

@ -0,0 +1,88 @@
package com.pictc.jdbc.model;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.pictc.jdbc.model.Criteria.DataType;
import com.pictc.jdbc.model.Criteria.Type;
import com.pictc.utils.CollectionUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
@ApiModel
@Accessors(chain = true)
@Data
public class QueryParameter implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String queryId;
private Class<?> entityClass; //实体类型
@ApiModelProperty(name = "实体对象会已eq方式转为查询条件")
private JSONObject data;
@ApiModelProperty(name = "where条件")
private List<CriteriaGroup> criterias;
@ApiModelProperty(name = "排序配置")
private List<QueryOrder> orders;
@ApiModelProperty(name = "查询指定列")
private Set<String> froms;
private int index;
private int size;
private boolean page;
@ApiModelProperty(hidden = true)
public List<CriteriaGroup> getAllCriterias(){
List<CriteriaGroup> res = null;
if(criterias!=null) {
res = CollectionUtils.newArrayList();
for (CriteriaGroup group : criterias) {
res.add(group);
}
}
if(data!=null && !data.isEmpty()) {
if(res==null) {
res = CollectionUtils.newArrayList();
}
res.add(objToCriteria(data));
}
return res;
}
private CriteriaGroup objToCriteria(JSONObject pojo) {
CriteriaGroup group = new CriteriaGroup();
for (String key : pojo.keySet()) {
Object val = pojo.get(key);
if(val==null || val instanceof JSONObject || val instanceof JSONArray) {
continue;
}else {
JdbcType type = JdbcType.valueOf(val.getClass());
DataType dtype = DataType.STRING;
if(type.isDecimal()) {
dtype = DataType.DOUBLE;
}else if(type.isDate()) {
dtype = DataType.DATE;
}
group.add(new Criteria().setType(Type.EQ).setVal(val).setDataType(dtype).setField(key));
}
}
return group;
}
}

View File

@ -0,0 +1,42 @@
package com.pictc.jdbc.model;
import java.util.List;
import java.util.Set;
import org.apache.ibatis.mapping.ResultFlag;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.type.TypeHandler;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class TResultCol {
private String property;
private String column;
private String alias;
private Class<?> javaType;
private JdbcType jdbcType;
private TypeHandler<?> typeHandler;
private String nestedResultMapId;
private String nestedQueryId;
private Set<String> notNullColumns;
private String columnPrefix;
private List<ResultFlag> flags;
private List<ResultMapping> composites;
}

View File

@ -0,0 +1,30 @@
package com.pictc.jdbc.model;
import java.util.List;
import com.pictc.datalog.LogTableInfo;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class TResultMap {
private String id;
private Class<?> type;
private LogTableInfo tabInfo;
private String alias;
private List<TResultCol> propertys;
private TResultCol idProperty;
private List<TResultMap> ones;
private List<TResultMap> manys;
}

View File

@ -0,0 +1,70 @@
package com.pictc.orm;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@SuppressWarnings("serial")
public abstract class BaseMasterEntity implements Serializable {
/**
*
*/
@ApiModelProperty("")
@TableId
private Long id;
/**
* 创建人ID
*/
@ApiModelProperty("")
@TableField(fill = FieldFill.INSERT)
private Long createUserId;
/**
* 创建时间
*/
@ApiModelProperty("")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createDate;
/**
* 修改人ID
*/
@ApiModelProperty("")
@TableField(fill = FieldFill.UPDATE)
private Long modifyUserId;
/**
* 修改时间
*/
@ApiModelProperty("")
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime modifyDate;
/**
* 逻辑删除标识
*/
@ApiModelProperty("")
@TableField(fill = FieldFill.INSERT)
@TableLogic
private Integer deleteMark;
/**
* 启用/作废标识
*/
@ApiModelProperty("")
@TableField(fill = FieldFill.INSERT)
private Integer enabledMark;
/**
* 租户ID
*/
@ApiModelProperty("")
private Long tenantId;
}

View File

@ -0,0 +1,81 @@
package com.pictc.utils;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ArrayUtils {
@SuppressWarnings("unchecked")
public static <T> T[] of(T... parameters) {
return parameters;
}
@SuppressWarnings("unchecked")
public static <T>T[] valueOf(List<T> list){
if(list!=null) {
T[] result = null;
for (int i = 0; i < list.size(); i++) {
T item = list.get(i);
if(result==null) {
result = (T[]) Array.newInstance(item.getClass(),list.size());
}
result[i] = item;
}
return result;
}
return null;
}
@SuppressWarnings("unchecked")
public static <T> T[] ofCollection(Collection<T> objs){
T[] result=null;
if(objs!=null) {
Iterator<T> it=objs.iterator();
int i=0;
while (it.hasNext()) {
T item =it.next();
if(result==null) {
result = (T[]) Array.newInstance(item.getClass(),objs.size());
}
result[i] = item;
i++;
}
}
return result;
}
public static <T> String join(T[] array){
return join(array,",",null);
}
public static <T> String join(T[] array,String split){
return join(array, split, null);
}
public static <T> String join(T[] array,String split,String suffix){
if(array==null || array.length==0){
return null;
}
StringBuilder str=new StringBuilder();
for (int i = 0; i < array.length; i++) {
if(i>0) {
str.append(split);
}
if(suffix!=null) str.append(suffix);
str.append(array[i].toString());
if(suffix!=null) str.append(suffix);
}
return str.toString();
}
}

View File

@ -0,0 +1,447 @@
package com.pictc.utils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.pictc.exceptions.TFieldException;
import com.pictc.exceptions.TMethodException;
/**
* @author 张福财
* @date 2023年8月11日
* @Description: java对象反射工具类
*/
@SuppressWarnings({"unchecked"})
public class BeanUtils {
private BeanUtils() {
super();
}
/**
* @Description: 获取java类的属性map集合
* @param @param cls
* @param @return 参数
* @return Map<String,Field> 返回类型
* @throws
*/
public static Map<String, Field> getMapFields(Class<?> cls) {
Map<String, Field> fields = CollectionUtils.newHashMap();
if (cls != null) {
List<Field> fieldList = new ArrayList<Field>();
Set<String> names = new HashSet<String>();
getFields(cls, fieldList,names);
for (Field field : fieldList) {
if (hasGetSet(field, cls)) {
fields.put(field.getName(), field);
}
}
}
return fields;
}
/**
* @Description: 获取对象非空值的Map集合
* @param @param obj
* @param @return 参数
* @return Map<String,Object> 返回类型
* @throws
*/
public static Map<String,Object> getBeanNotNullValue(Object obj){
Map<String,Object> rel=CollectionUtils.newHashMap();
if(obj==null) {
return rel;
}
Field[] fields= getFields(obj.getClass());
for (int i = 0; i < fields.length; i++) {
Object val=getFieldValue(fields[i], obj);
if(val!=null) {
rel.put(fields[i].getName(),val);
}
}
return rel;
}
/**
* @Description: 获取Class 包含指定注解类型的属性
* @param @param cls
* @param @param annotation
* @param @return 参数
* @return List<Field> 返回类型
* @throws
*/
public static List<Field> getFields(Class<?> cls, Class<? extends Annotation> annotation) {
List<Field> result = CollectionUtils.newArrayList();
Field[] fields = getFields(cls);
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (field.isAnnotationPresent(annotation)) {
result.add(field);
}
}
return result;
}
/**
* @Description: 获取Class 属性数组
* @param @param cls
* @param @return 参数
* @return Field[] 返回类型
* @throws
*/
public static Field[] getFields(Class<?> cls) {
List<Field> fields = new ArrayList<Field>();
Set<String> names = new HashSet<String>();
getFields(cls, fields,names);
Field[] result = new Field[fields.size()];
fields.toArray(result);
return result;
}
private static void getFields(Class<?> cls, List<Field> fields,Set<String> names) {
if (!cls.equals(Object.class)) {
Field[] _fields = cls.getDeclaredFields();
for (int i = 0; i < _fields.length; i++) {
Field field = _fields[i];
if(names.contains(field.getName())) {
continue;
}
fields.add(field);
names.add(field.getName());
}
getFields(cls.getSuperclass(), fields,names);
}
}
/**
* @Description: 判断class是否有指定属性名的getter、setter方法
* @param fieldName
* @param cls
* @return boolean 返回类型
*/
public static boolean hasGetSet(String fieldName, Class<?> cls) {
try {
return hasGetSet(cls.getDeclaredField(fieldName), cls);
} catch (Exception e) {
throw new RuntimeException("Class【"+cls+"】-属性【"+fieldName+"】获取getter、setter方法异常",e);
}
}
public static boolean hasGetSet(Field field, Class<?> cls) {
Class<?> type = field.getType();
String name = field.getName();
String getName = null;
String uname = getMethodName(name);
if (type.equals(boolean.class) || type.equals(Boolean.class)) {
if (name.startsWith("is")) {
getName = name;
} else {
getName = "is" + uname;
}
} else {
getName = "get" + uname;
}
String setName = "set" + uname;
Class<?> beanType = cls;
do {
if (findGetSet(beanType, getName, setName, type)) {
return true;
}
beanType = beanType.getSuperclass();
} while (!Object.class.equals(beanType));
return false;
}
private static boolean findGetSet(Class<?> beanType, String getName, String setName, Class<?> type) {
Method getMethod = null;
Method setMethod = null;
try {
getMethod = beanType.getDeclaredMethod(getName);
setMethod = beanType.getDeclaredMethod(setName, type);
} catch (Exception e) {
}
return getMethod != null && setMethod != null;
}
private static String getMethodName(String name) {
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
public static void setFieldValue(Field field, Object value, Object bean) {
try {
if(field==null) {
throw new TFieldException("setFieldValue时field不能为空");
}
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(bean, value);
} catch (Exception e) {
throw new TFieldException("setFieldValue异常", e);
}
}
public static void setFieldValue(String fieldName, Object value, Object bean) {
setFieldValue(getField(fieldName, bean), value, bean);
}
public static <T> T getFieldValue(String fieldName, Object bean) {
return getFieldValue(getField(fieldName, bean), bean);
}
public static <T> T getFieldValue(Field field, Object bean) {
Object value = null;
if(field==null) {
throw new TFieldException("获取属性值时field不能为空");
}
if (!field.isAccessible()) {
field.setAccessible(true);
}
try {
value = field.get(bean);
} catch (Exception e) {
throw new TFieldException("getFieldValue异常", e);
}
return value==null?null:(T)value;
}
public static Field getField(String fieldName, Object bean) {
return getField(fieldName, bean.getClass());
}
public static Field getField(String fieldName, Class<?> cls) {
try {
return cls.getDeclaredField(fieldName);
} catch (Exception e) {
throw new TFieldException("获取属性异常", e);
}
}
public static <T> T newInstance(Class<?> cls) {
return newInstance(cls,false);
}
public static <T> T newInstance(ClassLoader loader,Class<?> cls) {
return newInstance(loader,cls,false);
}
public static <T> T newInstance(Class<?> cls,boolean ignoreError) {
return newInstance(null,cls,ignoreError);
}
public static <T> T newInstance(ClassLoader loader,Class<?> cls,boolean ignoreError) {
try {
return (T) ClassUtils.loadClass(loader,cls.getName()).getDeclaredConstructor().newInstance();
} catch (Exception e) {
if(!ignoreError) {
throw new RuntimeException("实例化Class【"+cls.getName()+"】异常",e);
}
}
return null;
}
public static <T> T newInstance(String className) {
return newInstance(className, false);
}
public static <T> T newInstance(String className,boolean ignoreError) {
try {
return (T) ClassUtils.loadClass(className).getDeclaredConstructor().newInstance();
} catch (Exception e) {
if(!ignoreError) {
throw new RuntimeException("实例化Class【"+className+"】异常",e);
}
}
return null;
}
public static <T>T deepCopy(Object source){
if(source!=null) {
Map<String,Object> cache = CollectionUtils.newHashMap();
try {
return (T) deepCopy(source.getClass(),source,cache);
} finally {
cache.clear();
cache = null;
}
}
return null;
}
public static <T>T deepCopy(Type javaType,Object source){
if(source!=null) {
Map<String,Object> cache = CollectionUtils.newHashMap();
try {
return (T) deepCopy(javaType,source,cache);
} finally {
cache.clear();
cache = null;
}
}
return null;
}
private static Object deepCopy(Type javaType,Object source,Map<String,Object> cache){
if(source==null) {
return null;
}
String addr = Integer.toHexString(source.hashCode());
if(cache.containsKey(addr)) {
return cache.get(addr);
}
TypeInfo type = new TypeInfo(javaType);
Object target = null;
if(type.isPrimitive() || type.isEnum()) {
target = source;
}else if(type.isArray()) {
int length = Array.getLength(source);
List<Object> list = new ArrayList<Object>(length);
for (int j = 0; j < length; j += 1) {
Object obj = Array.get(source, j);
list.add(deepCopy(type.getArrayType(),obj));
}
target = list.toArray();
}else if(type.isCollection()) {
Collection<Object> cvals = (Collection<Object>) source;
Collection<Object> nvals = type.newCollection();
for (Object obj : cvals) {
nvals.add(deepCopy(type.getCollectionType(),obj));
}
target = nvals;
}else if(type.isMap()) {
Map<Object, Object> mapVal = type.newMap();
Map<?, ?> valMap = (Map<?, ?>) source;
for (final Entry<?, ?> e : valMap.entrySet()) {
final Object value = e.getValue();
if (value != null) {
mapVal.put(e.getKey(),deepCopy(value));
}
}
target = mapVal;
}else {
Class<?> klass = type.getKlass();
target = newInstance(klass);
cache.put(addr,target);
Field[] fields = getFields(klass);
Class<?> sklazz = source.getClass();
Map<String, Field> mapFields = getMapFields(sklazz);
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
Field sf = mapFields.get(field.getName());
if(sf==null || !sf.getType().equals(field.getType())) {
continue;
}
Object val = getFieldValue(sf, source);
if(val!=null) {
setFieldValue(field,deepCopy(field.getGenericType(),val, cache),target);
}
}
}
return target;
}
/**
* 调用方法
* */
public static <T>T callMethod(Method method, Object obj, Object... values) throws InstantiationException,
IllegalAccessException, NumberFormatException, IllegalArgumentException,
InvocationTargetException {
return (T) method.invoke(obj, values);
}
/**
* 判断类是否含义该属性
*
* @param klass
* @param field
* @return
*/
public static boolean hasField(Class<?> klass, String field) {
Class<?> btype = klass;
while (!Object.class.equals(btype)) {
try {
btype.getDeclaredField(field);
return true;
} catch (Exception e) {
}
btype = btype.getSuperclass();
}
return false;
}
public static Method getMethod(Class<?> cls, String name, Class<?>... agrs) {
Method method = null;
try {
if (agrs == null || agrs.length == 0) {
method = cls.getDeclaredMethod(name);
} else {
method = cls.getDeclaredMethod(name, agrs);
}
} catch (NoSuchMethodException | SecurityException e) {
throw new TMethodException(e);
}
return method;
}
public static Method getHasMethod(Class<?> cls, String name, Class<?>... agrs) {
Method method = null;
try {
if (agrs == null || agrs.length == 0) {
method = cls.getDeclaredMethod(name);
} else {
method = cls.getDeclaredMethod(name, agrs);
}
} catch (Exception e) {}
return method;
}
public static <T>T copyBean(Object source,T target){
if(source!=null) {
Field[] ffields = getFields(target.getClass());
Map<String,Field> tarNames = CollectionUtils.newHashMap();
for (int i = 0; i < ffields.length; i++) {
tarNames.put(ffields[i].getName(),ffields[i]);
}
Field[] fields = getFields(source.getClass());
for (Field field : fields) {
if(tarNames.containsKey(field.getName())) {
setFieldValue(tarNames.get(field.getName()),getFieldValue(field,source),target);
}
}
}
return target;
}
}

View File

@ -0,0 +1,342 @@
package com.pictc.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ClassUtils {
private static Set<Class<?>> primitives=CollectionUtils.newHashSet();
private static Set<Class<?>> numbers=CollectionUtils.newHashSet();
private static Set<Class<?>> integers=CollectionUtils.newHashSet();
private static Set<Class<?>> doubles=CollectionUtils.newHashSet();
private static Set<Class<?>> dates=CollectionUtils.newHashSet();
private static Set<Class<?>> strings=CollectionUtils.newHashSet();
static {
primitives.add(BigDecimal.class);primitives.add(BigInteger.class);
primitives.add(Integer.class);primitives.add(int.class);
primitives.add(Double.class);primitives.add(double.class);
primitives.add(Float.class);primitives.add(float.class);
primitives.add(Long.class);primitives.add(long.class);
primitives.add(Short.class);primitives.add(short.class);
primitives.add(Byte.class);primitives.add(byte.class);
primitives.add(Boolean.class);primitives.add(boolean.class);
primitives.add(Character.class);primitives.add(char.class);
primitives.add(String.class);primitives.add(Date.class);
primitives.add(Timestamp.class);primitives.add(java.util.Date.class);
primitives.add(Time.class);
integers.add(Integer.class);integers.add(int.class);
integers.add(Long.class);integers.add(long.class);
integers.add(Short.class);integers.add(short.class);
integers.add(Byte.class);integers.add(byte.class);
integers.add(BigInteger.class);
doubles.add(Double.class);doubles.add(double.class);
doubles.add(Float.class);doubles.add(float.class);
doubles.add(BigDecimal.class);
numbers.add(Integer.class);numbers.add(int.class);
numbers.add(Double.class);numbers.add(double.class);
numbers.add(Float.class);numbers.add(float.class);
numbers.add(Long.class);numbers.add(long.class);
numbers.add(Short.class);numbers.add(short.class);
numbers.add(Byte.class);numbers.add(byte.class);
numbers.add(BigDecimal.class);numbers.add(BigInteger.class);
dates.add(Date.class); dates.add(Time.class);
dates.add(Timestamp.class);dates.add(java.util.Date.class);
strings.add(Character.class);strings.add(char.class);
strings.add(String.class);strings.add(StringBuilder.class);
strings.add(StringBuffer.class);
}
/**
* 是否为基本数据类型
* */
public static boolean isPrimitive(Class<?> klass) {
return primitives.contains(klass);
}
/**
* 是否为字符串类型
* */
public static boolean isString(Class<?> cls) {
return strings.contains(cls) || hashClass(cls, CharSequence.class);
}
public static boolean isNumber(Class<?> type) {
return numbers.contains(type);
}
public static boolean isInt(Class<?> type) {
return integers.contains(type);
}
public static boolean isDouble(Class<?> type) {
return doubles.contains(type);
}
public static boolean isDate(Class<?> type) {
return dates.contains(type);
}
/**
* 是否是map集合
* */
public static boolean isMap(Class<?> klass) {
return hashClass(klass, Map.class);
}
/**
* 是否是set集合
* */
public static boolean isSet(Class<?> klass) {
return hashClass(klass, Set.class);
}
/**
* 是否是list集合
* */
public static boolean isList(Class<?> klass) {
return hashClass(klass, List.class);
}
public static boolean isCollection(Class<?> klass) {
return isList(klass) || isSet(klass);
}
/**
* klass是否实现了face类或接口
* @author tanuki
* @param klass 要判断的类型
* @param face 指定的类型
* */
public static boolean hashClass(Class<?> klass, Class<?> face) {
if (klass.equals(face)) {
return true;
} else {
if (Object.class.equals(klass)) {
return false;
}
Class<?>[] cls = klass.getInterfaces();
for (int i = 0; i < cls.length; i++) {
if (hashClass(cls[i], face)) {
return true;
}
}
if (!klass.isInterface()) {
if (hashClass(klass.getSuperclass(), face)) {
return true;
}
}
}
return false;
}
/**
* Type 类型转 class
* */
public static Class<?> getClass(Type type) throws ClassNotFoundException{
String cStr=type.toString();
if(cStr.indexOf("class ")==0){
return Class.forName(cStr.substring(6, cStr.length()));
}else if(cStr.indexOf("interface ")==0){
return Class.forName(cStr.substring(10, cStr.length()));
}else{
if(cStr.indexOf("<")!=-1){
return Class.forName(cStr.substring(0, cStr.indexOf("<")));
}
return Class.forName(cStr.substring(0, cStr.length()));
}
}
public static Type[] getFeildFan(Field field) {
Type type = field.getGenericType();
if(type instanceof ParameterizedType){
return ((ParameterizedType)type).getActualTypeArguments();
}
return null;
}
public static Type getFeildFan(Field field,int index) {
Type type = field.getGenericType();
if(type instanceof ParameterizedType){
return ((ParameterizedType)type).getActualTypeArguments()[index];
}
return field.getType();
}
public static Class<?> getFeildFanClass(Field field,int index) throws ClassNotFoundException {
return getClass(getFeildFan(field, index));
}
/**
* 获取结合的泛型
* */
public static Type getCollectionFan(Type type){
Type result=null;
if(type instanceof ParameterizedType){
result=((ParameterizedType)type).getActualTypeArguments()[0];
}else{
result=type;
}
return result;
}
/**
* 获取结合的泛型
* @throws ClassNotFoundException
* */
public static Class<?> getCollectionFanClass(Type type) throws ClassNotFoundException{
Class<?> result=null;
if(type instanceof ParameterizedType){
result= getClass(((ParameterizedType)type).getActualTypeArguments()[0]);
}else{
result = getClass(type);
}
return result;
}
/**
* 获取结合的泛型
* @throws ClassNotFoundException
* */
public static Class<?> getArrayClass(Class<?> type) throws ClassNotFoundException{
return type.getComponentType();
}
/**
* <p>
* 反射对象获取泛型
* </p>
*
* @param clazz 对象
* @param index 泛型所在位置
* @return Class
*/
public static Class<?> getSuperClassGenericType(final Class<?> clazz, final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
log.warn("Warn: {}'s superclass not ParameterizedType", clazz.getSimpleName());
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
log.warn("Warn: Index: {}, Size of {}'s Parameterized Type: {} .", index,clazz.getSimpleName(), params.length);
return Object.class;
}
if (!(params[index] instanceof Class)) {
log.warn("Warn: {} not set the actual class on superclass generic parameter",clazz.getSimpleName());
return Object.class;
}
return (Class<?>) params[index];
}
/**
* 获取Map的泛型
* */
public static Type[] getMapFan(Type type){
Type[] result=null;
if(type instanceof ParameterizedType){
result=((ParameterizedType)type).getActualTypeArguments();
}else{
result=new Type[0];
}
return result;
}
/**
* 读取远程jar包加载到当前jvm中
* */
public static void loadJar(Set<String> urls) {
Method method = null;
boolean accessible = false;
try {
method= URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
accessible = method.isAccessible();
if (accessible == false) {
method.setAccessible(true);
}
URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
for (String address : urls) {
method.invoke(classLoader,new URL(address));
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(method!=null) {
method.setAccessible(accessible);
}
}
}
public static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
}
catch (Throwable ex) {}
if (cl == null) {
cl = ClassUtils.class.getClassLoader();
if (cl == null) {
try {
cl = ClassLoader.getSystemClassLoader();
}
catch (Throwable ex) {}
}
}
return cl;
}
@SuppressWarnings("unchecked")
public static <T>T newInstance(String className) {
try {
return (T) ClassUtils.loadClass(className).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public static Class<?> loadClass(String className) {
ClassLoader loader = getDefaultClassLoader();
if(loader==null) throw new RuntimeException("ClassLoader为空");
try {
return loader.loadClass(className);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Class<?> loadClass(ClassLoader loader,String className) {
try {
if(loader==null) {
return loadClass(className);
}
return loader.loadClass(className);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,113 @@
package com.pictc.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
public class CollectionUtils{
public static <T>List<T> newVector(){
return new Vector<T>();
}
public static <T>List<T> newConcurrentArrayList(){
return new CopyOnWriteArrayList<T>();
}
public static <T>List<T> newArrayList(){
return new ArrayList<T>();
}
public static <T>List<T> newArrayList(int size){
return new ArrayList<T>(size);
}
public static <T>List<T> newLinkedList(){
return new LinkedList<T>();
}
public static <V, K>Map<K,V> newHashMap(){
return new HashMap<K,V>();
}
public static <V, K> Map<K,V> newHashtable(){
return new Hashtable<K,V>();
}
public static <V, K> Map<K,V> newIdentityHashMap(){
return new IdentityHashMap<K,V>();
}
public static <V, K> Map<K,V> newLinkedHashMap(){
return new LinkedHashMap<K,V>();
}
public static <V, K> Map<K,V> newTreeMap(){
return new TreeMap<K,V>();
}
public static <V, K> Map<K,V> newWeakHashMap(){
return new WeakHashMap<K,V>();
}
public static <V, K> Map<K,V> newConcurrentHashMap(){
return new ConcurrentHashMap<K,V>();
}
public static Properties newProperties(){
return new Properties();
}
public static <T> Set<T> newHashSet(){
return new HashSet<T>();
}
public static <T> Set<T> newLinkedHashSet(){
return new LinkedHashSet<T>();
}
public static <T> Set<T> newTreeSet(){
return new TreeSet<T>();
}
public static <T> Set<T> newConcurrentSet(){
return new ConcurrentSkipListSet<T>();
}
@SuppressWarnings("unchecked")
public static <T> T[] toArray(Collection<T> collection) {
if(collection!=null) {
return (T[]) collection.toArray();
}
return null;
}
public static boolean isEmpty(Collection<?> collection) {
return collection==null || collection.isEmpty();
}
public static boolean isNotEmpty(Collection<?> collection) {
return collection!=null && !collection.isEmpty();
}
}

View File

@ -0,0 +1,873 @@
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.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
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.exceptions.OrmException;
import com.pictc.jdbc.JdbcContext;
import com.pictc.jdbc.ResultSetUtils;
import com.pictc.jdbc.model.JdbcParam;
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.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 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("tenantId");
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 <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;
}
public static boolean deleteByIds(Class<?> klazz, @Valid List<Long> ids) {
for (Long id : ids) {
deleteById(klazz, id);
}
return true;
}
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;
}
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 void delete(Object entity,LogTableInfo tableinfo,BaseMapper mapper){
Long idValue = tableinfo.getIdValue(entity);
if(idValue!=null && idValue > 0) {
// QueryChainWrapper wrapper = new QueryChainWrapper(mapper);
// wrapper.eq(tableinfo.getIdColumn(),tableinfo.getIdValue(entity));
// mapper.delete(wrapper);
mapper.deleteById(idValue);
}else {
throw new RuntimeException("删除数据时,表【"+tableinfo.getName()+"】的主键为空,删除失败!");
}
}
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;
if((newVal==null && oldVal!=null) || (newVal!=null && oldVal==null)) {
flag = 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: 根据数据id获取操作日志
* @param klass 数据java类型
* @param dataId 数据id
* @return List<DataChangeLog> 返回类型
*/
public static <T>List<DataChangeLog> findLogsByEntityId(Class<T> klass,@NonNull Long dataId) {
LogTableInfo tabInfo = getAnnotation(klass);
String tableName = parseLogTableName(tabInfo);
if(initTable(tableName)) {
return null;
}
List<DataChangeLog> result = CollectionUtils.newArrayList();
String sql = parseSql(SQL_LIST, tableName);
JdbcContext context = null;
try {
context = new JdbcContext(true,false);
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 result;
} catch (SQLException e) {
throw context.createException(e);
} finally {
context.end();
}
}
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();
}
}
}

View File

@ -0,0 +1,448 @@
package com.pictc.utils;
import lombok.extern.slf4j.Slf4j;
import java.text.ParseException;
import java.text.SimpleDateFormat;
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.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Set;
import static java.util.Calendar.DATE;
import java.sql.Time;
import java.sql.Timestamp;
@Slf4j
public class DateUtils {
public static final String GENERAL = "yyyy-MM-dd";
public static final String FMT_TIME = "HH:mm:ss";
public static final String FMT_OFFSET_DATETIME = "yyyy-MM-dd HH:mm:ssXXX";
public static final String FMT_OFFSET_TIME = "HH:mm:ssXXX";
public static final String GENERAL_YYYYMMDD = "yyyyMMdd";
public static final String GENERAL_YYYYMMDDHHMMSS = "yyyyMMddHHmmSS";
public static final String LONG_FORMAT = "yyyy-MM-dd HH:mm:ss";
public final static DateTimeFormatter FORMATTER_YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern(LONG_FORMAT);
// 针对GMT格式的日期转换格式
public static final String GMT_DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'";
private static final SimpleDateFormat sdf = new SimpleDateFormat(LONG_FORMAT);
private static final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(GENERAL);
public static final ZoneId zone = ZoneId.of("GMT+8");
private static Set<Class<?>> dates = CollectionUtils.newHashSet();
static {
dates.add(Date.class);
dates.add(Time.class);
dates.add(Timestamp.class);
dates.add(java.util.Date.class);
}
public static boolean isDate(Class<?> type) {
return dates.contains(type);
}
public static String formatDate(Date date) {
if (null == date) {
return null;
}
return sdf.format(date);
}
public static Date formatDate2Date(Date date) {
if (null == date) {
return null;
}
String format = sdf.format(date);
try {
return sdf.parse(format);
} catch (ParseException e) {
log.error(e.getMessage(), e);
}
return null;
}
/**
* 按传入的格式化规则格式化传入的日期
*
* @param date : 传入日期对象
* @param dateFormat : 格式化规则(如yyyy-MM-dd,yyyyMMdd等如果传空或NULL则默认为yyyy-MM-dd)
* @return String
* @author 张江立
*/
public static String formatDate(Date date, String dateFormat) {
if (null == date) {
return null;
}
if (null == dateFormat || "".equals(dateFormat)) {
dateFormat = "yyyy-MM-dd";
}
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
String formatDateAfterStr = sdf.format(date);
return formatDateAfterStr;
}
/**
* 针对格林日期转换为字符串
*
* @param datestr日期字符串datestr = "Tue Jun 05 2018 13:11:11 GMT"
* @return Date
*/
public static Date GMTDateToString(String datestr) {
SimpleDateFormat sdf = new SimpleDateFormat(GMT_DATE_FORMAT, Locale.ENGLISH);
Date date = null;
try {
date = sdf.parse(datestr);
} catch (ParseException e) {
log.error(e.getMessage(), e);
}
return date;
}
/**
* 传入日期添加天数
*
* @param date : 日期对象
* @param days : 天数
* @return Date
*/
public static Date addDays(Date date, int days) {
if (null == date) {
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(DATE, days);
return calendar.getTime();
}
/**
* 日期字符串转成日期对象
*
* @param dateString; 如:"2012-12-06"
* @param dateFormat :格式化规则(如yyyy-MM-dd)
* :DateUtils.GENERAL
* :DateUtils.LONG_FORMAT
* @return Date
*/
public static Date stringToDate(String dateString, String dateFormat) {
Date date = null;
if (null == dateString || "".equals(dateString) || "null".equalsIgnoreCase(dateString) || null == dateFormat || "".equals(dateFormat)) {
return date;
}
try {
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
date = sdf.parse(dateString);
} catch (ParseException e) {
log.error(e.getMessage(), e);
return date;
}
return date;
}
/**
* 日期字符串转成日期对象,默认格式: yyyy-MM-dd HH:mm:ss
*
* @param dateString
* @return
*/
public static Date stringToDate(String dateString) {
Date date = null;
if (null == dateString || "".equals(dateString) || "null".equalsIgnoreCase(dateString)) {
return date;
}
try {
date = sdf.parse(dateString);
} catch (ParseException e) {
log.error(e.getMessage(), e);
return date;
}
return date;
}
/**
* 返回昨天
*
* @param today
* @return
*/
public static Date yesterday(Date today) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(today);
calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 1);
return calendar.getTime();
}
/**
* 返回明天
*
* @param today
* @return
*/
public static Date tomorrow(Date today) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(today);
calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) + 1);
return calendar.getTime();
}
public static final String format(Date date, String pattern) {
if(date==null) return null;
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(date);
}
public static final String format(LocalDate localDate) {
return format(localDate, GENERAL);
}
public static final String format(LocalDate localDate, String pattern) {
if(localDate==null) return null;
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
return localDate.format(dateFormatter);
}
public static final String format(LocalTime localDate) {
return format(localDate,FMT_TIME);
}
public static final String format(LocalTime localDate,String pattern) {
if(localDate==null) return null;
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
return localDate.format(dateFormatter);
}
public static final String format(LocalDateTime localDateTime) {
return format(localDateTime,LONG_FORMAT);
}
public static final String format(LocalDateTime localDateTime,String pattern) {
if(localDateTime==null) return null;
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
return localDateTime.format(dateFormatter);
}
public static final String format(OffsetDateTime offsetDateTime) {
return format(offsetDateTime,FMT_OFFSET_DATETIME);
}
public static final String format(OffsetDateTime offsetDateTime,String pattern) {
if(offsetDateTime==null) return null;
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
return offsetDateTime.format(dateFormatter);
}
public static final String format(OffsetTime offsetTime) {
return format(offsetTime,FMT_OFFSET_TIME);
}
public static final String format(OffsetTime offsetDateTime,String pattern) {
if(offsetDateTime==null) return null;
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
return offsetDateTime.format(dateFormatter);
}
public static final String format(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
public static long getDateTime(String dateStr) {
Date date = stringToDate(dateStr, "yyyy-MM-dd HH:mm:ss");
return date.getTime();
}
// 取得当前日期(YYYYMMDD)
public static String getYYYYMMDD() {
SimpleDateFormat sdf = new SimpleDateFormat(GENERAL_YYYYMMDD);
return sdf.format(new Date());
}
// 取得时间戳(YYYYMMDDHHMMSS)
public static String getTimeStamp() {
SimpleDateFormat sdf = new SimpleDateFormat(GENERAL_YYYYMMDDHHMMSS);
return sdf.format(new Date());
}
public static String getYear() {
Calendar cal = Calendar.getInstance();
return cal.get(Calendar.YEAR) + "";
}
public static String getMonth() {
Calendar cal = Calendar.getInstance();
int i = cal.get(Calendar.MONTH) + 1;
if (i < 10) {
return "0" + i;
}
return i + "";
}
public static String getDate() {
Calendar cal = Calendar.getInstance();
int i = cal.get(Calendar.DATE);
if (i < 10) {
return "0" + i;
}
return i + "";
}
/**
* 获取上个月最后一天
*
* @return
*/
public static String getMonthLastDate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Calendar c = Calendar.getInstance();
Date parse = new Date();
// 设置为指定日期
if (StringUtils.isNotEmpty(date)) {
date = date.replace("-", "");
try {
parse = sdf.parse(date);
} catch (ParseException e) {
log.error(e.getMessage(), e);
return "";
}
}
c.setTime(parse);
// 指定日期月份减去一
c.add(Calendar.MONTH, -1);
// 指定日期月份减去一后的 最大天数
c.set(Calendar.DATE, c.getActualMaximum(Calendar.DATE));
// 获取最终的时间
Date time = c.getTime();
return sdf.format(time);
}
/**
* 获取yyyy-MM-dd当天
*
* @return
*/
public static String getToday() {
String today = LocalDate.now().format(fmt);
return today;
}
/**
* 获取yyyy-MM-dd明天
*
* @return
*/
public static String getTomorrow() {
String tomorrow = LocalDate.now().plusDays(1).format(fmt);
return tomorrow;
}
/**
* 设置时间
*
* @param date 时间
* @param hour 小时
* @param minute 分钟
* @param second 秒钟
* @param millisecond 毫秒
* @return 返回值
*/
public static Date setDateTime(Date date, Integer hour, Integer minute, Integer second, Integer millisecond) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.MILLISECOND, millisecond);
return calendar.getTime();
}
public static LocalDateTime toLocalDateTime(String source){
return toLocalDateTime(source, LONG_FORMAT);
}
public static LocalDateTime toLocalDateTime(String source,String fmt){
try {
return LocalDateTime.parse(source,DateTimeFormatter.ofPattern(fmt));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static LocalDate toLocalDate(String source){
return toLocalDate(source, GENERAL);
}
public static LocalDate toLocalDate(String source,String fmt){
try {
return LocalDate.parse(source,DateTimeFormatter.ofPattern(fmt));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static LocalTime toLocalTime(String source){
return toLocalTime(source, FMT_TIME);
}
public static LocalTime toLocalTime(String source,String fmt){
try {
return LocalTime.parse(source,DateTimeFormatter.ofPattern(fmt));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Timestamp toTimestamp(String source,String fmt){
try {
SimpleDateFormat f = new SimpleDateFormat(fmt);
return new Timestamp(f.parse(source).getTime());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static LocalDateTime toLocalDateTime(Date date) {
return LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), zone);
}
public static Date toDate(LocalDateTime ldtime) {
return Date.from(ldtime.atZone(zone).toInstant());
}
public static Timestamp toTimestamp(LocalDateTime ldtime) {
return Timestamp.from(ldtime.atZone(zone).toInstant());
}
}

View File

@ -0,0 +1,349 @@
package com.pictc.utils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
public class IoUtils {
private final static Charset charset=Charset.forName("UTF-8");
private final static ForkJoinPool forkJoinPool = new ForkJoinPool();
public static void closeQuietly(Closeable... closeables) {
if (closeables == null)
return;
for (Closeable closeable : closeables) {
if (closeable == null)
return;
try {
closeable.close();
} catch (IOException ignored) {
}
}
}
// In JDK 1.6, java.net.Socket doesn't implement Closeable, so we have this
// overload.
public static void closeQuietly(final Socket... sockets) {
if (sockets == null)
return;
for (Socket socket : sockets) {
if (socket == null)
return;
try {
socket.close();
} catch (IOException ignored) {
}
}
}
/**
* Returns the text read from the given reader as a String. Closes the given
* reader upon return.
*/
public static String getText(Reader reader) throws IOException {
try {
StringBuilder source = new StringBuilder();
BufferedReader buffered = new BufferedReader(reader);
String line = buffered.readLine();
while (line != null) {
source.append(line);
source.append('\n');
line = buffered.readLine();
}
return source.toString();
} finally {
closeQuietly(reader);
}
}
/**
* Returns the text read from the given file as a String.
*/
public static String getText(File path) throws IOException {
return getText(new FileReader(path));
}
public static String getText(InputStream stream) throws IOException {
return getText(new InputStreamReader(stream,charset));
}
public static String getText(InputStream stream,Charset charset) throws IOException {
return getText(new InputStreamReader(stream,charset));
}
public static void createDirectory(File dir) throws IOException {
if (!dir.exists()) {
dir.mkdirs();
}
}
public static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[8192];
try {
int read = in.read(buffer);
while (read > 0) {
out.write(buffer, 0, read);
read = in.read(buffer);
}
} finally {
closeQuietly(in, out);
}
}
public static void copyFile(File source, File target) throws FileNotFoundException, IOException {
if (!source.isFile())
throw new IOException(
String.format("Error copying file %s to %s; source file does not exist", source, target));
createDirectory(target.getParentFile());
doCopyFile(source, target);
checkSameSize(source, target);
}
public static List<File> listFilesRecursively(File baseDir) throws IOException {
if (!baseDir.exists())
return Collections.emptyList();
List<File> result = new ArrayList<File>();
doListFilesRecursively(baseDir, result);
return result;
}
public static String getFileExtension(String filename) {
int index = filename.lastIndexOf('.');
return index == -1 ? null : filename.substring(index + 1, filename.length());
}
public static void createFile(File file) throws IOException {
if(!file.exists()) {
if(file.isDirectory()) {
file.mkdirs();
}else {
file.getParentFile().mkdirs();
file.createNewFile();
}
}
}
private static void doListFilesRecursively(File baseDir, List<File> result) throws IOException {
List<File> dirs = new ArrayList<File>();
File[] files = baseDir.listFiles();
if (files == null) {
throw new IOException("Failed to list files of directory '" + baseDir + "'");
}
for (File file : files) {
if (file.isFile()) {
result.add(file);
} else {
dirs.add(file);
}
}
for (File dir : dirs) {
doListFilesRecursively(dir, result);
}
}
private static void doCopyFile(File source, File target) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(source);
out = new FileOutputStream(target);
// instead of checking transferred size, we'll compare file sizes in
// checkSameSize()
in.getChannel().transferTo(0, Long.MAX_VALUE, out.getChannel());
} finally {
closeQuietly(in, out);
}
}
private static void checkSameSize(File source, File target) throws IOException {
long fromSize = source.length();
long toSize = target.length();
if (fromSize != toSize)
throw new IOException(
String.format("Error copying file %s to %s; source file size is %d, but target file size is %d",
source, target, fromSize, toSize));
}
public static byte[] getBytes(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
copyStream(in, out);
return out.toByteArray();
}
public static byte[] getBytes(File in) throws IOException {
return getBytes(new FileInputStream(in));
}
public static void streamToFile(InputStream in, File file) throws IOException {
if (!file.exists()) {
//createDirectory(file.getParentFile());
file.createNewFile();// 将压缩文件内容写入到这个文件中
}
FileOutputStream fos = new FileOutputStream(file);
int count;
byte[] buf = new byte[8192];
while ((count = in.read(buf)) != -1) {
fos.write(buf, 0, count);
}
fos.flush();
closeQuietly(in, fos);
}
public static void byteToFile(byte[] bytes, File file) throws IOException {
if (!file.exists()) {
//createDirectory(file.getParentFile());
file.createNewFile();// 将压缩文件内容写入到这个文件中
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(bytes);
fos.flush();
closeQuietly(fos);
}
public static void writeFile(File file, OutputStream out, boolean close) throws IOException {
FileInputStream in = null;
try {
in = new FileInputStream(file);
int count;
byte[] buf = new byte[8192];
while ((count = in.read(buf)) != -1) {
out.write(buf, 0, count);
}
out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
closeQuietly(in);
if (close) {
closeQuietly(out);
}
}
}
private static class FileSizeFinder extends RecursiveTask<Long> {
/**
*
*/
private static final long serialVersionUID = 1L;
final File file;
public FileSizeFinder(final File theFile) {
file = theFile;
}
@Override
public Long compute() {
long size = 0;
if (file.isFile()) {
size = file.length();
} else {
final File[] children = file.listFiles();
if (children != null) {
List<ForkJoinTask<Long>> tasks = new ArrayList<ForkJoinTask<Long>>();
for (final File child : children) {
if (child.isFile()) {
size += child.length();
} else {
tasks.add(new FileSizeFinder(child));
}
}
for (final ForkJoinTask<Long> task : invokeAll(tasks)) {
size += task.join();
}
}
}
return size;
}
}
public static long getFileSize(File file) {
return forkJoinPool.invoke(new FileSizeFinder(file));
}
public static String getProjectPath() {
String url=Thread.currentThread().getContextClassLoader().getResource("").getPath();
try {
url=url.substring(1, url.length()-15);
if(url.contains("/targe")) {
url = url.replace("/targe","");
}
return URLDecoder.decode(url,"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return url;
}
public static void delFile(File file) {
if(file.isDirectory()) {
File[] childs = file.listFiles();
if(childs!=null) {
for (int i = 0; i < childs.length; i++) {
if(childs[i].isDirectory()) {
delFile(childs[i]);
}else {
childs[i].delete();
}
}
}
}
file.delete();
}
public static List<File> findFile(File file,FilenameFilter filter) {
List<File> res = new ArrayList<File>();
findChilds(res, file, filter);
return res;
}
private static void findChilds(List<File> res,File file,FilenameFilter filter) {
if(file.isDirectory()) {
File[] delFiles=file.listFiles(filter);
for (int i = 0; i < delFiles.length; i++) {
res.add(delFiles[i]);
}
File[] childs= file.listFiles();
for (int i = 0; i < childs.length; i++) {
findChilds(res,childs[i],filter);
}
}
}
}

View File

@ -0,0 +1,69 @@
package com.pictc.utils;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public final class LambdaUtils {
private LambdaUtils() {
super();
}
public static <T, R>SerializedLambda getLambda(TFunction<T, R> fn) {
// 从function取出序列化方法
Method writeReplaceMethod = null;
try {
writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
writeReplaceMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
// 从序列化方法取出序列化的lambda信息
SerializedLambda lambda = null;
try {
lambda = (SerializedLambda) writeReplaceMethod.invoke(fn);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
return lambda;
}
public static <T, R>Field getField(TFunction<T, R> fn) {
// 从序列化方法取出序列化的lambda信息
SerializedLambda lambda = getLambda(fn);
String fieldName = getFieldName(lambda);
Field field = null;
try {
field = Class.forName(lambda.getImplClass().replace("/", ".")).getDeclaredField(fieldName);
} catch (ClassNotFoundException | NoSuchFieldException e) {
throw new RuntimeException(e);
}
return field;
}
private static <T, R>String getFieldName(SerializedLambda lambda) {
// 从lambda信息取出method、field、class等
String implMethodName = lambda.getImplMethodName();
// 确保方法是符合规范的get方法boolean类型是is开头
if (!implMethodName.startsWith("is") && !implMethodName.startsWith("get")) {
throw new RuntimeException("get方法名称: " + implMethodName + ", 不符合java bean规范");
}
// get方法开头为 is 或者 get将方法名 去除is或者get然后首字母小写就是属性名
int prefixLen = implMethodName.startsWith("is") ? 2 : 3;
String fieldName = implMethodName.substring(prefixLen);
String firstChar = fieldName.substring(0, 1);
fieldName = fieldName.replaceFirst(firstChar, firstChar.toLowerCase());
return fieldName;
}
public static <T, R>String getFieldName(TFunction<T, R> fn) {
SerializedLambda lambda = getLambda(fn);
return getFieldName(lambda);
}
}

View File

@ -0,0 +1,129 @@
package com.pictc.utils;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.NonNull;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ListUtils {
public static enum ListType{
ArrayList,LinkedList,Vector,CopyOnWriteArrayList
}
public static ListType parseType(Class<?> cls) {
if(LinkedList.class.equals(cls)) {
return ListType.LinkedList;
}else if(Vector.class.equals(cls)) {
return ListType.Vector;
}else if(CopyOnWriteArrayList.class.equals(cls)) {
return ListType.CopyOnWriteArrayList;
}else {
return ListType.ArrayList;
}
}
public static <T> List<T> getMapNewInstance(ListType type) {
List<T> result=null;
switch (type) {
case LinkedList:
result=CollectionUtils.newLinkedList();
break;
case Vector:
result=CollectionUtils.newVector();
break;
case CopyOnWriteArrayList:
result=CollectionUtils.newConcurrentArrayList();
break;
default:
result=CollectionUtils.newArrayList();
break;
}
return result;
}
public static <T>List<T> newInstance(Class<?> cls) {
return getMapNewInstance(parseType(cls));
}
public static <T> void forEach(@NonNull List<T> list,ListForEach<? super T> action){
int i=0;
Iterator<T> iterator=list.iterator();
while (iterator.hasNext()) {
action.accept(iterator.next(),i);
i++;
}
}
@FunctionalInterface
public interface ListForEach<T>{
void accept(T t,int index);
}
@SuppressWarnings("unchecked")
public static <T> List<T> ofArray(T... objs){
List<T> result=null;
if(objs!=null && objs.length>0) {
result=CollectionUtils.newArrayList();
for (int i = 0; i < objs.length; i++) {
result.add(objs[i]);
}
}
return result;
}
@SuppressWarnings("unchecked")
public static <T> List<T> newArrayList(T... objs){
List<T> result=null;
if(objs!=null && objs.length>0) {
result=CollectionUtils.newArrayList();
for (int i = 0; i < objs.length; i++) {
result.add(objs[i]);
}
}
return result;
}
@SuppressWarnings("unchecked")
public static <T> List<T> ofCollection(Collection<?> list){
List<T> result=null;
if(list!=null && list.size()>0) {
result=CollectionUtils.newArrayList();
for (Object t : list) {
result.add((T)t);
}
}
return result;
}
public static <T> List<T> ofArrays(T[] objs){
List<T> result=null;
if(objs!=null && objs.length>0) {
result=CollectionUtils.newArrayList();
for (int i = 0; i < objs.length; i++) {
result.add(objs[i]);
}
}
return result;
}
public static <T>T getFirst(List<T> list){
if(CollectionUtils.isNotEmpty(list)) {
return list.get(0);
}
return null;
}
}

View File

@ -0,0 +1,93 @@
package com.pictc.utils;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MapUtils {
public static enum MapType {
hashMap,Hashtable,Properties,LinkedHashMap,IdentityHashMap,
TreeMap,WeakHashMap,ConcurrentHashMap
}
public static MapType parseMapType(Class<?> cls) {
if(Hashtable.class.equals(cls)) {
return MapType.Hashtable;
}else if(Properties.class.equals(cls)) {
return MapType.Properties;
}else if(LinkedHashMap.class.equals(cls)) {
return MapType.LinkedHashMap;
}else if(IdentityHashMap.class.equals(cls)) {
return MapType.IdentityHashMap;
}else if(TreeMap.class.equals(cls)) {
return MapType.TreeMap;
}else if(WeakHashMap.class.equals(cls)) {
return MapType.WeakHashMap;
}else if(ConcurrentHashMap.class.equals(cls)) {
return MapType.ConcurrentHashMap;
}else {
return MapType.hashMap;
}
}
@SuppressWarnings("unchecked")
public static <K, V> Map<K,V> getMapNewInstance(MapType type) {
Map<K,V> result=null;
switch (type) {
case Hashtable:
result=CollectionUtils.newHashtable();
break;
case Properties:
result=(Map<K, V>) CollectionUtils.newProperties();
break;
case LinkedHashMap:
result=CollectionUtils.newLinkedHashMap();
break;
case IdentityHashMap:
result=CollectionUtils.newIdentityHashMap();
break;
case TreeMap:
result=CollectionUtils.newTreeMap();
break;
case WeakHashMap:
result=CollectionUtils.newWeakHashMap();
break;
case ConcurrentHashMap:
result=CollectionUtils.newConcurrentHashMap();
break;
default:
result=CollectionUtils.newHashMap();
break;
}
return result;
}
public static <K, V> Map<K,V> newInstance(Class<?> cls) {
return getMapNewInstance(parseMapType(cls));
}
public static <K, V, R> Map<K,V> ofList(Collection<V> collections,TFunction<V, R> fn) {
Map<K,V> map = CollectionUtils.newHashtable();
Field field = LambdaUtils.getField(fn);
for (V v : collections) {
K k = BeanUtils.getFieldValue(field, v);
map.put(k, v);
}
return map;
}
}

View File

@ -0,0 +1,103 @@
package com.pictc.utils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
@SuppressWarnings("rawtypes")
public class MybatisTools implements ApplicationContextAware {
/**
* 存储Mapper类与实体类的映射关系
* key: Mapper接口的Class对象
* value: 对应的实体类的Class对象
*/
private static final Map<Class<?>,BaseMapper<?>> ENTITY_MAPPER_MAP = new HashMap<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 获取所有继承自BaseMapper的接口即MyBatis-Plus的Mapper接口
Map<String, BaseMapper> mapperBeans = applicationContext.getBeansOfType(BaseMapper.class);
for (BaseMapper<?> mapper : mapperBeans.values()) {
// 获取Mapper接口的Class对象因为mapper是代理对象需要获取原始接口
Class<?> mapperInterface = getMapperInterface(mapper.getClass());
// 解析Mapper接口对应的实体类
Class<?> entityClass = resolveEntityClass(mapperInterface);
if (entityClass != null) {
ENTITY_MAPPER_MAP.put(entityClass, mapper);
}
}
System.out.println(ENTITY_MAPPER_MAP);
}
/**
* 获取Mapper代理对象对应的原始接口
*/
private Class<?> getMapperInterface(Class<?> mapperProxyClass) {
// MyBatis的Mapper代理类会实现对应的Mapper接口
Class<?>[] interfaces = mapperProxyClass.getInterfaces();
for (Class<?> iface : interfaces) {
// 判断是否是BaseMapper的子类
if (BaseMapper.class.isAssignableFrom(iface) && iface != BaseMapper.class) {
return iface;
}
}
return mapperProxyClass;
}
/**
* 解析Mapper接口对应的实体类通过泛型参数
*/
private Class<?> resolveEntityClass(Class<?> mapperInterface) {
// 获取Mapper接口的泛型父类BaseMapper<T>
Type[] genericInterfaces = mapperInterface.getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
if (genericInterface instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
// 检查是否是BaseMapper
if (parameterizedType.getRawType() == BaseMapper.class) {
// 获取泛型参数T即实体类
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length > 0 && actualTypeArguments[0] instanceof Class) {
return (Class<?>) actualTypeArguments[0];
}
}
}
}
return null;
}
/**
* 根据实体类获取对应的Mapper类
*/
public static BaseMapper<?> getMapper(Class<?> entityClass) {
return ENTITY_MAPPER_MAP.get(entityClass);
}
public static TableInfo getTableInfo(Class<?> entityClass) {
return TableInfoHelper.getTableInfo(entityClass);
}
public static TableInfo getTableInfo(String tablename) {
return TableInfoHelper.getTableInfo(tablename);
}
}

View File

@ -0,0 +1,118 @@
package com.pictc.utils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexUtils {
private static final Set<String> symbols=SetUtils.of("\\","^","$","*","+","?","{","}","[","]",".","|","-","\\b","\\B"
,"\\c","\\d","\\D","\\f","\\n","\\r","\\s","\\S","\\t","\\v","\\w","\\W","\\x","\\u");
private static final String prefix="${";
private static final String suffixed="}";
private static final Pattern placeholder_regex=buildPlaceholderPattern(prefix, suffixed);
private RegexUtils() {
super();
}
public static boolean has(String regex,String str) {
return has(Pattern.compile(regex), str);
}
/**
* 判断字符中是否包含占位符
* */
public static boolean has(Pattern pattern,String str) {
return pattern.matcher(str).find();
}
public static boolean has(String str) {
return placeholder_regex.matcher(str).find();
}
public static List<String> findPlaceholder(String str) {
return findPlaceholder(str,placeholder_regex,2,1);
}
public static List<String> findPlaceholder(String str,String regex,int prefixLeng,int endLeng) {
return findPlaceholder(str,Pattern.compile(regex),prefixLeng,endLeng);
}
/**
* 查找字符串中的占位符中的字符
* */
public static List<String> findPlaceholder(String str,Pattern pattern,int prefixLeng,int endLeng) {
Matcher m=pattern.matcher(str);
List<String> result=null;
while (m.find()) {
if(result==null) result=CollectionUtils.newArrayList();
result.add(m.group().substring(prefixLeng, m.group().length()-endLeng));
}
return result;
}
public static String replacePlaceholder(String str,String[] replaceStr) {
return replacePlaceholder(placeholder_regex, str, replaceStr);
}
public static String replacePlaceholder(String str,Map<String,String> values) {
List<String> placeholders = findPlaceholder(str);
List<String> replaceValues = CollectionUtils.newArrayList();
for (String key : placeholders) {
replaceValues.add(values.get(key));
}
String[] _vals = new String[replaceValues.size()];
replaceValues.toArray(_vals);
return replacePlaceholder(placeholder_regex, str,_vals);
}
public static String replacePlaceholder(Pattern regex,String str,String[] replaceStr) {
Matcher m=regex.matcher(str);
StringBuilder result=new StringBuilder();
int index=0;int before=0;
while (m.find()) {
result.append(str.subSequence(before, m.start()));
before=m.end();
if(index<replaceStr.length) {
String _value = replaceStr[index];
if(_value!=null) {
result.append(_value);
}
}
index++;
}
if(str.length()!=before) result.append(str.subSequence(before, str.length()));
return result.toString();
}
/**
* 转义字符中的正则元符
* */
public static String decodeRegex(String str) {
for (String key : symbols) {
if(str.contains(key)) {
str=str.replace(key,"\\"+key);
}
}
return str;
}
/**
* 创建占位符的正则表达式
* */
public static Pattern buildPlaceholderPattern(String prefix,String suffixed) {
prefix=decodeRegex(prefix);
suffixed=decodeRegex(suffixed);
return Pattern.compile(String.format("%s[^%s]*%s", prefix,suffixed,suffixed));
}
}

View File

@ -0,0 +1,23 @@
package com.pictc.utils;
public class SanDefaultFilter implements SanFilter{
public final String CLASS_SUFFIX = "^([^\\$]+|[^\\d+]+)\\.class";
@Override
public boolean accept(String current_package,String scan_package) {
if(StringUtils.isEmpty(scan_package)) {
return true;
}else if(scan_package.contains("*")) {
return current_package.matches(scan_package);
}
return current_package.startsWith(scan_package);
}
@Override
public boolean accept(String className) {
return className.matches(CLASS_SUFFIX);
}
}

View File

@ -0,0 +1,23 @@
package com.pictc.utils;
public interface SanFilter {
public final String CLASS_SUFFIX = "^([^\\$]+|[^\\d+]+)\\.class";
public default boolean accept(String current_package,String scan_package) {
if(scan_package.contains("*")) {
return current_package.matches(scan_package);
}
return current_package.equals(scan_package) || current_package.startsWith(scan_package);
};
public default boolean accept(String className) {
return className.matches(CLASS_SUFFIX);
};
public default boolean accept(Class<?> klazz) {
return true;
};
}

View File

@ -0,0 +1,200 @@
package com.pictc.utils;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ScanClasses {
private static Log log=LogFactory.getLog(ScanClasses.class);
/** 过滤器 **/
private static SanFilter filter =new SanDefaultFilter();
public static final String CLASS_SUFFIX = ".class";
private static final String FILE_PROCOTOL="file";
private static final String JAR_PROCOTOL="jar";
private ScanClasses() {
super();
}
public static Set<Class<?>> scan(Set<String> packages) {
return scan(packages, filter);
}
public static Set<Class<?>> scan(Set<String> packages,SanFilter filter) {
return scan(packages,null,filter);
}
public static Set<Class<?>> scan(Set<String> packages,Set<Class<? extends Annotation>> annotations) {
return scan(packages,annotations,filter);
}
public static Set<Class<?>> scan(Set<String> packages,Set<Class<? extends Annotation>> annotations,SanFilter filter) {
Set<Class<?>> classes=CollectionUtils.newHashSet();
Iterator<String> iterator=packages.iterator();
while (iterator.hasNext()) {
scan(classes,iterator.next(),annotations,filter);
}
return classes;
}
public static Set<Class<?>> scan(String[] packages) {
return scan(packages, filter);
}
public static Set<Class<?>> scan(String[] packages,SanFilter filter) {
return scan(packages,null,filter);
}
public static Set<Class<?>> scan(String[] packages,Set<Class<? extends Annotation>> annotations) {
return scan(packages,annotations,filter);
}
public static Set<Class<?>> scan(String[] packages,Set<Class<? extends Annotation>> annotations,SanFilter filter) {
Set<Class<?>> classes=CollectionUtils.newHashSet();
for (int i = 0; i < packages.length; i++) {
scan(classes,packages[i],annotations,filter);
}
return classes;
}
private static void scan(Set<Class<?>> classes,String scan_package,Set<Class<? extends Annotation>> annotations,SanFilter filter){
String current_package=getCurrentPackage(scan_package);
// 获取包的名字 并进行替换
String packageDirName = current_package.replace('.', '/');
// 定义一个枚举的集合 并进行循环来处理这个目录下的things
Enumeration<URL> dirs = null;
try {
dirs = ClassUtils.getDefaultClassLoader().getResources(packageDirName);
while(dirs.hasMoreElements()) {
URL url = dirs.nextElement();
if(log.isDebugEnabled()) {
log.debug("url协议--->"+url.getProtocol());
}
if(FILE_PROCOTOL.equals(url.getProtocol())) {
File file = new File(URLDecoder.decode(url.getFile(), "UTF-8"));
if(!file.exists() || !file.isDirectory()) {
continue;
}
if(file.isDirectory()) {
File[] files=file.listFiles();
for (int i = 0; i < files.length; i++) {
scanFile(scan_package,current_package,files[i],annotations,classes,filter);
}
}else {
scanFile(scan_package, current_package, file,annotations,classes,filter);
}
}else if(JAR_PROCOTOL.equals(url.getProtocol())) {
scanJar(scan_package, current_package, ((JarURLConnection)url.openConnection()).getJarFile(),annotations,classes,filter);
}
}
} catch (IOException e) {
log.error("扫描claess异常",e);
}
}
private static String getCurrentPackage(String scan_package) {
if(scan_package.contains(".*")) {
return scan_package.substring(0,scan_package.indexOf(".*"));
}
return scan_package;
}
/**
* 获取下次扫描的包路径
* */
private static String getNextPackage(String current_package,String file_name) {
String nextPackage=null;
if(StringUtils.isEmpty(current_package)) {
nextPackage= getClassName(file_name);
}else {
nextPackage=current_package+"."+getClassName(file_name);
}
return nextPackage;
}
private static void scanFile(String scan_package,String current_package,File file,Set<Class<? extends Annotation>> annotations,Set<Class<?>> classes,SanFilter filter) {
if(filter==null || (filter!=null && filter.accept(current_package,scan_package))){
String file_name=file.getName();
if(file.isDirectory()) {
File[] files=file.listFiles();
for (int i = 0; i < files.length; i++) {
scanFile(scan_package,getNextPackage(current_package,file_name),files[i],annotations,classes,filter);
}
}else {
if(filter==null || (filter!=null && filter.accept(file_name))) {
parseClass(scan_package, current_package,getNextPackage(current_package,file_name),annotations,classes,filter);
}
}
}
}
private static void parseClass(String scan_package,String current_package,String className,Set<Class<? extends Annotation>> annotations,Set<Class<?>> classes,SanFilter filter) {
Class<?> cls= ClassUtils.loadClass(className);
if(annotations!=null && !annotations.isEmpty()) {
for (Class<? extends Annotation> annotation : annotations) {
if(cls.getAnnotation(annotation)!=null) {
classes.add(cls);
return;
}
}
}else if(filter!=null && filter.accept(cls)){
classes.add(cls);
}
}
private static void scanJar(String scan_package,String current_package,JarFile jar,Set<Class<? extends Annotation>> annotations,Set<Class<?>> classes,SanFilter filter) {
Enumeration<JarEntry> entrys= jar.entries();
while(entrys.hasMoreElements()) {
JarEntry entry=entrys.nextElement();
if(!entry.isDirectory()) {
String cpackage = getJarPackage(entry);
if(filter==null || filter.accept(cpackage,scan_package)) {
String name = entry.getName();
if(filter==null || filter.accept(name)) {
parseClass(scan_package,cpackage,getJarClassName(entry),annotations,classes,filter);
}
}
}
}
}
private static String getJarPackage(JarEntry entry) {
String name = entry.getName();
if(name.lastIndexOf("/")!=-1) {
name = name.substring(0, name.lastIndexOf("/"));
}
return name.replace("/", ".");
}
private static String getJarClassName(JarEntry entry) {
return entry.getName().substring(0, entry.getName().length()-6).replaceAll("/", ".");
}
private static String getClassName(String name) {
return name.split("\\.")[0];
}
}

View File

@ -0,0 +1,68 @@
package com.pictc.utils;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import lombok.extern.slf4j.Slf4j;
/**
* @Description TODO(这里用一句话描述这个类的作用)
* @author zhangfucai
* @Date 2023年1月8日 下午6:29:01
* @version 1.0.0
*/
@Slf4j
public class ScanFile {
private static final String FILE_PROCOTOL="file";
private static final String JAR_PROCOTOL="jar";
public static void scan(String name,ScanFileFilter filter) {
try {
Enumeration<URL> dirs = getDefaultClassLoader().getResources(name);
if(dirs!=null) {
while(dirs.hasMoreElements()) {
URL url = dirs.nextElement();
if(FILE_PROCOTOL.equals(url.getProtocol())) {
filter.accept(url.openStream());
}else if(JAR_PROCOTOL.equals(url.getProtocol())) {
JarFile jarFile = ((JarURLConnection)url.openConnection()).getJarFile();
ZipEntry entry = jarFile.getEntry(name);
if(entry!=null) {
filter.accept(jarFile.getInputStream(entry));
}
}
}
}else {
log.info("没有扫描到任何东西!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (Throwable ex) {
}
if (cl == null) {
cl = ScanFile.class.getClassLoader();
if (cl == null) {
try {
cl = ClassLoader.getSystemClassLoader();
} catch (Throwable ex) {
}
}
}
return cl;
}
}

View File

@ -0,0 +1,15 @@
package com.pictc.utils;
import java.io.InputStream;
/**
* @Description TODO(这里用一句话描述这个类的作用)
* @author zhangfucai
* @Date 2023年1月8日 下午6:29:56
* @version 1.0.0
*/
public interface ScanFileFilter {
public void accept(InputStream in);
}

View File

@ -0,0 +1,114 @@
package com.pictc.utils;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class SetUtils {
public static enum SetType{
HashSet,TreeSet,LinkedHashSet,ConcurrentSkipListSet
}
public static SetType parseType(Class<?> cls) {
if(LinkedHashSet.class.equals(cls)) {
return SetType.LinkedHashSet;
}else if(TreeSet.class.equals(cls)) {
return SetType.TreeSet;
}else if(ConcurrentSkipListSet.class.equals(cls)) {
return SetType.ConcurrentSkipListSet;
}else {
return SetType.HashSet;
}
}
public static <T> Set<T> getMapNewInstance(SetType type) {
Set<T> result=null;
switch (type) {
case LinkedHashSet:
result=CollectionUtils.newLinkedHashSet();
break;
case TreeSet:
result=CollectionUtils.newTreeSet();
break;
case ConcurrentSkipListSet:
result=CollectionUtils.newConcurrentSet();
break;
default:
result=CollectionUtils.newHashSet();
break;
}
return result;
}
public static <T> Set<T> newInstance(Class<?> cls) {
return getMapNewInstance(parseType(cls));
}
@SafeVarargs
public static <T> Set<T> of(T... objs){
Set<T> result=null;
if(objs!=null && objs.length>0) {
result=CollectionUtils.newHashSet();
for (int i = 0; i < objs.length; i++) {
result.add(objs[i]);
}
}
return result;
}
public static <T> Set<T> ofArray(T[] objs){
Set<T> result=null;
if(objs!=null && objs.length>0) {
result=CollectionUtils.newHashSet();
for (int i = 0; i < objs.length; i++) {
result.add(objs[i]);
}
}
return result;
}
public static <T> Set<T> ofCollection(Collection<T> objs){
Set<T> result=null;
if(objs!=null) {
result=getMapNewInstance(SetType.HashSet);
Iterator<T> it=objs.iterator();
while (it.hasNext()) {
result.add(it.next());
}
}
return result;
}
public static <T, V, R> Set<V> ofCollection(Collection<T> collections,TFunction<V, R> fn) {
Set<V> set = CollectionUtils.newHashSet();
Field field = LambdaUtils.getField(fn);
for (T t : collections) {
V v = BeanUtils.getFieldValue(field, t);
set.add(v);
}
return set;
}
public static <T>T getFirst(Set<T> sets){
if(CollectionUtils.isNotEmpty(sets)) {
for (T t : sets) {
if(t!= null) {
return t;
}
}
}
return null;
}
}

View File

@ -0,0 +1,138 @@
package com.pictc.utils;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import com.pictc.cache.CacheFactory;
import com.pictc.cache.TanukiCache;
/**
* @Description TODO(这里用一句话描述这个类的作用)
* @author zhangfucai
* @Date 2022年11月6日 上午10:22:31
* @version 1.0.0
*/
@Component
public class SpringAnnotationUtils implements EnvironmentAware{
private static final TanukiCache<String,InvocationHandler> handlerCache= CacheFactory.factory("Invocation-cache");
private static final TanukiCache<String,Annotation> findCache = CacheFactory.factory("Annotation-cache");
private static final String findKeyFormat="%s@%s";
private static final String handlerKeyFormat="%s@%s";
private static Environment environment;
@SuppressWarnings("unchecked")
public static <A extends Annotation>A findAnnotation(Class<?> clazz,Class<A> annotationType){
if(!clazz.isAnnotationPresent(annotationType)) {
return null;
}
String key=String.format(findKeyFormat, clazz.getName(),annotationType.getName());
if(!findCache.containsKey(key)) {
findCache.save(key, resolveAnnotationEnvValue(clazz.getAnnotation(annotationType)));
}
return (A) findCache.get(key);
}
@SuppressWarnings("unchecked")
public static <A extends Annotation>A findAnnotation(AnnotatedElement element,Class<A> annotationType){
if(!element.isAnnotationPresent(annotationType)) {
return null;
}
String key=String.format(findKeyFormat,System.identityHashCode(element),annotationType.getName());
if(!findCache.containsKey(key)) {
findCache.save(key, resolveAnnotationEnvValue(element.getAnnotation(annotationType)));
}
return (A) findCache.get(key);
}
private static <A extends Annotation>A resolveAnnotationEnvValue(A annotation) {
Map<String, Object> values=AnnotationUtils.getAnnotationAttributes(annotation);
if(values!=null) {
Set<Entry<String, Object>> vs= values.entrySet();
for (Entry<String, Object> entry : vs) {
values.put(entry.getKey(),parseValue(entry.getValue()));
}
}
changeValues(annotation, values);
return annotation;
}
@SuppressWarnings("unchecked")
public static Map<String,Object> getValues(Annotation annotation){
String key=String.format(handlerKeyFormat,annotation.getClass().getName(),System.identityHashCode(annotation));
if(!handlerCache.containsKey(key)) {
handlerCache.save(key, Proxy.getInvocationHandler(annotation));
}
InvocationHandler invocationHandler =handlerCache.get(key);
try {
Field declaredField = invocationHandler.getClass().getDeclaredField("memberValues");
declaredField.setAccessible(true);
return (Map<String, Object>) declaredField.get(invocationHandler);
} catch (Exception e) {}
return null;
}
public static void changeValue(Annotation annotation,String name,Object value) {
Map<String, Object> values = getValues(annotation);
if(values!=null) {
values.put(name,value);
}
}
public static void changeValues(Annotation annotation,Map<String,Object> attrs) {
Map<String, Object> values = getValues(annotation);
if(values!=null) {
values.putAll(attrs);
}
}
private static Object parseValue(Object val) {
if(environment==null) {
return val;
}
if(val!=null && val instanceof String && RegexUtils.has(val.toString())) {
String strVal=val.toString();
List<String> names=RegexUtils.findPlaceholder(strVal);
String[] values=new String[names.size()];
for (int i = 0; i < values.length; i++) {
String key=names.get(i);
String[] keys=key.split(":");
if(keys.length==2) {
if(environment.containsProperty(keys[0])) {
values[i]=environment.getProperty(keys[0]);
}else {
values[i]=keys[1];
}
}else {
values[i] = environment.getProperty(key);
}
}
return RegexUtils.replacePlaceholder(strVal, values);
}
return val;
}
@Override
public void setEnvironment(Environment environment) {
SpringAnnotationUtils.environment=environment;
}
}

View File

@ -0,0 +1,176 @@
package com.pictc.utils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
/**
* @Description springbean 工具类型
* @author zhangfucai
* @Date 2023年6月29日 下午3:47:01
* @version 1.0.0
*/
public class SpringTools implements ApplicationContextAware,EnvironmentAware{
public static final String CONFIG_KEY_APPLICATION = "spring.application.name";
public static final String CONFIG_KEY_PROFILE = "spring.profiles.active";
public static final String CONFIG_PROD_VALUE = "prod";
private static ApplicationContext context;
private static Environment environment;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
SpringTools.context = context;
}
@Override
public void setEnvironment(Environment environment) {
SpringTools.environment = environment;
}
public static ConfigurableApplicationContext logStarter(Class<?> appClass,String[] args) {
long start = System.currentTimeMillis();
SpringApplicationBuilder builder = new SpringApplicationBuilder(appClass);
return logStarter(start, builder.headless(false).run(args));
}
public static ConfigurableApplicationContext logStarter(long start,ConfigurableApplicationContext context) {
ConfigurableEnvironment env = context.getEnvironment();
Integer _port = env.getProperty("server.port",int.class);
int port = _port==null?8080:_port.intValue();
String profile = env.getProperty(CONFIG_KEY_PROFILE,"dev");
Map<String,String> values = new HashMap<String, String>();
ServerProperties server = context.getBean(ServerProperties.class);
String path = getContextPath(server.getServlet().getContextPath());
String portPath = port==80?"":":"+port;
values.put("${serverName}", env.getProperty(CONFIG_KEY_APPLICATION));
values.put("${profiles}", profile);
values.put("${time}",String.valueOf((System.currentTimeMillis()-start)/1000));
values.put("${url}", "http://localhost"+portPath+path);
printBanner(values);
return context;
}
/**
* @param values
*/
private static void printBanner(Map<String, String> values) {
ScanFile.scan("t-banner.txt",new ScanFileFilter() {
private boolean ready = false;
@Override
public void accept(InputStream in) {
if(!ready) {
ready = true;
}else {
return;
}
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = reader.readLine()) != null) {
for (String key : values.keySet()) {
line = line.replace(key, values.get(key));
}
System.out.println(line);
}
} catch (Exception e) {
}finally {
IoUtils.closeQuietly(reader);
}
}
});
}
public static String getLocalIp() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
throw new RuntimeException("获取本地ip异常", e);
}
}
private static String getContextPath(String path) {
if(!StringUtils.isEmpty(path)) {
if(!path.startsWith("/")) {
path = "/"+path;
}
if(path.endsWith("/")) {
path = path.substring(0,path.length()-1);
}
return path;
}
return "";
}
public static <T>T getBean(Class<T> clazz){
return context.getBean(clazz);
}
@SuppressWarnings("unchecked")
public static <T>T getBean(String name){
if(context.containsBean(name)) {
return (T) context.getBean(name);
}
return null;
}
public static <T>Map<String, T> getBeansOfType(Class<T> clazz){
return context.getBeansOfType(clazz);
}
public static <T>List<T> getBeans(Class<T> clazz){
return getBeans(clazz, false);
}
public static <T>List<T> getBeans(Class<T> clazz,boolean sort){
List<T> beans = CollectionUtils.newArrayList();
Map<String, T> maps = getBeansOfType(clazz);
if(maps!=null && maps.isEmpty()==false) {
beans = new ArrayList<T>(maps.values());
if(sort) AnnotationAwareOrderComparator.sort(beans);
}
return beans;
}
public static <T>T getProperty(String key,Class<T> targetType,T defaultValue) {
return environment.getProperty(key, targetType, defaultValue);
}
public static <T>T getProperty(String key,Class<T> targetType) {
return environment.getProperty(key, targetType);
}
public static String getProperty(String key) {
return environment.getProperty(key);
}
}

View File

@ -0,0 +1,122 @@
package com.pictc.utils;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
public class StringUtils {
private StringUtils() {
super();
}
public static boolean isEmpty(String str) {
if(str==null || "".equals(str.trim())) {
return true;
}
return false;
}
public static boolean isNotEmpty(String str) {
return !isEmpty(str);
}
public static String parseBytes(byte[] data,Charset charset) {
return new String(data, charset);
}
public static String parseStream(InputStream in,Charset charset) throws IOException {
return parseStream(new InputStreamReader(in, charset));
}
public static String parseStream(Reader reader) throws IOException {
try {
StringBuilder source = new StringBuilder();
BufferedReader buffered = new BufferedReader(reader);
String line = buffered.readLine();
while (line != null) {
source.append(line);
source.append('\n');
line = buffered.readLine();
}
return source.toString();
} finally {
IoUtils.closeQuietly(reader);
}
}
public static byte[] toBytes(String str,Charset charset) {
if(str==null) {
return null;
}
return str.getBytes(charset);
}
public static InputStream toInputStream(String str,Charset charset) {
return new ByteArrayInputStream(toBytes(str,charset));
}
/**
* 将驼峰命名的字符串转为下划线
* */
public static String convertHump(String str) {
StringBuilder result=new StringBuilder();
char[] chars=str.toCharArray();
for (int i = 0; i < chars.length; i++) {
if(Character.isUpperCase(chars[i])) {
if(i>0) {
result.append('_');
}
result.append(Character.toLowerCase(chars[i]));
continue;
}
result.append(chars[i]);
}
return result.toString();
}
public static String excludeEmpty(String val,String defVal) {
if(isEmpty(val)) {
return defVal;
}
return val;
}
public static String format(String str,Object... args) {
if(str!=null && args !=null && args.length > 0) {
for (int i = 0; i < args.length; i++) {
Object item = args[i];
str = str.replace("{"+i+"}",item!=null?item.toString():"");
}
}
return str;
}
public static String opt(String val,String defVal) {
if(isEmpty(val)) {
return defVal;
}
return val;
}
public static boolean eq(String val,String secondVal) {
if(val==null && secondVal==null) {
return true;
}
if(val!=null) {
return val.equals(secondVal);
}
return secondVal.equals(val);
}
}

View File

@ -0,0 +1,15 @@
package com.pictc.utils;
import java.io.Serializable;
import java.util.function.Function;
/**
* 支持序列化的 Function
*
* @author miemie
* @since 2018-05-12
*/
@FunctionalInterface
public interface TFunction<T, R> extends Function<T, R>, Serializable {
}

View File

@ -0,0 +1,137 @@
package com.pictc.utils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.Getter;
/**
* @Description TODO(这里用一句话描述这个类的作用)
* @author zhangfucai
* @Date 2022年11月7日 下午11:30:00
* @version 1.0.0
*/
@Getter
public class TypeInfo {
private Type type;
private Class<?> klass;
private Type[] generics;
public TypeInfo(Type type) {
super();
this.type = type;
if(type instanceof Class) {
klass = (Class<?>)type;
List<Type> types = CollectionUtils.newArrayList();
addGenerics(types, klass.getGenericSuperclass());
Type[] itypes = klass.getGenericInterfaces();
if(itypes!=null) {
for (int i = 0; i < itypes.length; i++) {
addGenerics(types, itypes[i]);
}
}
generics = ArrayUtils.ofCollection(types);
}else if(type instanceof ParameterizedType) {
ParameterizedType gtype = ((ParameterizedType)type);
klass = (Class<?>) gtype.getRawType();
generics = gtype.getActualTypeArguments();
}
}
private void addGenerics(List<Type> types,Type stype) {
if(stype!=null && stype instanceof ParameterizedType) {
ParameterizedType gtype = ((ParameterizedType)stype);
Type[] sgs = gtype.getActualTypeArguments();
if(sgs!=null) {
for (Type _t : sgs) {
types.add(_t);
}
}
}
}
public static TypeInfo valueOf(Type type) {
return new TypeInfo(type);
}
public boolean isGenerics() {
return generics!=null;
}
public Type getGenericType(int index) {
if(!isGenerics()) {
throw new RuntimeException("不是泛型,无法获取泛型类型");
}
return generics[index];
}
public Type getCollectionType() {
if(!isGenerics()) {
throw new RuntimeException("不是泛型,无法获取泛型类型");
}
return generics[0];
}
public boolean isArray() {
return klass.isArray();
}
public boolean isInterface() {
return klass.isInterface();
}
public boolean isPrimitive() {
return ClassUtils.isPrimitive(klass);
}
public boolean isEnum() {
return klass.isEnum();
}
public boolean isCollection() {
return ClassUtils.isCollection(klass);
}
public boolean isList() {
return ClassUtils.isList(klass);
}
public boolean isSet() {
return ClassUtils.isSet(klass);
}
public boolean isMap() {
return ClassUtils.isMap(klass);
}
public Class<?> getArrayType(){
return klass.getComponentType();
}
public <T>Collection<T> newCollection(){
return isList()?newList():newSet();
}
public <T>List<T> newList(){
return ListUtils.getMapNewInstance(ListUtils.parseType(klass));
}
public <T>Set<T> newSet(){
return SetUtils.getMapNewInstance(SetUtils.parseType(klass));
}
public <K,V>Map<K,V> newMap(){
return MapUtils.getMapNewInstance(MapUtils.parseMapType(klass));
}
public String toString() {
return String.format("Class:[%s],泛型:%s", klass.getName(),Arrays.toString(generics));
}
}

View File

@ -0,0 +1,30 @@
package com.xjrsoft.common;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.pictc.utils.DataLogTools;
@Service
public class CommonEnhancedService {
@Transactional(rollbackFor = Exception.class)
public <T>T insert(T entity) {
return DataLogTools.insert(entity);
}
public <T>T updateById(T entity) {
return DataLogTools.update(entity);
}
public <T>T delete(T entity) {
return DataLogTools.delete(entity);
}
public <T>T deleteById(Class<T> klazz,long id) {
return DataLogTools.deleteById(klazz, id);
}
}

View File

@ -0,0 +1,120 @@
package com.xjrsoft.module.datalog.entity;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import com.baomidou.mybatisplus.annotation.TableField;
import com.pictc.common.mybatis.JsonTypeHandler;
import com.xjrsoft.module.datalog.entity.json.FieldChange;
import com.xjrsoft.module.datalog.vo.OperationType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 数据变更日志实体类
* 用于记录数据库字段修改和实体删除操作
*/
@ApiModel(value = "DataChangeLog对象", description = "数据变更日志")
@Data
@Accessors(chain = true)
public class DataChangeLog implements Serializable{
/**
* @Fields {todo}(用一句话描述这个变量表示什么)
*/
private static final long serialVersionUID = 1L;
/**
* 日志ID主键
*/
@ApiModelProperty("主键")
private String id;
/**
* 日志ID主键
*/
@ApiModelProperty("流水id")
private String flowId;
/**
* 父表ID,根节点#
*/
@ApiModelProperty("父表ID")
private String pid = "#";
/**
* 实体类名称(全类名)
*/
@ApiModelProperty("实体类名称(全类名)")
private String entityClassName;
/**
* 实体类简称(简单类名)
*/
@ApiModelProperty("业务名称")
private String busName;
/**
* 操作的实体ID主键值
*/
@ApiModelProperty("操作的实体ID主键值")
private Long entityId;
/**
* 字段变更详情
* key: 字段名
* value: 包含旧值和新值的Map
*/
@TableField(typeHandler = JsonTypeHandler.class)
@ApiModelProperty("属性值记录")
private List<FieldChange> fieldChanges = new ArrayList<FieldChange>();
/**
* 操作类型INSERT-新增UPDATE-修改DELETE-删除
*/
@ApiModelProperty("操作类型INSERT-新增UPDATE-修改DELETE-删除")
private OperationType operationType;
/**
* 操作人ID
*/
@ApiModelProperty("操作人ID")
private Long operatorId;
/**
* 操作人姓名
*/
@ApiModelProperty("操作人姓名")
private String operatorName;
/**
* 操作时间
*/
@ApiModelProperty("操作时间")
private LocalDateTime operationTime;
/**
* 操作IP地址
*/
@ApiModelProperty("操作IP地址")
private String operationIp;
/**
* 判断是否有字段变更
*/
public boolean hasFieldChanges() {
return !this.fieldChanges.isEmpty();
}
public void addFiledChnage(FieldChange change) {
fieldChanges.add(change);
}
}

View File

@ -0,0 +1,39 @@
package com.xjrsoft.module.datalog.entity.json;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
@ApiModel(value = "FieldChange对象", description = "数据变更字段记录")
@Data
@Accessors(chain = true)
public class FieldChange implements Serializable{
private static final long serialVersionUID = 1L;
@ApiModelProperty("属性名称")
private String name;
@ApiModelProperty("属性")
private String field;
/**
* 旧值
*/
@ApiModelProperty("旧值")
private String oldValue;
/**
* 新值
*/
@ApiModelProperty("新值")
private String newValue;
}

View File

@ -0,0 +1,25 @@
package com.xjrsoft.module.datalog.service;
import java.util.List;
import javax.validation.Valid;
import com.xjrsoft.module.datalog.entity.DataChangeLog;
public interface DatalogService {
public <T>T insert(T entity);
public <T>List<T> insertBatch(List<T> entity);
public <T>boolean updateById(T entity);
public <T>T delete(T entity);
public <T>T deleteById(Class<T> klazz,long id);
public <T>List<DataChangeLog> findByEntityId(Class<T> klazz,long id);
public <T>boolean deleteByIds(Class<T> class1, @Valid List<Long> ids);
}

View File

@ -0,0 +1,18 @@
package com.xjrsoft.module.datalog.service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.pictc.jdbc.model.ParamQueryBo;
import com.pictc.jdbc.model.QueryParameter;
public interface QueryService {
public JSONArray queryList(QueryParameter param);
public IPage<JSONObject> queryPage(QueryParameter param);
public JSONArray queryParamsList(ParamQueryBo param);
}

View File

@ -0,0 +1,69 @@
package com.xjrsoft.module.datalog.service.impl;
import java.util.List;
import javax.validation.Valid;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.google.api.client.util.Lists;
import com.pictc.utils.DataLogTools;
import com.xjrsoft.module.datalog.entity.DataChangeLog;
import com.xjrsoft.module.datalog.service.DatalogService;
@Service
public class DatalogServiceImpl implements DatalogService{
@Transactional(rollbackFor = Exception.class)
@Override
public <T> T insert(T entity) {
return DataLogTools.insert(entity);
}
@Transactional(rollbackFor = Exception.class)
@Override
public <T> List<T> insertBatch(List<T> entitys) {
List<T> res = Lists.newArrayList();
for (T entity : entitys) {
res.add(DataLogTools.insert(entity));
}
return res;
}
@Transactional(rollbackFor = Exception.class)
@Override
public <T> boolean updateById(T entity) {
DataLogTools.update(entity);
return true;
}
@Transactional(rollbackFor = Exception.class)
@Override
public <T> T delete(T entity) {
return DataLogTools.delete(entity);
}
@Transactional(rollbackFor = Exception.class)
@Override
public <T> T deleteById(Class<T> klazz, long id) {
return DataLogTools.deleteById(klazz, id);
}
@Transactional(rollbackFor = Exception.class)
@Override
public <T> boolean deleteByIds(Class<T> class1, @Valid List<Long> ids) {
return DataLogTools.deleteByIds(class1, ids);
}
@Transactional(readOnly = true)
@Override
public <T> List<DataChangeLog> findByEntityId(Class<T> klazz, long dataId) {
return DataLogTools.findLogsByEntityId(klazz, dataId);
}
}

View File

@ -0,0 +1,62 @@
package com.xjrsoft.module.datalog.service.impl;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.pictc.jdbc.JdbcTools;
import com.pictc.jdbc.SqlBuilder;
import com.pictc.jdbc.model.JdbcParam;
import com.pictc.jdbc.model.ParamItem;
import com.pictc.jdbc.model.ParamQueryBo;
import com.pictc.jdbc.model.QueryParameter;
import com.pictc.utils.ListUtils;
import com.xjrsoft.module.datalog.service.QueryService;
@Service
public class QueryServiceImpl implements QueryService{
public static final String SQL_FIND_SQL = "select sql from lng_sql_rpt where id = ?";
public String getQuerySql(String queryId) {
String sql= JdbcTools.queryPrimitive(SQL_FIND_SQL,String.class,ListUtils.ofArray(JdbcParam.of(Types.VARCHAR, String.class, queryId)));
if(sql.contains("call")) {
return sql;
}
return "SELECT * FROM ("+sql+") t";
}
@Transactional(rollbackFor = Exception.class)
@Override
public JSONArray queryList(QueryParameter param) {
return JdbcTools.query(getQuerySql(param.getQueryId()),param);
}
@Transactional(rollbackFor = Exception.class)
@Override
public IPage<JSONObject> queryPage(QueryParameter param) {
return JdbcTools.queryPage(getQuerySql(param.getQueryId()), param);
}
@Transactional(rollbackFor = Exception.class)
@Override
public JSONArray queryParamsList(ParamQueryBo param) {
SqlBuilder sql = new SqlBuilder();
sql.append(getQuerySql(param.getQueryId()));
List<ParamItem> params2 = param.getParams();
List<JdbcParam> params = new ArrayList<JdbcParam>();
if(params2!=null && !params2.isEmpty()) {
for (ParamItem item : params2) {
params.add(item.toParam());
}
}
return JdbcTools.queryArray(sql.toString(), params);
}
}

View File

@ -0,0 +1,4 @@
# src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pictc.config.PcitcAutoConfig,\
com.pictc.config.JdbcConfig

View File

@ -0,0 +1 @@
component=com.pictc

View File

@ -0,0 +1,9 @@
███████ ██████ ██ ██████████ ██████
░██░░░░██ ██░░░░██░██░░░░░██░░░ ██░░░░██
░██ ░██ ██ ░░ ░██ ░██ ██ ░░ 服务名称:${serverName}
░███████ ░██ ░██ ░██ ░██ 启动环境:${profiles}
░██░░░░ ░██ ░██ ░██ ░██ 启动耗时:${time}s
░██ ░░██ ██░██ ░██ ░░██ ██ 访问地址:${url}
░██ ░░██████ ░██ ░██ ░░██████
░░ ░░░░░░ ░░ ░░ ░░░░░░