├── src ├── main │ └── java │ │ └── com │ │ └── gysoft │ │ └── jdbc │ │ ├── bean │ │ ├── Opt.java │ │ ├── Criteria.java │ │ ├── SQLType.java │ │ ├── TableEnum.java │ │ ├── JoinType.java │ │ ├── ValueReference.java │ │ ├── FieldReference.java │ │ ├── GyjdbcException.java │ │ ├── Drunk.java │ │ ├── SQLInterceptor.java │ │ ├── Pair.java │ │ ├── Page.java │ │ ├── PageResult.java │ │ ├── Sort.java │ │ ├── CriteriaProxy.java │ │ ├── SQLPiepline.java │ │ ├── Index.java │ │ ├── IndexMeta.java │ │ ├── TypeFunction.java │ │ ├── SQLTree.java │ │ ├── Result.java │ │ ├── Table.java │ │ ├── ColumnMeta.java │ │ ├── Where.java │ │ ├── TableMeta.java │ │ ├── WhereParam.java │ │ ├── SqlModifier.java │ │ ├── Joins.java │ │ ├── Column.java │ │ ├── AuxiliaryOperation.java │ │ ├── AbstractCriteria.java │ │ └── SQL.java │ │ ├── multi │ │ ├── balance │ │ │ ├── SelectFirstLoadBalance.java │ │ │ ├── SelectLastLoadBalance.java │ │ │ ├── LoadBalance.java │ │ │ ├── RandomLoadBalance.java │ │ │ ├── RoundRobinLoadBalance.java │ │ │ ├── AbstractLoadBalance.java │ │ │ └── LeastActiveLoadBalance.java │ │ ├── BindPoint.java │ │ ├── BindPointAspectRegistar.java │ │ ├── JdbcRoutingDataSource.java │ │ ├── BindPointAspect.java │ │ ├── AtomicPositiveInteger.java │ │ ├── DataSourceBindHolder.java │ │ └── DataSourceBind.java │ │ ├── annotation │ │ ├── Column.java │ │ └── Table.java │ │ ├── tools │ │ ├── CollectionUtil.java │ │ ├── CustomResultSetExractorFactory.java │ │ └── EntityTools.java │ │ └── dao │ │ ├── ISpringJdbc.java │ │ ├── EntityDao.java │ │ └── SpringJdbc.java └── test │ └── java │ └── com │ └── gysoft │ └── jdbc │ ├── Role.java │ └── Token.java ├── .gitignore ├── pom.xml ├── LICENSE └── README.md /src/main/java/com/gysoft/jdbc/bean/Opt.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | /** 4 | * @author zhouning 5 | */ 6 | public enum Opt { 7 | AND,OR; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Criteria.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | /** 4 | * mysql查询条件封装 5 | * @author 周宁 6 | */ 7 | public class Criteria extends AbstractCriteria { 8 | 9 | } -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/SQLType.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | /** 4 | * @author zhouning 5 | */ 6 | public enum SQLType { 7 | Select, Update, Insert, Delete,Create, Truncate, Drop; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/TableEnum.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | /** 4 | * @author 周宁 5 | */ 6 | public class TableEnum { 7 | 8 | public enum Engine { 9 | InnoDB, MyISAM, MEMORY; 10 | } 11 | 12 | public enum RowFormat { 13 | DYNAMIC, COMPRESSED, FIXED; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/balance/SelectFirstLoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi.balance; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author zhouning 7 | */ 8 | public class SelectFirstLoadBalance extends AbstractLoadBalance{ 9 | @Override 10 | protected String doSelect(List keys, String group) { 11 | return keys.get(0); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/balance/SelectLastLoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi.balance; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author zhouning 7 | */ 8 | public class SelectLastLoadBalance extends AbstractLoadBalance { 9 | @Override 10 | protected String doSelect(List keys, String group) { 11 | return keys.get(keys.size() - 1); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/balance/LoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi.balance; 2 | 3 | import com.gysoft.jdbc.multi.DataSourceBind; 4 | 5 | /** 6 | * 负载均衡策略接口 7 | * 8 | * @author 周宁 9 | */ 10 | public interface LoadBalance { 11 | /** 12 | * 选择一个数据源 13 | * 14 | * @param dataSourceBind 数据源绑定参数 15 | * @return String 数据源的key 16 | */ 17 | String select(DataSourceBind dataSourceBind); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/JoinType.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | /** 4 | * @author 周宁 5 | */ 6 | public enum JoinType { 7 | LeftJoin("LEFT JOIN"), 8 | RightJoin("RIGHT JOIN"), 9 | InnerJoin("INNER JOIN"), 10 | NatureJoin(","); 11 | 12 | private final String type; 13 | 14 | JoinType(String type) { 15 | this.type = type; 16 | } 17 | 18 | public String getType() { 19 | return type; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/balance/RandomLoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi.balance; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.ThreadLocalRandom; 5 | 6 | /** 7 | * @author 周宁 8 | */ 9 | public class RandomLoadBalance extends AbstractLoadBalance { 10 | 11 | @Override 12 | protected String doSelect(List keys, String group) { 13 | int length = keys.size(); 14 | return keys.get(ThreadLocalRandom.current().nextInt(length)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | disconf.properties 12 | 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | 20 | # Package Files # 21 | *.jar 22 | *.war 23 | *.ear 24 | 25 | *.classpath 26 | !/.project 27 | .project 28 | *.settings 29 | target/ 30 | .idea/ 31 | .DS_Store 32 | .idea 33 | overlays/ 34 | .gradle/ 35 | build/ 36 | bin/ 37 | *.iml 38 | *.log 39 | *.log.gz 40 | out/ 41 | MANIFEST.MF 42 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/ValueReference.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | /** 4 | * @author 周宁 5 | */ 6 | public class ValueReference { 7 | 8 | private Object value; 9 | 10 | public Object getValue() { 11 | return value; 12 | } 13 | 14 | public void setValue(Object value) { 15 | this.value = value; 16 | } 17 | 18 | public ValueReference(Object value) { 19 | this.value = value; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return "ValueReference(" + value + ")"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/annotation/Column.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | import java.util.Date; 6 | 7 | import static java.lang.annotation.ElementType.FIELD; 8 | import static java.lang.annotation.ElementType.METHOD; 9 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 10 | 11 | /** 12 | * 字段名及相关属性信息 13 | * @author 彭佳佳 14 | */ 15 | @Target({METHOD, FIELD}) 16 | @Retention(RUNTIME) 17 | public @interface Column { 18 | 19 | /** 20 | * 字段名称 21 | * @return String 22 | */ 23 | String name() default ""; 24 | } -------------------------------------------------------------------------------- /src/test/java/com/gysoft/jdbc/Role.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc; 2 | 3 | import com.gysoft.jdbc.annotation.Table; 4 | 5 | /** 6 | * @author 周宁 7 | * @Date 2019-01-04 11:18 8 | */ 9 | @Table(name = "tb_role") 10 | public class Role { 11 | 12 | private String name; 13 | 14 | private String auths; 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public String getAuths() { 25 | return auths; 26 | } 27 | 28 | public void setAuths(String auths) { 29 | this.auths = auths; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/FieldReference.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | /** 4 | * 代表字段的引用 5 | * 6 | * @author 周宁 7 | */ 8 | public class FieldReference { 9 | /** 10 | * 字段 11 | */ 12 | private String field; 13 | 14 | public FieldReference(String field) { 15 | this.field = field; 16 | } 17 | 18 | public String getField() { 19 | return field; 20 | } 21 | 22 | public void setField(String field) { 23 | this.field = field; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "FieldReference(" + field + ")"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/annotation/Table.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.Target; 6 | 7 | import static java.lang.annotation.ElementType.TYPE; 8 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 9 | 10 | /** 11 | * 实体映射表自定义注解 12 | * @author 彭佳佳 13 | */ 14 | @Documented 15 | @Target(TYPE) 16 | @Retention(RUNTIME) 17 | public @interface Table { 18 | /** 19 | * 表名称 20 | * @return String 21 | */ 22 | String name() default ""; 23 | 24 | /** 25 | * 主键字段 26 | * @return String 27 | */ 28 | String pk() default "id"; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/GyjdbcException.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | /** 4 | * 异常类 5 | * @author 周宁 6 | */ 7 | public class GyjdbcException extends RuntimeException{ 8 | 9 | public GyjdbcException() { 10 | super(); 11 | } 12 | 13 | public GyjdbcException(String message) { 14 | super(message); 15 | } 16 | 17 | public GyjdbcException(String message, Throwable cause) { 18 | super(message, cause); 19 | } 20 | 21 | public GyjdbcException(Throwable cause) { 22 | super(cause); 23 | } 24 | 25 | protected GyjdbcException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 26 | super(message, cause, enableSuppression, writableStackTrace); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Drunk.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * Drunk形容一个人喝醉了,犯糊涂了然后清楚表数据或者删除表 8 | * @author 周宁 9 | */ 10 | public class Drunk { 11 | /** 12 | * 表名称集合 13 | */ 14 | private Set tables; 15 | /** 16 | * 是否管exists 17 | */ 18 | private boolean ifExists; 19 | 20 | public Drunk(){ 21 | tables = new HashSet<>(); 22 | } 23 | 24 | public Set getTables() { 25 | return tables; 26 | } 27 | 28 | public void setTables(Set tables) { 29 | this.tables = tables; 30 | } 31 | 32 | public boolean isIfExists() { 33 | return ifExists; 34 | } 35 | 36 | public void setIfExists(boolean ifExists) { 37 | this.ifExists = ifExists; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/SQLInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | /** 4 | * 用于在构建sql、参数数组钱执行相应逻辑, 5 | * 可用于添加统一的条件、强制更新时间戳、记录sql等, 6 | * 7 | * @author zhouning 8 | */ 9 | public interface SQLInterceptor { 10 | /** 11 | * 在真正构建sql和参数之前执行,该方法会影响最终的sql和参数 12 | * 该方法仅对entityDao.xxxSql()方法有效 13 | * 14 | * @param sqlModifier sql修改器 15 | * @throws Exception sql错误抛出异常 16 | * @author ZhouNing 17 | **/ 18 | void beforeBuild(SQLType sqlType, SqlModifier sqlModifier) throws Exception; 19 | 20 | /** 21 | * 成功构建sql和参数后执行,该方法执行不能够影响sql 22 | * 23 | * @param sql 真正的sql字符串 24 | * @param args sql入参数组 25 | * @throws Exception sql错误抛出异常 26 | * @author ZhouNing 27 | **/ 28 | void afterBuild(String sql, Object[] args) throws Exception; 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Pair.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 包装两个对象关系 7 | * 8 | * @author 周宁 9 | */ 10 | public class Pair implements Serializable { 11 | /** 12 | * 第一个属性(一般为key) 13 | */ 14 | private F first; 15 | /** 16 | * 第二个属性(一般为value) 17 | */ 18 | private S second; 19 | 20 | public F getFirst() { 21 | return first; 22 | } 23 | 24 | public void setFirst(F first) { 25 | this.first = first; 26 | } 27 | 28 | public S getSecond() { 29 | return second; 30 | } 31 | 32 | public void setSecond(S second) { 33 | this.second = second; 34 | } 35 | 36 | public Pair() { 37 | } 38 | 39 | public Pair(F first, S second) { 40 | this.first = first; 41 | this.second = second; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/BindPoint.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi; 2 | 3 | import com.gysoft.jdbc.multi.balance.LoadBalance; 4 | import com.gysoft.jdbc.multi.balance.RoundRobinLoadBalance; 5 | import org.springframework.context.annotation.Import; 6 | 7 | import java.lang.annotation.*; 8 | 9 | /** 10 | * 数据源绑定注解 11 | * 12 | * @author 周宁 13 | */ 14 | @Target({ElementType.METHOD, ElementType.TYPE}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | @Import(BindPointAspectRegistar.class) 18 | public @interface BindPoint { 19 | /** 20 | * @return String 数据源key 21 | */ 22 | String key() default ""; 23 | 24 | /** 25 | * @return String 数据源组 26 | */ 27 | String group() default ""; 28 | 29 | /** 30 | * @return Class 负载均衡策略class 31 | */ 32 | Class loadBalance() default RoundRobinLoadBalance.class; 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/gysoft/jdbc/Token.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc; 2 | 3 | import com.gysoft.jdbc.annotation.Column; 4 | import com.gysoft.jdbc.annotation.Table; 5 | import com.gysoft.jdbc.tools.SqlMakeTools; 6 | 7 | /** 8 | * @author 周宁 9 | * @Date 2019-01-04 15:51 10 | */ 11 | @Table(name = "tb_token") 12 | public class Token { 13 | private Integer id; 14 | 15 | private Integer size; 16 | @Column(name = "ddd") 17 | private String tk; 18 | 19 | public Integer getId() { 20 | return id; 21 | } 22 | 23 | public void setId(Integer id) { 24 | this.id = id; 25 | } 26 | 27 | public Integer getSize() { 28 | return size; 29 | } 30 | 31 | public void setSize(Integer size) { 32 | this.size = size; 33 | } 34 | 35 | public String getTk() { 36 | return tk; 37 | } 38 | 39 | public void setTk(String tk) { 40 | this.tk = tk; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/balance/RoundRobinLoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi.balance; 2 | 3 | 4 | import com.gysoft.jdbc.multi.AtomicPositiveInteger; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | /** 11 | * @author 周宁 12 | */ 13 | public class RoundRobinLoadBalance extends AbstractLoadBalance { 14 | 15 | private Map sequences = new ConcurrentHashMap<>(); 16 | 17 | @Override 18 | protected String doSelect(List keys, String group) { 19 | AtomicPositiveInteger sequence = sequences.get(group); 20 | if (sequence == null) { 21 | sequences.putIfAbsent(group, new AtomicPositiveInteger()); 22 | sequence = sequences.get(group); 23 | } 24 | int currentSequence = sequence.getAndIncrement(); 25 | return keys.get(currentSequence % keys.size()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/BindPointAspectRegistar.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi; 2 | 3 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 4 | import org.springframework.beans.factory.support.RootBeanDefinition; 5 | import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; 6 | import org.springframework.core.type.AnnotationMetadata; 7 | 8 | /** 9 | * @author 周宁 10 | */ 11 | public class BindPointAspectRegistar implements ImportBeanDefinitionRegistrar { 12 | /** 13 | * 是否已经初始化 14 | */ 15 | private static boolean inited; 16 | 17 | @Override 18 | public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { 19 | if (!inited) { 20 | RootBeanDefinition root = new RootBeanDefinition(); 21 | root.setBeanClass(BindPointAspect.class); 22 | registry.registerBeanDefinition(BindPointAspect.class.getName(), root); 23 | inited = true; 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Page.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | 4 | import java.io.Serializable; 5 | 6 | /** 7 | * @author 周宁 8 | */ 9 | public class Page implements Serializable { 10 | /** 11 | * 当前页 12 | */ 13 | private int currentPage; 14 | /** 15 | * 每页记录数 16 | */ 17 | private int pageSize; 18 | 19 | public int getOffset() { 20 | //当前页数小于0 21 | if (currentPage < 1) { 22 | return 0; 23 | } 24 | return (this.currentPage - 1) * this.pageSize; 25 | } 26 | 27 | public Page() { 28 | 29 | } 30 | 31 | public Page(int currentPage, int pageSize) { 32 | this.currentPage = currentPage; 33 | this.pageSize = pageSize; 34 | } 35 | 36 | public int getCurrentPage() { 37 | return currentPage; 38 | } 39 | 40 | public void setCurrentPage(int currentPage) { 41 | this.currentPage = currentPage; 42 | } 43 | 44 | public int getPageSize() { 45 | return pageSize; 46 | } 47 | 48 | public void setPageSize(int pageSize) { 49 | this.pageSize = pageSize; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/JdbcRoutingDataSource.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi; 2 | 3 | import com.gysoft.jdbc.multi.balance.AbstractLoadBalance; 4 | import org.apache.commons.lang.StringUtils; 5 | import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * @author 周宁 11 | */ 12 | public class JdbcRoutingDataSource extends AbstractRoutingDataSource { 13 | /** 14 | * 默认的数据源key;如果你的dao没有调用任何bind***()方法 15 | * 或者在对应的方法上没有使用类似@BindPoint("slave")注解 16 | * 则该值会很有用,他会帮我们应用一个全局的数据源key 17 | */ 18 | private String defaultLookUpKey; 19 | 20 | public void setDataSourceKeysGroup(Map dataSourceKeysGroup) { 21 | AbstractLoadBalance.initDataSourceKeysGroup(dataSourceKeysGroup); 22 | } 23 | 24 | public void setDefaultLookUpKey(String defaultLookUpKey) { 25 | this.defaultLookUpKey = defaultLookUpKey; 26 | } 27 | 28 | @Override 29 | protected Object determineCurrentLookupKey() { 30 | String lookUpKey = DataSourceBindHolder.getDataSource(); 31 | if(StringUtils.isEmpty(lookUpKey)){ 32 | lookUpKey = defaultLookUpKey; 33 | } 34 | return lookUpKey; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/PageResult.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | 4 | import java.io.Serializable; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | /** 9 | * 分页返回通用类 10 | * 11 | * @author 彭佳佳 12 | * @param 結果類型 13 | */ 14 | public class PageResult implements Serializable { 15 | /** 16 | * 总数量 17 | */ 18 | private Integer total; 19 | /** 20 | * 返回对象类型列表 21 | */ 22 | private List list; 23 | 24 | public PageResult() { 25 | 26 | } 27 | 28 | public PageResult(List list, Integer total) { 29 | this.total = total; 30 | this.list = list; 31 | } 32 | 33 | /** 34 | * 创建一个空的分页结果集 35 | * @author 周宁 36 | * @return PageResult 37 | * @version 1.0 38 | */ 39 | public static PageResult emptyPageResult(){ 40 | return new PageResult(Collections.EMPTY_LIST,0); 41 | } 42 | 43 | public Integer getTotal() { 44 | return total; 45 | } 46 | 47 | public void setTotal(Integer total) { 48 | this.total = total; 49 | } 50 | 51 | public List getList() { 52 | return list; 53 | } 54 | 55 | public void setList(List list) { 56 | this.list = list; 57 | } 58 | 59 | @Override 60 | public String toString() { 61 | return "PageResult{" + 62 | "total=" + total + 63 | ", list=" + list + 64 | '}'; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Sort.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author 周宁 7 | */ 8 | public class Sort implements Serializable { 9 | 10 | /** 11 | * 排序字段 12 | */ 13 | private String sortField; 14 | /** 15 | * 排序类型(DESC降序,ASC升序) 16 | */ 17 | private String sortType = "DESC"; 18 | 19 | public Sort(String sortField) { 20 | this.sortField = sortField; 21 | } 22 | 23 | public Sort(TypeFunction function) { 24 | this.sortField = TypeFunction.getLambdaColumnName(function); 25 | } 26 | 27 | public Sort(String sortField, String sortType) { 28 | this.sortField = sortField; 29 | this.sortType = sortType; 30 | } 31 | 32 | public Sort(TypeFunction function, String sortType) { 33 | this.sortField = TypeFunction.getLambdaColumnName(function); 34 | this.sortType = sortType; 35 | } 36 | 37 | public String getSortField() { 38 | return sortField; 39 | } 40 | 41 | public void setSortField(String sortField) { 42 | this.sortField = sortField; 43 | } 44 | 45 | public String getSortType() { 46 | return sortType; 47 | } 48 | 49 | public void setSortType(String sortType) { 50 | this.sortType = sortType; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/balance/AbstractLoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi.balance; 2 | 3 | import com.gysoft.jdbc.multi.DataSourceBind; 4 | import org.apache.commons.lang.StringUtils; 5 | 6 | import java.util.Arrays; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | 12 | /** 13 | * 负载均衡抽象策略实现类 14 | * @author 周宁 15 | */ 16 | public abstract class AbstractLoadBalance implements LoadBalance { 17 | 18 | private static Map dataSourceKeysGroup = new HashMap<>(); 19 | 20 | @Override 21 | public String select(DataSourceBind dataSourceBind) { 22 | String group = dataSourceBind.getGroup(); 23 | if (StringUtils.isEmpty(group)) { 24 | return null; 25 | } 26 | String keys = dataSourceKeysGroup.get(group); 27 | if (StringUtils.isNotEmpty(keys)) { 28 | List list = Arrays.asList(keys.split(",")); 29 | if (list.size() == 1) { 30 | return list.get(0); 31 | } 32 | return doSelect(list,group); 33 | } 34 | return null; 35 | } 36 | 37 | protected abstract String doSelect(List keys,String group); 38 | 39 | public static void initDataSourceKeysGroup(Map group) { 40 | dataSourceKeysGroup.putAll(group); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/CriteriaProxy.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | /** 4 | * 代理拼接处更复杂的sql 5 | * 6 | * @author 周宁 7 | */ 8 | public class CriteriaProxy { 9 | /** 10 | * 插入到Set中的位置 11 | */ 12 | private int whereParamsIndex = 0; 13 | /** 14 | * andCriteria或者orCriteria的sql拼接 15 | */ 16 | private StringBuilder sql; 17 | /** 18 | * 保存andCriteria或者orCriteria条件的入参 19 | */ 20 | private Object[] params; 21 | /** 22 | * and或者or、with 23 | */ 24 | private String criteriaType; 25 | 26 | 27 | public StringBuilder getSql() { 28 | return sql; 29 | } 30 | 31 | public void setSql(StringBuilder sql) { 32 | this.sql = sql; 33 | } 34 | 35 | public Object[] getParams() { 36 | return params; 37 | } 38 | 39 | public void setParams(Object[] params) { 40 | this.params = params; 41 | } 42 | 43 | public int getWhereParamsIndex() { 44 | return whereParamsIndex; 45 | } 46 | 47 | public void setWhereParamsIndex(int whereParamsIndex) { 48 | this.whereParamsIndex = whereParamsIndex; 49 | } 50 | 51 | public String getCriteriaType() { 52 | return criteriaType; 53 | } 54 | 55 | public void setCriteriaType(String criteriaType) { 56 | this.criteriaType = criteriaType; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/tools/CollectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.tools; 2 | 3 | import com.gysoft.jdbc.bean.GyjdbcException; 4 | import org.apache.commons.collections.CollectionUtils; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author 周宁 11 | */ 12 | public class CollectionUtil { 13 | 14 | 15 | /** 16 | * 将集合切片,切片后的每个集合大小为size 17 | * @param size 切片大小 18 | * @param c 待切片集合 19 | * @param 集合存放元素类型 20 | * @return List[] 切片后的集合数组 21 | */ 22 | public static List[] slice(List c, int size) { 23 | if (size < 1) { 24 | throw new GyjdbcException("无效的size:" + size); 25 | } 26 | if (CollectionUtils.isEmpty(c)) { 27 | return new List[0]; 28 | } 29 | int cSize = c.size(); 30 | int sliceNum = cSize % size == 0 ? cSize / size : cSize / size + 1; 31 | List[] result = new ArrayList[sliceNum]; 32 | for (int i = 0; i < sliceNum; i++) { 33 | int startIdx = size * i; 34 | int endIdx = size * (i + 1) > cSize ? cSize : size * (i + 1); 35 | List l = new ArrayList<>(); 36 | for (int j = startIdx; j < endIdx; j++) { 37 | l.add(c.get(j)); 38 | } 39 | result[i] = l; 40 | } 41 | return result; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/SQLPiepline.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author 周宁 8 | */ 9 | public class SQLPiepline { 10 | 11 | private List sqlNexts = new ArrayList<>(); 12 | private SQL head; 13 | 14 | SQL getHead() { 15 | return head; 16 | } 17 | 18 | public SQLPiepline(SQL head) { 19 | this.head = head; 20 | sqlNexts.add(new SQLNext(head, null)); 21 | } 22 | 23 | public void add(SQL sql, String type) { 24 | sqlNexts.add(new SQLNext(sql, type)); 25 | } 26 | 27 | public List getSqlNexts() { 28 | return sqlNexts; 29 | } 30 | 31 | public static class SQLNext { 32 | 33 | private SQL sql; 34 | 35 | private String unionType; 36 | 37 | public SQL getSql() { 38 | return sql; 39 | } 40 | 41 | public SQLNext(SQL sql, String unionType) { 42 | this.sql = sql; 43 | this.unionType = unionType; 44 | } 45 | 46 | public void setSql(SQL sql) { 47 | this.sql = sql; 48 | } 49 | 50 | public String getUnionType() { 51 | return unionType; 52 | } 53 | 54 | public void setUnionType(String unionType) { 55 | this.unionType = unionType; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Index.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.Collectors; 5 | 6 | /** 7 | * @author 周宁 8 | */ 9 | public class Index { 10 | /** 11 | * 表 12 | */ 13 | private final Table table; 14 | /** 15 | * 索引元数据 16 | */ 17 | private IndexMeta indexMeta; 18 | 19 | public Index(Table table) { 20 | this.table = table; 21 | indexMeta = new IndexMeta(); 22 | } 23 | 24 | public Index name(String indexName) { 25 | this.indexMeta.setIndexName(indexName); 26 | return this; 27 | } 28 | 29 | public Index unique() { 30 | this.indexMeta.setUnique(true); 31 | return this; 32 | } 33 | 34 | public Index column(String... columns) { 35 | this.indexMeta.getColumnNames().addAll(Arrays.stream(columns).collect(Collectors.toList())); 36 | return this; 37 | } 38 | 39 | public Index usingBtree(){ 40 | this.indexMeta.setIndexType("USING BTREE"); 41 | return this; 42 | } 43 | 44 | public Index usingHash(){ 45 | this.indexMeta.setIndexType("USING HASH"); 46 | return this; 47 | } 48 | 49 | public Index comment(String comment){ 50 | this.indexMeta.setComment(comment); 51 | return this; 52 | } 53 | 54 | public Table commit() { 55 | table.getTableMeta().getIndexs().add(this.indexMeta); 56 | return table; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/IndexMeta.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.util.LinkedHashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * @author 周宁 8 | */ 9 | public class IndexMeta { 10 | /** 11 | * 索引名称 12 | */ 13 | private String indexName; 14 | /** 15 | * 行 16 | */ 17 | private Set columnNames = new LinkedHashSet(); 18 | /** 19 | * 是否为唯一索引 20 | */ 21 | private boolean unique; 22 | /** 23 | * 索引类型 24 | */ 25 | private String indexType; 26 | /** 27 | * 备注 28 | */ 29 | private String comment; 30 | 31 | public String getIndexName() { 32 | return indexName; 33 | } 34 | 35 | public void setIndexName(String indexName) { 36 | this.indexName = indexName; 37 | } 38 | 39 | public Set getColumnNames() { 40 | return columnNames; 41 | } 42 | 43 | public void setColumnNames(Set columnNames) { 44 | this.columnNames = columnNames; 45 | } 46 | 47 | public boolean isUnique() { 48 | return unique; 49 | } 50 | 51 | public void setUnique(boolean unique) { 52 | this.unique = unique; 53 | } 54 | 55 | public String getIndexType() { 56 | return indexType; 57 | } 58 | 59 | public void setIndexType(String indexType) { 60 | this.indexType = indexType; 61 | } 62 | 63 | public String getComment() { 64 | return comment; 65 | } 66 | 67 | public void setComment(String comment) { 68 | this.comment = comment; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/TypeFunction.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import com.gysoft.jdbc.annotation.Column; 4 | import com.gysoft.jdbc.tools.EntityTools; 5 | 6 | import java.beans.Introspector; 7 | import java.io.Serializable; 8 | import java.lang.invoke.SerializedLambda; 9 | import java.lang.reflect.Field; 10 | import java.lang.reflect.Method; 11 | import java.util.function.Function; 12 | 13 | /** 14 | * @author 周宁 15 | */ 16 | @FunctionalInterface 17 | public interface TypeFunction extends Serializable, Function { 18 | 19 | /** 20 | * 获取列名称 21 | * 22 | * @param lambda lamda表达式 23 | * @return String 列名称 24 | */ 25 | static String getLambdaColumnName(Serializable lambda) { 26 | try { 27 | Method method = lambda.getClass().getDeclaredMethod("writeReplace"); 28 | method.setAccessible(Boolean.TRUE); 29 | SerializedLambda serializedLambda = (SerializedLambda) method.invoke(lambda); 30 | String getter = serializedLambda.getImplMethodName(); 31 | String fieldName = Introspector.decapitalize(getter.replace("get", "")); 32 | 33 | // 通过字段名获取字段 34 | Field field = 35 | Class.forName(serializedLambda.getImplClass().replace("/", ".")) 36 | .getDeclaredField(fieldName); 37 | 38 | com.gysoft.jdbc.annotation.Column anno = field.getAnnotation(Column.class); 39 | if (anno != null) { 40 | return EntityTools.getColumnName(field); 41 | } else { 42 | return EntityTools.transferColumnName(fieldName); 43 | } 44 | } catch (ReflectiveOperationException e) { 45 | throw new GyjdbcException(e); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/BindPointAspect.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | import org.aspectj.lang.annotation.Around; 5 | import org.aspectj.lang.annotation.Aspect; 6 | import org.aspectj.lang.annotation.Pointcut; 7 | import org.aspectj.lang.reflect.MethodSignature; 8 | 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * @author 周宁 13 | */ 14 | @Aspect 15 | public class BindPointAspect { 16 | 17 | @Pointcut("@annotation(com.gysoft.jdbc.multi.BindPoint)") 18 | public void processMethod() { 19 | } 20 | 21 | @Pointcut("@within(com.gysoft.jdbc.multi.BindPoint)") 22 | public void processClass() { 23 | } 24 | 25 | @Around("processMethod()||processClass()") 26 | public Object around(ProceedingJoinPoint point) throws Throwable { 27 | Object object = point.getTarget(); 28 | BindPoint classBindPoint = object.getClass().getAnnotation(BindPoint.class); 29 | if (classBindPoint != null) { 30 | DataSourceBindHolder.setDataSource(DataSourceBind.bindPoint(classBindPoint)); 31 | } 32 | String methodName = point.getSignature().getName(); 33 | MethodSignature methodSignature = ((MethodSignature) point.getSignature()); 34 | Class[] parameterTypes = methodSignature.getMethod().getParameterTypes(); 35 | Method method = object.getClass().getMethod(methodName, parameterTypes); 36 | BindPoint methodBindPoint = method.getAnnotation(BindPoint.class); 37 | if (methodBindPoint != null) { 38 | DataSourceBindHolder.setDataSource(DataSourceBind.bindPoint(methodBindPoint)); 39 | } 40 | try { 41 | return point.proceed(); 42 | } finally { 43 | DataSourceBindHolder.clearDataSource(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/balance/LeastActiveLoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi.balance; 2 | 3 | import com.gysoft.jdbc.multi.DataSourceBindHolder; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.concurrent.ThreadLocalRandom; 8 | 9 | /** 10 | * @author 周宁 11 | */ 12 | public class LeastActiveLoadBalance extends AbstractLoadBalance { 13 | 14 | @Override 15 | protected String doSelect(List keys, String group) { 16 | if (keys == null || keys.isEmpty()) { 17 | return null; 18 | } 19 | if (keys.size() == 1) { 20 | return keys.get(0); 21 | } 22 | // 查找活跃连接数最少的数据源 23 | List leastActiveKeys = findLeastActiveKeys(keys); 24 | // 如果只有一个最少活跃的数据源,直接返回 25 | if (leastActiveKeys.size() == 1) { 26 | return leastActiveKeys.get(0); 27 | } 28 | // 如果有多个活跃连接数相同的数据源,则随机选择 29 | return selectRandomFromCandidates(leastActiveKeys); 30 | } 31 | 32 | private List findLeastActiveKeys(List keys) { 33 | List leastActiveKeys = new ArrayList<>(); 34 | int minActiveCount = Integer.MAX_VALUE; 35 | for (String key : keys) { 36 | Integer activeCount = DataSourceBindHolder.getActiveCount(key); 37 | if (activeCount == null) { 38 | activeCount = 0; 39 | } 40 | if (activeCount < minActiveCount) { 41 | minActiveCount = activeCount; 42 | leastActiveKeys.clear(); 43 | leastActiveKeys.add(key); 44 | } else if (activeCount == minActiveCount) { 45 | leastActiveKeys.add(key); 46 | } 47 | } 48 | return leastActiveKeys; 49 | } 50 | 51 | /** 52 | * 从候选数据源中随机选择一个 53 | */ 54 | private String selectRandomFromCandidates(List candidates) { 55 | return candidates.get(ThreadLocalRandom.current().nextInt(candidates.size())); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/AtomicPositiveInteger.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi; 2 | 3 | import com.gysoft.jdbc.bean.GyjdbcException; 4 | 5 | import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; 6 | 7 | /** 8 | * @author 周宁 9 | */ 10 | public class AtomicPositiveInteger extends Number { 11 | 12 | 13 | private static final long serialVersionUID = -3038533876489105940L; 14 | 15 | private static final AtomicIntegerFieldUpdater indexUpdater = 16 | AtomicIntegerFieldUpdater.newUpdater(AtomicPositiveInteger.class, "index"); 17 | 18 | private volatile int index = 0; 19 | 20 | public AtomicPositiveInteger() { 21 | } 22 | 23 | 24 | public final int getAndIncrement() { 25 | return indexUpdater.getAndIncrement(this) & Integer.MAX_VALUE; 26 | } 27 | 28 | public final int get() { 29 | return indexUpdater.get(this) & Integer.MAX_VALUE; 30 | } 31 | 32 | public final void set(int newValue) { 33 | if (newValue < 0) { 34 | throw new GyjdbcException("new value " + newValue + " < 0"); 35 | } 36 | indexUpdater.set(this, newValue); 37 | } 38 | 39 | @Override 40 | public byte byteValue() { 41 | return (byte) get(); 42 | } 43 | 44 | @Override 45 | public short shortValue() { 46 | return (short) get(); 47 | } 48 | 49 | @Override 50 | public int intValue() { 51 | return get(); 52 | } 53 | 54 | @Override 55 | public long longValue() { 56 | return (long) get(); 57 | } 58 | 59 | @Override 60 | public float floatValue() { 61 | return (float) get(); 62 | } 63 | 64 | @Override 65 | public double doubleValue() { 66 | return (double) get(); 67 | } 68 | 69 | @Override 70 | public String toString() { 71 | return Integer.toString(get()); 72 | } 73 | 74 | @Override 75 | public int hashCode() { 76 | final int prime = 31; 77 | int result = 1; 78 | result = prime * result + get(); 79 | return result; 80 | } 81 | 82 | @Override 83 | public boolean equals(Object obj) { 84 | if (this == obj) return true; 85 | if (!(obj instanceof AtomicPositiveInteger)) return false; 86 | AtomicPositiveInteger other = (AtomicPositiveInteger) obj; 87 | return intValue() == other.intValue(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/DataSourceBindHolder.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | /** 7 | * @author 周宁 8 | */ 9 | public abstract class DataSourceBindHolder { 10 | private static ThreadLocal DataSourceBindHolder = new ThreadLocal<>(); 11 | private static Map activeCountMap = new ConcurrentHashMap<>(); 12 | 13 | public static void setDataSource(DataSourceBind dataSourceBind) { 14 | //上个线程设置的DataSourceBind 15 | dataSourceBind.setPrev(DataSourceBindHolder.get()); 16 | DataSourceBindHolder.set(dataSourceBind); 17 | } 18 | 19 | public static void clearDataSource() { 20 | DataSourceBind dataSourceBind = DataSourceBindHolder.get(); 21 | if (dataSourceBind != null) { 22 | decreaseActiveCount(dataSourceBind); 23 | } 24 | DataSourceBindHolder.remove(); 25 | } 26 | 27 | public static String getDataSource() { 28 | DataSourceBind dataSourceBind = DataSourceBindHolder.get(); 29 | if (dataSourceBind == null) { 30 | return null; 31 | } 32 | try { 33 | String result = dataSourceBind.select(true); 34 | increaseActiveCount(result); 35 | return result; 36 | } finally { 37 | //清理或者恢复上次的DataSourceBind 38 | //这么写通过entityDao.bindXxx()方法调用时就不会存在内存泄漏问题了 39 | if (dataSourceBind.getBindType().equals(DataSourceBind.BindType.byMethod)) { 40 | clearDataSource(); 41 | if (dataSourceBind.getPrev() != null) { 42 | DataSourceBindHolder.set(dataSourceBind.getPrev()); 43 | } 44 | } 45 | } 46 | } 47 | 48 | private static void increaseActiveCount(String key) { 49 | if (key != null) { 50 | activeCountMap.compute(key, (k, v) -> v == null ? 1 : v + 1); 51 | } 52 | } 53 | 54 | private static void decreaseActiveCount(DataSourceBind dataSourceBind) { 55 | String key = dataSourceBind.select(false); 56 | if (key != null) { 57 | activeCountMap.computeIfPresent(key, (k, v) -> v - dataSourceBind.getActive()); 58 | } 59 | } 60 | 61 | public static Integer getActiveCount(String dataSourceKey) { 62 | return activeCountMap.get(dataSourceKey); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/SQLTree.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | 4 | import java.util.List; 5 | 6 | /** 7 | * 查询条件节点抽象 8 | * 9 | * @author 周宁 10 | */ 11 | public class SQLTree { 12 | /** 13 | * 该criteria节点对应的sql 14 | */ 15 | private String sql; 16 | /** 17 | * 该criteria节点对应的参数 18 | */ 19 | private Object[] params; 20 | /** 21 | * 子sql 22 | */ 23 | private List childs; 24 | /** 25 | * 树节点的id 26 | */ 27 | private String id; 28 | /** 29 | * 连接类型 30 | */ 31 | private String unionType; 32 | /** 33 | * 将sql作为表的别名 34 | */ 35 | private String asTable; 36 | /** 37 | * 将整条sql作为表别名 38 | */ 39 | private String fromAsTable; 40 | 41 | public String getSql() { 42 | return sql; 43 | } 44 | 45 | public void setSql(String sql) { 46 | this.sql = sql; 47 | } 48 | 49 | public Object[] getParams() { 50 | return params; 51 | } 52 | 53 | public void setParams(Object[] params) { 54 | this.params = params; 55 | } 56 | 57 | public List getChilds() { 58 | return childs; 59 | } 60 | 61 | public void setChilds(List childs) { 62 | this.childs = childs; 63 | } 64 | 65 | public String getId() { 66 | return id; 67 | } 68 | 69 | public void setId(String id) { 70 | this.id = id; 71 | } 72 | 73 | public String getUnionType() { 74 | return unionType; 75 | } 76 | 77 | public String getAsTable() { 78 | return asTable; 79 | } 80 | 81 | public String getFromAsTable() { 82 | return fromAsTable; 83 | } 84 | 85 | public void setFromAsTable(String fromAsTable) { 86 | this.fromAsTable = fromAsTable; 87 | } 88 | 89 | public void setAsTable(String asTable) { 90 | this.asTable = asTable; 91 | } 92 | 93 | public void setUnionType(String unionType) { 94 | this.unionType = unionType; 95 | } 96 | 97 | public SQLTree(String sql, Object[] params, List childs, String id, String unionType, String asTable, String fromAsTable) { 98 | this.sql = sql; 99 | this.params = params; 100 | this.childs = childs; 101 | this.id = id; 102 | this.unionType = unionType; 103 | this.asTable = asTable; 104 | this.fromAsTable = fromAsTable; 105 | } 106 | 107 | public SQLTree() { 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Result.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import org.apache.commons.lang.ArrayUtils; 4 | import org.springframework.dao.support.DataAccessUtils; 5 | import org.springframework.jdbc.core.BeanPropertyRowMapper; 6 | import org.springframework.jdbc.core.ColumnMapRowMapper; 7 | import org.springframework.jdbc.core.JdbcTemplate; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.function.BiConsumer; 12 | 13 | /** 14 | * @param 结果类型 15 | * @author 周宁 16 | */ 17 | public class Result { 18 | 19 | private final Class type; 20 | private final String sql; 21 | private final Object[] params; 22 | private final JdbcTemplate jdbcTemplate; 23 | private BiConsumer consumer; 24 | 25 | public Result(Class type, String sql, Object[] params, JdbcTemplate jdbcTemplate,BiConsumer consumer) { 26 | this.type = type; 27 | this.sql = sql; 28 | this.params = params; 29 | this.jdbcTemplate = jdbcTemplate; 30 | this.consumer = consumer; 31 | } 32 | 33 | public E queryOne() throws Exception { 34 | return DataAccessUtils.singleResult(queryList()); 35 | } 36 | 37 | public E queryObject() throws Exception { 38 | consumer.accept(sql,params); 39 | return jdbcTemplate.queryForObject(sql, params, type); 40 | } 41 | 42 | public List queryList() throws Exception { 43 | consumer.accept(sql,params); 44 | return jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(type), params); 45 | } 46 | 47 | public List queryForList()throws Exception{ 48 | consumer.accept(sql,params); 49 | return jdbcTemplate.queryForList(sql, type, params); 50 | } 51 | 52 | public List> queryMaps() throws Exception { 53 | consumer.accept(sql,params); 54 | return jdbcTemplate.query(sql, params, new ColumnMapRowMapper()); 55 | } 56 | 57 | public PageResult pageQuery(Page page) throws Exception { 58 | Object pageParams[] = {}; 59 | String pageSql = "SELECT SQL_CALC_FOUND_ROWS * FROM (" + sql + ") temp "; 60 | pageSql = pageSql + " LIMIT ?,?"; 61 | pageParams = ArrayUtils.addAll(params, new Object[]{page.getOffset(), page.getPageSize()}); 62 | consumer.accept(pageSql,pageParams); 63 | List paged = jdbcTemplate.query(pageSql, pageParams, BeanPropertyRowMapper.newInstance(type)); 64 | String countSql = "SELECT FOUND_ROWS() "; 65 | consumer.accept(countSql,new Object[]{}); 66 | int count = jdbcTemplate.queryForObject(countSql, Integer.class); 67 | return new PageResult(paged, count); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/dao/ISpringJdbc.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.dao; 2 | 3 | import com.gysoft.jdbc.bean.Page; 4 | import com.gysoft.jdbc.bean.PageResult; 5 | import java.util.List; 6 | import java.util.Map; 7 | import org.springframework.jdbc.core.JdbcTemplate; 8 | import org.springframework.jdbc.core.ResultSetExtractor; 9 | import org.springframework.jdbc.core.RowMapper; 10 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; 11 | 12 | /** 13 | * @author 周宁 14 | */ 15 | public interface ISpringJdbc { 16 | JdbcTemplate getJdbcTemplate(); 17 | 18 | NamedParameterJdbcTemplate getNamedParameterJdbcTemplate(); 19 | 20 | String insertForId(String sql) throws Exception; 21 | 22 | String insertForId(String sql, Object[] args) throws Exception; 23 | 24 | int batchInsert(String sql, List batchArgs) throws Exception; 25 | 26 | int batchInsert(String sql, List batchArgs, int[] types) throws Exception; 27 | 28 | int batchInsert(String sql, List batchArgs, int batchPageSize) throws Exception; 29 | 30 | int batchInsert(String sql, List batchArgs, int[] types, int batchPageSize) throws Exception; 31 | 32 | void batchUpdate(String sql, List batchArgs) throws Exception; 33 | 34 | void batchUpdate(String sql, List batchArgs, int batchPageSize) throws Exception; 35 | 36 | void batchUpdate(String sql, List batchArgs, int[] types) throws Exception; 37 | 38 | void batchUpdate(String sql, List batchArgs, int[] types, int batchPageSize) throws Exception; 39 | 40 | int update(String sql, Object[] args) throws Exception; 41 | 42 | T query(String sql, ResultSetExtractor rse) throws Exception; 43 | 44 | T query(String sql, Object[] args, ResultSetExtractor rse) throws Exception; 45 | 46 | List query(String sql, RowMapper rowMapper) throws Exception; 47 | 48 | List query(String sql, Object[] args, RowMapper rowMapper) throws Exception; 49 | 50 | List query(String sql, Class elementType) throws Exception; 51 | 52 | List query(String sql, Object[] args, Class elementType) throws Exception; 53 | 54 | List query(String sql, Map paramMap, Class elementType) throws Exception; 55 | 56 | T queryForObject(String sql, Class requiredType) throws Exception; 57 | 58 | T queryForObject(String sql, Object[] args, Class requiredType) throws Exception; 59 | 60 | List> queryForList(String sql, Object[] args) throws Exception; 61 | 62 | PageResult queryForPageResult(Page page, String sql, Object[] args, Class requiredType) throws Exception; 63 | 64 | PageResult queryForPageResult(Page page, String sql, Map paramMap, Class requiredType) throws Exception; 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Table.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.util.function.Consumer; 4 | 5 | /** 6 | * @author 周宁 7 | */ 8 | public class Table { 9 | /** 10 | * 持有的sql对象 11 | */ 12 | private final SQL sql; 13 | /** 14 | * 表的元数据 15 | */ 16 | private TableMeta tableMeta; 17 | 18 | public Table(SQL sql) { 19 | this.sql = sql; 20 | tableMeta = new TableMeta(); 21 | } 22 | 23 | public Table temporary(){ 24 | tableMeta.setTemporary(true); 25 | return this; 26 | } 27 | 28 | public Table table(String name) { 29 | tableMeta.setName(name); 30 | return this; 31 | } 32 | 33 | public Table table(){ 34 | return this; 35 | } 36 | 37 | public Table ifNotExists(){ 38 | tableMeta.setIfNotExists(true); 39 | return this; 40 | } 41 | 42 | public Table comment(String comment) { 43 | tableMeta.setComment(comment); 44 | return this; 45 | } 46 | 47 | public Table engine(TableEnum.Engine tableEngine) { 48 | tableMeta.setEngine(tableEngine); 49 | return this; 50 | } 51 | 52 | public Table charset(String charset) { 53 | tableMeta.setCharacterSet(charset); 54 | return this; 55 | } 56 | 57 | public Table collation(String collation) { 58 | tableMeta.setCollation(collation); 59 | return this; 60 | } 61 | 62 | public Table utf8mb4() { 63 | return this.charset("utf8mb4").collation("utf8mb4_general_ci"); 64 | } 65 | 66 | public Table latin1() { 67 | return this.charset("latin1").collation("latin1_swedish_ci"); 68 | } 69 | 70 | public Table utf8() { 71 | return this.charset("utf8").collation("utf8_general_ci"); 72 | } 73 | 74 | public Table autoIncrement(long startVal) { 75 | tableMeta.setAutoIncrement(startVal); 76 | return this; 77 | } 78 | 79 | public Table rowFormat(TableEnum.RowFormat rowFormat) { 80 | tableMeta.setRowFormat(rowFormat); 81 | return this; 82 | } 83 | 84 | public SQL commit() { 85 | sql.setTableMeta(tableMeta); 86 | return sql; 87 | } 88 | 89 | public Column column() { 90 | return new Column(this); 91 | } 92 | 93 | public Index index(){ 94 | return new Index(this); 95 | } 96 | 97 | public Table column(Consumer consumer) { 98 | Column column = new Column(this); 99 | consumer.accept(column); 100 | return column.commit(); 101 | } 102 | 103 | public Table index(Consumer consumer){ 104 | Index index = new Index(this); 105 | consumer.accept(index); 106 | return index.commit(); 107 | } 108 | 109 | TableMeta getTableMeta() { 110 | return tableMeta; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/ColumnMeta.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.sql.JDBCType; 4 | 5 | /** 6 | * @author 周宁 7 | */ 8 | public class ColumnMeta { 9 | /** 10 | * 字段名称 11 | */ 12 | private String name; 13 | /** 14 | * 字段长度 15 | */ 16 | private int length; 17 | /** 18 | * 字段精度 19 | */ 20 | private int precision; 21 | /** 22 | * 字段范围 23 | */ 24 | private int scale; 25 | /** 26 | * 是否notnull 27 | */ 28 | private boolean notNull; 29 | /** 30 | * 是否为主键 31 | */ 32 | private boolean primaryKey; 33 | /** 34 | * 类型 35 | */ 36 | private JDBCType jdbcType; 37 | /** 38 | * 默认值 39 | */ 40 | private String val; 41 | /** 42 | * 类型字符串 43 | */ 44 | private String dataType; 45 | /** 46 | * 备注 47 | */ 48 | private String comment; 49 | /** 50 | * 自增长 51 | */ 52 | private boolean autoIncr; 53 | 54 | public int getLength() { 55 | return length; 56 | } 57 | 58 | public void setLength(int length) { 59 | this.length = length; 60 | } 61 | 62 | public int getPrecision() { 63 | return precision; 64 | } 65 | 66 | public void setPrecision(int precision) { 67 | this.precision = precision; 68 | } 69 | 70 | public int getScale() { 71 | return scale; 72 | } 73 | 74 | public void setScale(int scale) { 75 | this.scale = scale; 76 | } 77 | 78 | public boolean isNotNull() { 79 | return notNull; 80 | } 81 | 82 | public void setNotNull(boolean notNull) { 83 | this.notNull = notNull; 84 | } 85 | 86 | public boolean isPrimaryKey() { 87 | return primaryKey; 88 | } 89 | 90 | public void setPrimaryKey(boolean primaryKey) { 91 | this.primaryKey = primaryKey; 92 | } 93 | 94 | public JDBCType getJdbcType() { 95 | return jdbcType; 96 | } 97 | 98 | public void setJdbcType(JDBCType jdbcType) { 99 | this.jdbcType = jdbcType; 100 | } 101 | 102 | public void setName(String name) { 103 | this.name = name; 104 | } 105 | 106 | public String getVal() { 107 | return val; 108 | } 109 | 110 | public void setVal(String val) { 111 | this.val = val; 112 | } 113 | 114 | public String getName() { 115 | return name; 116 | } 117 | 118 | public String getDataType() { 119 | return dataType; 120 | } 121 | 122 | public void setDataType(String dataType) { 123 | this.dataType = dataType; 124 | } 125 | 126 | public String getComment() { 127 | return comment; 128 | } 129 | 130 | public void setComment(String comment) { 131 | this.comment = comment; 132 | } 133 | 134 | public boolean isAutoIncr() { 135 | return autoIncr; 136 | } 137 | 138 | public void setAutoIncr(boolean autoIncr) { 139 | this.autoIncr = autoIncr; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/tools/CustomResultSetExractorFactory.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.tools; 2 | 3 | import org.springframework.dao.DataAccessException; 4 | import org.springframework.jdbc.core.ResultSetExtractor; 5 | 6 | import java.math.BigDecimal; 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | import java.util.Date; 10 | import java.util.HashMap; 11 | import java.util.LinkedHashMap; 12 | import java.util.Map; 13 | 14 | /** 15 | * @author 周宁 16 | */ 17 | public class CustomResultSetExractorFactory { 18 | /** 19 | * 两列结果值得映射Mapper类 20 | */ 21 | private static final ResultSetExtractor DOUBLE_COLUMN_VALUE_RESULTSETEXRACTOR = (rs) -> { 22 | Map result = new LinkedHashMap<>(); 23 | while (rs.next()) { 24 | result.put(rs.getObject(1), rs.getObject(2)); 25 | } 26 | return result; 27 | }; 28 | 29 | 30 | /** 31 | * 创建两列结果值得Map集合的RowMapper 32 | * 注意:这个方法可能会导致类型转换BUG,已过时,建议使用重载方法 33 | * 34 | * @return ResultSetExtractor 两列结果值得映射抽取器 35 | */ 36 | @Deprecated 37 | public static ResultSetExtractor createDoubleColumnValueResultSetExractor() { 38 | return DOUBLE_COLUMN_VALUE_RESULTSETEXRACTOR; 39 | } 40 | 41 | public static ResultSetExtractor createDoubleColumnValueResultSetExtractor(Class kCls, Class vCls) { 42 | return new ResultSetExtractor() { 43 | Map result = new LinkedHashMap<>(1); 44 | 45 | @Override 46 | public Object extractData(ResultSet rs) throws SQLException, DataAccessException { 47 | while (rs.next()) { 48 | result.put(getColumVal(kCls, rs, 1), getColumVal(vCls, rs, 2)); 49 | } 50 | return result; 51 | } 52 | }; 53 | } 54 | 55 | 56 | public static Object getColumVal(Class cls, ResultSet rs, int i) throws SQLException { 57 | if (String.class.equals(cls)) { 58 | return rs.getString(i); 59 | } else if (int.class.equals(cls) || Integer.class.equals(cls)) { 60 | return rs.getInt(i); 61 | } else if (double.class.equals(cls) || Double.class.equals(cls)) { 62 | return rs.getDouble(i); 63 | } else if (Date.class.isAssignableFrom(cls)) { 64 | return rs.getDate(i); 65 | } else if (long.class.equals(cls) || Long.class.equals(cls)) { 66 | return rs.getLong(i); 67 | } else if (float.class.equals(cls) || Float.class.equals(cls)) { 68 | return rs.getFloat(i); 69 | } else if (boolean.class.equals(cls) || Boolean.class.equals(cls)) { 70 | return rs.getBoolean(i); 71 | } else if (short.class.equals(cls) || Short.class.equals(cls)) { 72 | return rs.getShort(i); 73 | } else if (byte.class.equals(cls) || Byte.class.equals(cls)) { 74 | return rs.getByte(i); 75 | } else if (BigDecimal.class.equals(cls)) { 76 | return rs.getBigDecimal(i); 77 | } else { 78 | return rs.getObject(i); 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Where.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.util.Collection; 4 | 5 | /** 6 | * @author zhouning 7 | */ 8 | public class Where { 9 | 10 | private String key; 11 | private Criteria criteria; 12 | 13 | public Where() { 14 | this.criteria = new Criteria(); 15 | } 16 | 17 | public Where(String key) { 18 | this.criteria = new Criteria(); 19 | this.key = key; 20 | } 21 | 22 | protected Where(Criteria criteria, String key) { 23 | this.criteria = criteria; 24 | this.key = key; 25 | } 26 | 27 | public static Where where(String key) { 28 | return new Where(key); 29 | } 30 | 31 | public static Where where(TypeFunction function) { 32 | return new Where(TypeFunction.getLambdaColumnName(function)); 33 | } 34 | 35 | public Where or(String key) { 36 | return new Where(criteria, " OR " + key); 37 | } 38 | 39 | public Where or(TypeFunction function) { 40 | return new Where(criteria, " OR " + TypeFunction.getLambdaColumnName(function)); 41 | } 42 | 43 | public Where and(String key) { 44 | return new Where(criteria, key); 45 | } 46 | 47 | public Where and(TypeFunction function) { 48 | return and(TypeFunction.getLambdaColumnName(function)); 49 | } 50 | 51 | public Where equal(Object val) { 52 | criteria.and(key, val); 53 | return this; 54 | } 55 | 56 | public Where notEqual(Object val) { 57 | criteria.notEqual(key, val); 58 | return this; 59 | } 60 | 61 | public Where lt(Object val) { 62 | criteria.lt(key, val); 63 | return this; 64 | } 65 | 66 | public Where let(Object val) { 67 | criteria.let(key, val); 68 | return this; 69 | } 70 | 71 | public Where gt(Object val) { 72 | criteria.gt(key, val); 73 | return this; 74 | } 75 | 76 | public Where gte(Object val) { 77 | criteria.gte(key, val); 78 | return this; 79 | } 80 | 81 | public Where in(Collection val) { 82 | criteria.in(key, val); 83 | return this; 84 | } 85 | 86 | public Where notIn(Collection val) { 87 | criteria.notIn(key, val); 88 | return this; 89 | } 90 | 91 | public Where like(Object val) { 92 | criteria.like(key, val); 93 | return this; 94 | } 95 | 96 | public Where isNull() { 97 | criteria.isNull(key); 98 | return this; 99 | } 100 | 101 | public Where isNotNull() { 102 | criteria.isNotNull(key); 103 | return this; 104 | } 105 | 106 | public Where exists(SQL sql) { 107 | criteria.exists(sql); 108 | return this; 109 | } 110 | 111 | public Where notExists(SQL sql) { 112 | criteria.notExists(sql); 113 | return this; 114 | } 115 | 116 | public Where betweenAnd(Object v1, Object v2) { 117 | criteria.betweenAnd(key, v1, v2); 118 | return this; 119 | } 120 | 121 | Criteria getCriteria() { 122 | return criteria; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/TableMeta.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author 周宁 8 | */ 9 | public class TableMeta { 10 | 11 | /** 12 | * 表名称 13 | */ 14 | private String name; 15 | /** 16 | * 备注 17 | */ 18 | private String comment; 19 | /** 20 | * 引擎类型 21 | */ 22 | private TableEnum.Engine engine; 23 | /** 24 | * 是否为临时表 25 | */ 26 | private boolean temporary; 27 | /** 28 | * 是否判断表的存在与否 29 | */ 30 | private boolean ifNotExists; 31 | 32 | /** 33 | * 字符集 (例如: utf8mb4) 34 | * 对应 SQL: DEFAULT CHARSET=utf8mb4 35 | */ 36 | private String characterSet; 37 | 38 | /** 39 | * 排序规则 (例如: utf8mb4_general_ci) 40 | * 对应 SQL: COLLATE=utf8mb4_general_ci 41 | */ 42 | private String collation; 43 | 44 | /** 45 | * 自增主键起始值 46 | * 对应 SQL: AUTO_INCREMENT=1000 47 | */ 48 | private Long autoIncrement; 49 | 50 | /** 51 | * 行格式 (例如: DYNAMIC, COMPRESSED, FIXED) 52 | * 对应 SQL: ROW_FORMAT=DYNAMIC 53 | */ 54 | private TableEnum.RowFormat rowFormat; 55 | 56 | private List columns = new ArrayList<>(); 57 | 58 | private List indexs = new ArrayList<>(); 59 | 60 | public String getName() { 61 | return name; 62 | } 63 | 64 | public void setName(String name) { 65 | this.name = name; 66 | } 67 | 68 | public String getComment() { 69 | return comment; 70 | } 71 | 72 | public void setComment(String comment) { 73 | this.comment = comment; 74 | } 75 | 76 | public TableEnum.Engine getEngine() { 77 | return engine; 78 | } 79 | 80 | public void setEngine(TableEnum.Engine engine) { 81 | this.engine = engine; 82 | } 83 | 84 | public List getColumns() { 85 | return columns; 86 | } 87 | 88 | public void setColumns(List columns) { 89 | this.columns = columns; 90 | } 91 | 92 | public List getIndexs() { 93 | return indexs; 94 | } 95 | 96 | public void setIndexs(List indexs) { 97 | this.indexs = indexs; 98 | } 99 | 100 | public boolean isTemporary() { 101 | return temporary; 102 | } 103 | 104 | public void setTemporary(boolean temporary) { 105 | this.temporary = temporary; 106 | } 107 | 108 | public boolean isIfNotExists() { 109 | return ifNotExists; 110 | } 111 | 112 | public void setIfNotExists(boolean ifNotExists) { 113 | this.ifNotExists = ifNotExists; 114 | } 115 | 116 | public String getCharacterSet() { 117 | return characterSet; 118 | } 119 | 120 | public void setCharacterSet(String characterSet) { 121 | this.characterSet = characterSet; 122 | } 123 | 124 | public String getCollation() { 125 | return collation; 126 | } 127 | 128 | public void setCollation(String collation) { 129 | this.collation = collation; 130 | } 131 | 132 | public Long getAutoIncrement() { 133 | return autoIncrement; 134 | } 135 | 136 | public void setAutoIncrement(Long autoIncrement) { 137 | this.autoIncrement = autoIncrement; 138 | } 139 | 140 | public TableEnum.RowFormat getRowFormat() { 141 | return rowFormat; 142 | } 143 | 144 | public void setRowFormat(TableEnum.RowFormat rowFormat) { 145 | this.rowFormat = rowFormat; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/WhereParam.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.util.Collection; 4 | 5 | /** 6 | *@author 周宁 7 | */ 8 | public class WhereParam { 9 | 10 | public enum OptEnum { 11 | Like, Gt, Gte, Lt, Let, NotEqual, IsNull, IsNotNull, 12 | Equal, Exists, NotExists, BetweenAnd, In, NotIn; 13 | } 14 | 15 | private String key; 16 | private String opt; 17 | private Object value; 18 | 19 | private OptEnum optEnum; 20 | 21 | public String getKey() { 22 | return key; 23 | } 24 | 25 | public void setKey(String key) { 26 | this.key = key; 27 | } 28 | 29 | public String getOpt() { 30 | return opt; 31 | } 32 | 33 | public void setOpt(String opt) { 34 | this.opt = opt; 35 | } 36 | 37 | public Object getValue() { 38 | return value; 39 | } 40 | 41 | public void setValue(Object value) { 42 | this.value = value; 43 | } 44 | 45 | public OptEnum getOptEnum() { 46 | return optEnum; 47 | } 48 | 49 | public void setOptEnum(OptEnum optEnum) { 50 | this.optEnum = optEnum; 51 | } 52 | 53 | WhereParam(String key, String opt, Object value) { 54 | this.key = key; 55 | this.opt = opt; 56 | this.value = value; 57 | } 58 | 59 | 60 | WhereParam(String key) { 61 | this.key = key; 62 | } 63 | 64 | WhereParam() { 65 | } 66 | 67 | 68 | public static WhereParam where(String key){ 69 | return new WhereParam(key); 70 | } 71 | 72 | public static WhereParam where(TypeFunction function) { 73 | return new WhereParam(TypeFunction.getLambdaColumnName(function)); 74 | } 75 | 76 | 77 | public WhereParam equal(Object val) { 78 | this.optEnum = OptEnum.Equal; 79 | this.value =val; 80 | return this; 81 | } 82 | 83 | public WhereParam notEqual(Object val) { 84 | this.optEnum = OptEnum.NotEqual; 85 | this.value =val; 86 | return this; 87 | } 88 | 89 | public WhereParam lt(Object val) { 90 | this.optEnum = OptEnum.Lt; 91 | this.value =val; 92 | return this; 93 | } 94 | 95 | public WhereParam let(Object val) { 96 | this.optEnum = OptEnum.Let; 97 | this.value =val; 98 | return this; 99 | } 100 | 101 | public WhereParam gt(Object val) { 102 | this.optEnum = OptEnum.Gt; 103 | this.value =val; 104 | return this; 105 | } 106 | 107 | public WhereParam gte(Object val) { 108 | this.optEnum = OptEnum.Gte; 109 | this.value =val; 110 | return this; 111 | } 112 | 113 | public WhereParam in(Collection val) { 114 | this.optEnum = OptEnum.In; 115 | this.value =val; 116 | return this; 117 | } 118 | 119 | public WhereParam notIn(Collection val) { 120 | this.optEnum = OptEnum.NotIn; 121 | this.value =val; 122 | return this; 123 | } 124 | 125 | public WhereParam like(Object val) { 126 | this.optEnum = OptEnum.Like; 127 | this.value =val; 128 | return this; 129 | } 130 | 131 | public WhereParam isNull() { 132 | this.optEnum = OptEnum.IsNull; 133 | this.value =null; 134 | return this; 135 | } 136 | 137 | public WhereParam isNotNull() { 138 | this.optEnum = OptEnum.IsNotNull; 139 | this.value =null; 140 | return this; 141 | } 142 | 143 | public WhereParam exists(SQL sql) { 144 | this.optEnum = OptEnum.Exists; 145 | this.value =sql; 146 | return this; 147 | } 148 | 149 | public WhereParam notExists(SQL sql) { 150 | this.optEnum = OptEnum.NotExists; 151 | this.value =sql; 152 | return this; 153 | } 154 | 155 | public WhereParam betweenAnd(Object v1, Object v2) { 156 | this.optEnum = OptEnum.BetweenAnd; 157 | this.value =new Pair(v1,v2); 158 | return this; 159 | } 160 | } -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/multi/DataSourceBind.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.multi; 2 | 3 | import com.gysoft.jdbc.multi.balance.*; 4 | import org.apache.commons.lang.StringUtils; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author 周宁 11 | */ 12 | public class DataSourceBind { 13 | private static final Map LoadBalanceMap = new HashMap<>(); 14 | 15 | static { 16 | LoadBalanceMap.put(RoundRobinLoadBalance.class, new RoundRobinLoadBalance()); 17 | LoadBalanceMap.put(RandomLoadBalance.class, new RandomLoadBalance()); 18 | LoadBalanceMap.put(SelectFirstLoadBalance.class, new SelectFirstLoadBalance()); 19 | LoadBalanceMap.put(SelectLastLoadBalance.class, new SelectLastLoadBalance()); 20 | LoadBalanceMap.put(LeastActiveLoadBalance.class, new LeastActiveLoadBalance()); 21 | } 22 | 23 | enum BindType { 24 | byMethod, byAnno; 25 | } 26 | 27 | private BindType bindType; 28 | 29 | private String key; 30 | 31 | private String group; 32 | 33 | private Class loadBalance; 34 | 35 | private String select; 36 | 37 | private Integer active; 38 | 39 | private DataSourceBind prev; 40 | 41 | public DataSourceBind(String key, BindType bindType, String group, Class loadBalance) { 42 | this.key = key; 43 | this.bindType = bindType; 44 | this.group = group; 45 | this.loadBalance = loadBalance; 46 | this.active = 0; 47 | } 48 | 49 | 50 | public static DataSourceBind bindKey(String key) { 51 | return new DataSourceBind(key, BindType.byMethod, null, null); 52 | } 53 | 54 | public static DataSourceBind bindGroup(String group, Class loadBalance) { 55 | return new DataSourceBind(null, BindType.byMethod, group, loadBalance); 56 | } 57 | 58 | public static DataSourceBind bindPoint(BindPoint bindPoint) { 59 | String key = bindPoint.key(); 60 | String group = bindPoint.group(); 61 | if (StringUtils.isNotEmpty(key)) { 62 | return new DataSourceBind(key, BindType.byAnno, null, null); 63 | } else if (StringUtils.isNotEmpty(group)) { 64 | return new DataSourceBind(null, BindType.byAnno, group, bindPoint.loadBalance()); 65 | } 66 | return null; 67 | } 68 | 69 | public String select(boolean updateActive) { 70 | if (updateActive) { 71 | active = active + 1; 72 | } 73 | if (StringUtils.isNotEmpty(this.select)) { 74 | return select; 75 | } 76 | if (StringUtils.isNotEmpty(key)) { 77 | this.select = key; 78 | } else if (StringUtils.isNotEmpty(group)) { 79 | this.select = LoadBalanceMap.get(loadBalance).select(this); 80 | } 81 | return select; 82 | } 83 | 84 | public void setPrev(DataSourceBind prev) { 85 | if (this.getBindType().equals(BindType.byMethod) && prev != null && prev.getBindType().equals(BindType.byAnno)) { 86 | this.prev = prev; 87 | } 88 | } 89 | 90 | public DataSourceBind getPrev() { 91 | return prev; 92 | } 93 | 94 | public String getKey() { 95 | return key; 96 | } 97 | 98 | public String getGroup() { 99 | return group; 100 | } 101 | 102 | public Class getLoadBalance() { 103 | return loadBalance; 104 | } 105 | 106 | public BindType getBindType() { 107 | return bindType; 108 | } 109 | 110 | public int getActive() { 111 | return active; 112 | } 113 | 114 | @Override 115 | public String toString() { 116 | return "DataSourceBind{" + 117 | "bindType=" + bindType + 118 | ", key='" + key + '\'' + 119 | ", group='" + group + '\'' + 120 | ", loadBalance=" + loadBalance + 121 | ", active='" + active + '\'' + 122 | '}'; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/tools/EntityTools.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.tools; 2 | 3 | import com.gysoft.jdbc.annotation.Column; 4 | import com.gysoft.jdbc.annotation.Table; 5 | import com.gysoft.jdbc.bean.GyjdbcException; 6 | import org.apache.commons.lang.StringUtils; 7 | import org.springframework.util.ReflectionUtils; 8 | 9 | import java.lang.reflect.Field; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | 13 | /** 14 | * 数据库实体映射工具类 15 | * 16 | * @author 彭佳佳 17 | */ 18 | public class EntityTools { 19 | 20 | /** 21 | * 根据实体类名,获取表名称 22 | * 23 | * @param entity 实体类型 24 | * @return String 表名称 25 | */ 26 | public static String getTableName(Class entity) { 27 | Table table = entity.getAnnotation(Table.class); 28 | if (null != table && !StringUtils.isEmpty(table.name())) { 29 | return table.name(); 30 | } else { 31 | StringBuffer tableName = new StringBuffer(); 32 | String entityName = entity.getSimpleName(); 33 | StringBuilder str = new StringBuilder(); 34 | char[] subStr = entityName.toCharArray(); 35 | int i = 0; 36 | char z = 'Z'; 37 | while (i < entityName.length()) { 38 | while (i < entityName.length() && subStr[i] > z) { 39 | if (Character.isLowerCase(subStr[i])) { 40 | str.append(String.valueOf(subStr[i]).toUpperCase()); 41 | } else { 42 | str.append(subStr[i]); 43 | } 44 | i++; 45 | } 46 | if (str.toString().length() > 0) { 47 | if ((i - entityName.length() == 0)) { 48 | tableName.append(str.toString()); 49 | } else { 50 | tableName.append(str.toString() + "_"); 51 | } 52 | } 53 | if (i < entityName.length()) { 54 | str = new StringBuilder(); 55 | str.append(subStr[i++]); 56 | } 57 | } 58 | return tableName.toString(); 59 | } 60 | } 61 | 62 | /** 63 | * 获取主键名称 64 | * 65 | * @param entity 实体类型 66 | * @return String 表主键 67 | */ 68 | public static String getPk(Class entity) { 69 | Table table = entity.getAnnotation(Table.class); 70 | if (null != table) { 71 | return table.pk(); 72 | } 73 | return "id"; 74 | } 75 | 76 | 77 | /** 78 | * 判断是否为主键 79 | * 80 | * @param entity 实体类型 81 | * @param field 属性 82 | * @return boolean true代表主键 false反之 83 | */ 84 | public static boolean isPk(Class entity, Field field) { 85 | String pk = getPk(entity); 86 | String columnName = field.getName(); 87 | //该字段是主键 88 | if (pk.equals(columnName)) { 89 | return true; 90 | } 91 | return false; 92 | } 93 | 94 | public static String getColumnName(Field field) { 95 | String columnName = field.getName(); 96 | Column anno = field.getAnnotation(Column.class); 97 | if (anno != null) { 98 | Method[] meth = anno.annotationType().getDeclaredMethods(); 99 | if (meth != null) { 100 | for (Method me : meth) { 101 | if (!me.isAccessible()) { 102 | me.setAccessible(true); 103 | } 104 | try { 105 | if (me.getName().equals("name")) { 106 | columnName = me.invoke(anno, null).toString(); 107 | } 108 | } catch (Exception e) { 109 | throw new GyjdbcException(e); 110 | } 111 | } 112 | } 113 | 114 | } 115 | return columnName; 116 | } 117 | 118 | public static String transferColumnName(String columnName) { 119 | if (!columnName.startsWith("`") || !columnName.endsWith("`")) { 120 | return "`" + columnName + "`"; 121 | } 122 | return columnName; 123 | } 124 | 125 | public static String transferFieldName(String fieldName) { 126 | if (fieldName.startsWith("`") && fieldName.endsWith("`")) { 127 | return fieldName.substring(1, fieldName.length() - 1); 128 | } 129 | return fieldName; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/SqlModifier.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import com.gysoft.jdbc.dao.EntityDao; 4 | import org.apache.commons.collections.CollectionUtils; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Optional; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * sql对象编辑器,可用于给sql统一添加查询条件、添加更新字段、添加插入字段等 13 | * 14 | * @author zhouning 15 | */ 16 | public class SqlModifier { 17 | private final SQL sql; 18 | 19 | public SqlModifier(SQL sql) { 20 | this.sql = sql; 21 | } 22 | 23 | public SqlModifier addUpdate(String key, Object val) throws Exception { 24 | if (EntityDao.SQL_UPDATE.equals(this.sql.getSqlType())) { 25 | sql.set(key, val); 26 | } 27 | return this; 28 | } 29 | 30 | public SqlModifier addInsert(String key, Object val) throws Exception { 31 | if (EntityDao.SQL_INSERT.equals(this.sql.getSqlType()) 32 | || EntityDao.SQL_REPLACE.equals(this.sql.getSqlType()) 33 | || EntityDao.SQL_INSERTIGNORE.equals(this.sql.getSqlType())) { 34 | List insertValues = sql.getInsertValues(); 35 | if (CollectionUtils.isNotEmpty(insertKeys()) && CollectionUtils.isNotEmpty(insertValues)) { 36 | sql.getInsert().getSecond().add(key); 37 | List newValues = new ArrayList<>(); 38 | List values = sql.getInsertValues(); 39 | for (Object[] arr : values) { 40 | Object[] tmp = new Object[arr.length + 1]; 41 | for (int i = 0; i < arr.length; i++) { 42 | tmp[i] = arr[i]; 43 | } 44 | tmp[arr.length] = val; 45 | newValues.add(tmp); 46 | } 47 | sql.setInsertValues(newValues); 48 | } 49 | } 50 | return this; 51 | } 52 | 53 | public SqlModifier addSelect(Object field) { 54 | if (EntityDao.SQL_SELECT.equals(this.sql.getSqlType())) { 55 | sql.getSelectFields().add(field); 56 | } 57 | return this; 58 | } 59 | 60 | public SqlModifier addAnd(Where where) { 61 | if (EntityDao.SQL_SELECT.equals(this.sql.getSqlType())) { 62 | sql.and(where); 63 | } 64 | return this; 65 | } 66 | 67 | public SqlModifier addOr(Where where) { 68 | if (EntityDao.SQL_SELECT.equals(this.sql.getSqlType())) { 69 | sql.or(where); 70 | } 71 | return this; 72 | } 73 | 74 | public SqlModifier addAndWhere(Where where) { 75 | if (EntityDao.SQL_SELECT.equals(this.sql.getSqlType())) { 76 | sql.andWhere(where); 77 | } 78 | return this; 79 | } 80 | 81 | public SqlModifier addOrWhere(Where where) { 82 | if (EntityDao.SQL_SELECT.equals(this.sql.getSqlType())) { 83 | sql.orWhere(where); 84 | } 85 | return this; 86 | } 87 | 88 | public void changeSqlType(String type) { 89 | sql.setSqlType(type); 90 | } 91 | 92 | public void changeTableName(String tableName) { 93 | if (sql.getSqlType().equals(EntityDao.SQL_CREATE)) { 94 | sql.getTableMeta().setName(tableName); 95 | } else { 96 | sql.getSqlPiepline().getHead().setTbName(tableName); 97 | } 98 | } 99 | 100 | public List selectKeys() { 101 | List result = new ArrayList<>(); 102 | if (sql.getSqlType().equals(EntityDao.SQL_SELECT) && CollectionUtils.isNotEmpty(sql.getSelectFields())) { 103 | return Optional.ofNullable(sql.getSqlPiepline().getHead().getSelectFields()).orElseGet(ArrayList::new); 104 | } 105 | return result; 106 | } 107 | 108 | public List updateKeys() { 109 | List result = new ArrayList<>(); 110 | if (sql.getSqlType().equals(EntityDao.SQL_UPDATE) && CollectionUtils.isNotEmpty(sql.getKvs())) { 111 | sql.getKvs().forEach(pair -> result.add(pair.getFirst().toString())); 112 | } 113 | return result; 114 | } 115 | 116 | public List insertKeys() { 117 | List result = new ArrayList<>(); 118 | if (EntityDao.SQL_INSERT.equals(this.sql.getSqlType()) 119 | || EntityDao.SQL_REPLACE.equals(this.sql.getSqlType()) 120 | || EntityDao.SQL_INSERTIGNORE.equals(this.sql.getSqlType())) { 121 | return Optional.ofNullable(sql.getInsert().getSecond()).orElseGet(ArrayList::new); 122 | } 123 | return result; 124 | } 125 | 126 | public String tableName() { 127 | if (sql.getSqlType().equals(EntityDao.SQL_CREATE)) { 128 | return sql.getTableMeta().getName(); 129 | } else if (sql.getSqlType().equals(EntityDao.SQL_DROP) || sql.getSqlType().equals(EntityDao.SQL_TRUNCATE)) { 130 | return sql.getDrunk().getTables().stream().collect(Collectors.joining(",")); 131 | } else { 132 | return sql.getSqlPiepline().getHead().getTbName(); 133 | } 134 | } 135 | 136 | public String sqlType() { 137 | return sql.getSqlType(); 138 | } 139 | 140 | public String sqlId() { 141 | return sql.getId(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Joins.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import com.gysoft.jdbc.tools.EntityTools; 4 | import com.gysoft.jdbc.tools.SqlMakeTools; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.function.Predicate; 9 | 10 | /** 11 | * @author 周宁 12 | */ 13 | public class Joins { 14 | 15 | private StringBuilder joinSql; 16 | 17 | private List criteriaProxys; 18 | 19 | public abstract class BaseJoin { 20 | 21 | public void setJoinType(JoinType joinType) { 22 | joinSql = new StringBuilder(String.format(joinSql.toString(), joinType.getType())); 23 | } 24 | 25 | public StringBuilder getJoinSql() { 26 | return new StringBuilder(joinSql.toString().replace("ON AND", "ON")); 27 | } 28 | 29 | public List getCriteriaProxys() { 30 | return criteriaProxys; 31 | } 32 | } 33 | 34 | public class With extends BaseJoin { 35 | public As as(String aliasName) { 36 | joinSql.append(" " + aliasName + " "); 37 | return getAs(); 38 | } 39 | 40 | public On on(String field, String field2) { 41 | joinSql.append(" ON " + field + " = " + field2 + " "); 42 | return getOn(); 43 | } 44 | } 45 | 46 | public class As extends BaseJoin { 47 | public On on(String field, String field2) { 48 | joinSql.append(" ON " + field + " = " + field2 + " "); 49 | return getOn(); 50 | } 51 | 52 | public On on(TypeFunction function, TypeFunction function2) { 53 | return this.on(TypeFunction.getLambdaColumnName(function), TypeFunction.getLambdaColumnName(function2)); 54 | } 55 | 56 | On on() { 57 | joinSql.append(" ON "); 58 | return getOn(); 59 | } 60 | } 61 | 62 | public class On extends BaseJoin { 63 | public On on(String field, String field2) { 64 | joinSql.append(" AND " + field + " = " + field2 + " "); 65 | return this; 66 | } 67 | 68 | public On on(TypeFunction function, TypeFunction function2) { 69 | return this.on(TypeFunction.getLambdaColumnName(function), TypeFunction.getLambdaColumnName(function2)); 70 | } 71 | 72 | public On and(TypeFunction function, Object value) { 73 | return this.and(TypeFunction.getLambdaColumnName(function), "=", value); 74 | } 75 | 76 | public On and(String key, Object value) { 77 | return this.and(key, "=", value); 78 | } 79 | 80 | public On and(TypeFunction function, String opt, Object value) { 81 | return this.and(TypeFunction.getLambdaColumnName(function), opt, value); 82 | } 83 | 84 | public On and(String key, String opt, Object value) { 85 | CriteriaProxy criteriaProxy = new CriteriaProxy(); 86 | Pair pair = SqlMakeTools.doCriteria(new Criteria().where(key, opt, value), new StringBuilder()); 87 | criteriaProxy.setSql(new StringBuilder(pair.getFirst().replace("WHERE", "").trim())); 88 | criteriaProxy.setParams(pair.getSecond()); 89 | criteriaProxy.setCriteriaType("AND"); 90 | criteriaProxy.setWhereParamsIndex(-1); 91 | criteriaProxys.add(criteriaProxy); 92 | return this; 93 | } 94 | 95 | public On andIfAbsent(String key, Object value) { 96 | return this.andIfAbsent(key, "=", value); 97 | } 98 | 99 | public On andIfAbsent(String key, String opt, Object value) { 100 | if (AuxiliaryOperation.getDefaultPredicate().test(value)) { 101 | return and(key, opt, value); 102 | } 103 | return this; 104 | } 105 | 106 | public On andIfAbsent(String key, Object value, Predicate predicate) { 107 | return this.andIfAbsent(key, "=", value, predicate); 108 | } 109 | 110 | public On andIfAbsent(String key, String opt, Object value, Predicate predicate) { 111 | if (predicate.test(value)) { 112 | return and(key, opt, value); 113 | } 114 | return this; 115 | } 116 | } 117 | 118 | public Joins() { 119 | this.joinSql = new StringBuilder(); 120 | this.criteriaProxys = new ArrayList<>(); 121 | } 122 | 123 | public With with(Class clss) { 124 | joinSql.append(" %s " + EntityTools.getTableName(clss)); 125 | return getWith(); 126 | } 127 | 128 | public With with(String tb) { 129 | joinSql.append(" %s " + tb); 130 | return getWith(); 131 | } 132 | 133 | public With with(SQL sql) { 134 | Pair pair = SqlMakeTools.useSql(sql); 135 | joinSql.append(" %s " + "(" + pair.getFirst() + ")"); 136 | CriteriaProxy criteriaProxy = new CriteriaProxy(); 137 | criteriaProxy.setWhereParamsIndex(-1); 138 | criteriaProxy.setParams(pair.getSecond()); 139 | criteriaProxy.setCriteriaType("WITH"); 140 | criteriaProxys.add(criteriaProxy); 141 | return getWith(); 142 | } 143 | 144 | public StringBuilder getJoinSql() { 145 | return joinSql; 146 | } 147 | 148 | private With getWith() { 149 | return new With(); 150 | } 151 | 152 | private As getAs() { 153 | return new As(); 154 | } 155 | 156 | private On getOn() { 157 | return new On(); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/Column.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import java.sql.JDBCType; 4 | 5 | /** 6 | * @author 周宁 7 | */ 8 | public class Column { 9 | /** 10 | * 表 11 | */ 12 | private Table table; 13 | /** 14 | * 行元数据 15 | */ 16 | private ColumnMeta columnMeta; 17 | 18 | public Column(Table table) { 19 | this.table = table; 20 | columnMeta = new ColumnMeta(); 21 | } 22 | 23 | public Column jdbcType(JDBCType jdbcType) { 24 | columnMeta.setJdbcType(jdbcType); 25 | return this; 26 | } 27 | 28 | public Column notNull() { 29 | columnMeta.setNotNull(true); 30 | return this; 31 | } 32 | 33 | public Column defaultVal(String val) { 34 | columnMeta.setVal(val); 35 | return this; 36 | } 37 | 38 | public Column defaultCurrentTimestamp() { 39 | return defaultVal("CURRENT_TIMESTAMP"); 40 | } 41 | 42 | public Column defaultNull() { 43 | return defaultVal("NULL"); 44 | } 45 | 46 | public Column length(int length) { 47 | columnMeta.setLength(length); 48 | columnMeta.setPrecision(length); 49 | return this; 50 | } 51 | 52 | public Column length(int precision, int scale) { 53 | columnMeta.setLength(precision); 54 | columnMeta.setScale(scale); 55 | columnMeta.setPrecision(precision); 56 | return this; 57 | } 58 | 59 | public Column varchar(int length) { 60 | return this.jdbcType(JDBCType.VARCHAR).length(length); 61 | } 62 | 63 | public Column number(int precision, int scale) { 64 | return this.jdbcType(JDBCType.NUMERIC).length(precision, scale); 65 | } 66 | 67 | public Column number(int len) { 68 | return this.jdbcType(JDBCType.NUMERIC).length(len, 0); 69 | } 70 | 71 | public Column clob() { 72 | return this.jdbcType(JDBCType.CLOB); 73 | } 74 | 75 | public Column integer() { 76 | return this.jdbcType(JDBCType.INTEGER); 77 | } 78 | 79 | public Column datetime() { 80 | return this.jdbcType(JDBCType.TIMESTAMP); 81 | } 82 | 83 | public Column datetime(int length) { 84 | return this.jdbcType(JDBCType.TIMESTAMP).length(length); 85 | } 86 | 87 | public Column tinyint() { 88 | return this.jdbcType(JDBCType.TINYINT); 89 | } 90 | 91 | public Column primary() { 92 | columnMeta.setPrimaryKey(true); 93 | return this; 94 | } 95 | 96 | public Column name(String name) { 97 | columnMeta.setName(name); 98 | return this; 99 | } 100 | 101 | public Column comment(String comment) { 102 | columnMeta.setComment(comment); 103 | return this; 104 | } 105 | 106 | public Column autoIncrement() { 107 | columnMeta.setAutoIncr(true); 108 | return this; 109 | } 110 | 111 | public Table commit() { 112 | columnMeta.setDataType(dataType(this.columnMeta)); 113 | table.getTableMeta().getColumns().add(this.columnMeta); 114 | return table; 115 | } 116 | 117 | private String dataType(ColumnMeta meta) { 118 | if (meta.getJdbcType() == null) { 119 | throw new GyjdbcException("JDBCType is null"); 120 | } 121 | if (meta.getJdbcType().equals(JDBCType.CHAR)) { 122 | return "char(" + meta.getLength() + ")"; 123 | } 124 | if (meta.getJdbcType().equals(JDBCType.VARCHAR)) { 125 | return "varchar(" + meta.getLength() + ")"; 126 | } 127 | if (meta.getJdbcType().equals(JDBCType.TIMESTAMP)) { 128 | return "datetime(" + Math.min(6, meta.getLength()) + ")"; 129 | } 130 | if (meta.getJdbcType().equals(JDBCType.TIME)) { 131 | return "time"; 132 | } 133 | if (meta.getJdbcType().equals(JDBCType.DATE)) { 134 | return "date"; 135 | } 136 | if (meta.getJdbcType().equals(JDBCType.CLOB)) { 137 | return "longtext"; 138 | } 139 | if (meta.getJdbcType().equals(JDBCType.LONGVARBINARY)) { 140 | return "longblob"; 141 | } 142 | if (meta.getJdbcType().equals(JDBCType.LONGVARCHAR)) { 143 | return "longtext"; 144 | } 145 | if (meta.getJdbcType().equals(JDBCType.BLOB)) { 146 | return "blob"; 147 | } 148 | if (meta.getJdbcType().equals(JDBCType.BIGINT)) { 149 | if (meta.getLength() > 0) { 150 | return "bigint(" + meta.getLength() + ")"; 151 | } else { 152 | return "bigint"; 153 | } 154 | } 155 | if (meta.getJdbcType().equals(JDBCType.INTEGER)) { 156 | if (meta.getLength() > 0) { 157 | return "int(" + meta.getLength() + ")"; 158 | } else { 159 | return "int"; 160 | } 161 | } 162 | if (meta.getJdbcType().equals(JDBCType.TINYINT)) { 163 | if (meta.getLength() > 0) { 164 | return "tinyint(" + meta.getLength() + ")"; 165 | } else { 166 | return "tinyint"; 167 | } 168 | } 169 | if (meta.getJdbcType().equals(JDBCType.BOOLEAN)) { 170 | return "tinyint(1)"; 171 | } 172 | if (meta.getJdbcType().equals(JDBCType.NUMERIC) || meta.getJdbcType().equals(JDBCType.DECIMAL)) { 173 | if (meta.getPrecision() <= 0 || meta.getScale() < 0) { 174 | return "decimal(10,0)"; 175 | } 176 | return "decimal(" + meta.getPrecision() + "," + meta.getScale() + ")"; 177 | } 178 | if (meta.getJdbcType().equals(JDBCType.DOUBLE)) { 179 | if (meta.getLength() > 0) { 180 | return "double(" + meta.getPrecision() + "," + meta.getScale() + ")"; 181 | } else { 182 | return "double"; 183 | } 184 | } 185 | if (meta.getJdbcType().equals(JDBCType.OTHER)) { 186 | return "json"; 187 | } 188 | throw new GyjdbcException("unknown jdbcType"); 189 | } 190 | 191 | 192 | } 193 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | io.github.springstudent 7 | GyJdbc 8 | 1.4.7.RELEASE 9 | jar 10 | https://github.com/SpringStudent/GyJdbc 11 | a nice sql maker 12 | 13 | GyJdbc 14 | 15 | 16 | 17 | The Apache License, Version 2.0 18 | http://www.apache.org/licenses/LICENSE-2.0.txt 19 | 20 | 21 | 22 | 23 | scm:git:https://github.com/SpringStudent/GyJdbc.git 24 | scm:git:https://github.com/SpringStudent/GyJdbc.git 25 | https://github.com/SpringStudent/GyJdbc 26 | ${project.version} 27 | 28 | 29 | 30 | 31 | zhouning 32 | 2267431887@qq.com 33 | http://www.bigfacecat.site:827 34 | DJZ 35 | 36 | 37 | 38 | 39 | 40 | ossrh 41 | https://s01.oss.sonatype.org/content/repositories/snapshots 42 | 43 | 44 | ossrh 45 | https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ 46 | 47 | 48 | 49 | 50 | 51 | 8 52 | 8 53 | 1.8 54 | UTF-8 55 | 4.3.14.RELEASE 56 | 57 | 58 | 59 | 60 | junit 61 | junit 62 | 4.11 63 | test 64 | 65 | 66 | commons-collections 67 | commons-collections 68 | 3.2.2 69 | 70 | 71 | commons-lang 72 | commons-lang 73 | 2.6 74 | 75 | 76 | org.springframework 77 | spring-jdbc 78 | ${spring.version} 79 | 80 | 81 | org.springframework 82 | spring-context 83 | ${spring.version} 84 | 85 | 86 | commons-beanutils 87 | commons-beanutils 88 | 1.9.3 89 | 90 | 91 | org.aspectj 92 | aspectjtools 93 | 1.9.1 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | org.sonatype.central 102 | central-publishing-maven-plugin 103 | 0.4.0 104 | true 105 | 106 | ossrh 107 | true 108 | 109 | 110 | 111 | 112 | org.apache.maven.plugins 113 | maven-source-plugin 114 | 2.2.1 115 | 116 | 117 | attach-sources 118 | 119 | jar-no-fork 120 | 121 | 122 | 123 | 124 | 125 | 126 | org.apache.maven.plugins 127 | maven-javadoc-plugin 128 | 2.9.1 129 | 130 | 131 | attach-javadocs 132 | 133 | jar 134 | 135 | 136 | 137 | 138 | 139 | org.apache.maven.plugins 140 | maven-gpg-plugin 141 | 1.6 142 | 143 | 144 | sign-artifacts 145 | verify 146 | 147 | sign 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/dao/EntityDao.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.dao; 2 | 3 | import com.gysoft.jdbc.bean.*; 4 | import com.gysoft.jdbc.multi.balance.LoadBalance; 5 | import org.springframework.jdbc.core.ResultSetExtractor; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import org.springframework.jdbc.core.RowMapper; 12 | 13 | /** 14 | * @author 周宁 15 | */ 16 | public interface EntityDao { 17 | 18 | /** 19 | * 设置一些操作的常量 20 | */ 21 | String SQL_SELECT = "select"; 22 | String SQL_INSERT = "insert"; 23 | String SQL_INSERTIGNORE = "insert ignore"; 24 | String SQL_REPLACE = "replace"; 25 | String SQL_UPDATE = "update"; 26 | String SQL_DELETE = "delete"; 27 | String SQL_TRUNCATE = "truncate"; 28 | String SQL_DROP = "drop"; 29 | String SQL_CREATE = "create"; 30 | 31 | /** 32 | * 插入指定的持久化对象 33 | * 34 | * @param t 实体对象 35 | * @throws Exception sql错误抛出异常 36 | */ 37 | int save(T t) throws Exception; 38 | 39 | /** 40 | * 修改指定的持久化对象 41 | * 42 | * @param t 实体对象 43 | * @throws Exception sql错误抛出异常 44 | */ 45 | int update(T t) throws Exception; 46 | 47 | /** 48 | * 批量保存指定的持久化对象 49 | * 50 | * @param list 实体对象集合 51 | * @throws Exception sql错误抛出异常 52 | */ 53 | void batchSave(List list) throws Exception; 54 | 55 | /** 56 | * 保存或更新持久化对象 57 | * 58 | * @param t 实体对象 59 | * @throws Exception sql错误抛出异常 60 | */ 61 | void saveOrUpdate(T t) throws Exception; 62 | 63 | /** 64 | * 批量保存指定的持久化对象 65 | * 66 | * @param list 实体对象集合 67 | * @return int插入记录的条数 68 | * @throws Exception 69 | */ 70 | int saveAll(List list) throws Exception; 71 | 72 | /** 73 | * 批量更新指定的持久化对象 74 | * 75 | * @param list 实体对象集合 76 | * @throws Exception sql错误抛出异常 77 | */ 78 | void batchUpdate(List list) throws Exception; 79 | 80 | /** 81 | * 根据主键删除 82 | * 83 | * @param id 实体主键 84 | * @throws Exception sql错误抛出异常 85 | */ 86 | int delete(Id id) throws Exception; 87 | 88 | /** 89 | * 根据where条件删除 90 | * 91 | * @param criteria 条件参数 92 | * @throws Exception sql错误抛出异常 93 | */ 94 | int deleteWithCriteria(Criteria criteria) throws Exception; 95 | 96 | /** 97 | * 根据主键批量删除 98 | * 99 | * @param ids 主键集合 100 | * @throws Exception sql错误抛出异常 101 | */ 102 | int batchDelete(List ids) throws Exception; 103 | 104 | /** 105 | * 根据ID检索持久化对象 106 | * 107 | * @param id 主键 108 | * @return T 实体对象 109 | * @throws Exception sql错误抛出异常 110 | */ 111 | T queryOne(Id id) throws Exception; 112 | 113 | /** 114 | * 根据ID检索持久化对象 115 | * 116 | * @param id 主键 117 | * @param tRowMapper 自定义实体映射mapper 118 | * @return T 实体对象 119 | * @throws Exception sql错误抛出异常 120 | */ 121 | T queryOne(Id id, RowMapper tRowMapper) throws Exception; 122 | 123 | /** 124 | * 检索所有持久化对象 125 | * 126 | * @return List 实体对象列表 127 | * @throws Exception sql错误抛出异常 128 | */ 129 | List queryAll() throws Exception; 130 | 131 | /** 132 | * 检索所有持久化对象 133 | * 134 | * @param tRowMapper 自定义实体映射mapper 135 | * @return List 实体对象列表 136 | * @throws Exception sql错误抛出异常 137 | */ 138 | List queryAll(RowMapper tRowMapper) throws Exception; 139 | 140 | /** 141 | * 分页查询 142 | * 143 | * @param page 分页条件 144 | * @return PageResult 分页查询结果 145 | * @throws Exception sql错误抛出异常 146 | */ 147 | PageResult pageQuery(Page page) throws Exception; 148 | 149 | /** 150 | * 分页查询 151 | * 152 | * @param page 分页条件 153 | * @param tRowMapper 自定义实体映射mapper 154 | * @return PageResult 分页查询结果 155 | * @throws Exception sql错误抛出异常 156 | */ 157 | PageResult pageQuery(Page page, RowMapper tRowMapper) throws Exception; 158 | 159 | /** 160 | * 分页条件查询 161 | * 162 | * @param page 分页条件 163 | * @param criteria 查询条件 164 | * @return PageResult 分页查询结果 165 | * @throws Exception sql错误抛出异常 166 | */ 167 | PageResult pageQueryWithCriteria(Page page, Criteria criteria) throws Exception; 168 | 169 | /** 170 | * 分页条件查询 171 | * 172 | * @param page 分页条件 173 | * @param criteria 查询条件 174 | * @param tRowMapper 自定义实体映射mapper 175 | * @return PageResult 分页查询结果 176 | * @throws Exception sql错误抛出异常 177 | */ 178 | PageResult pageQueryWithCriteria(Page page, Criteria criteria, RowMapper tRowMapper) throws Exception; 179 | 180 | /** 181 | * 条件查询 182 | * 183 | * @param criteria 查询条件 184 | * @return List 结果集 185 | * @throws Exception sql错误抛出异常 186 | */ 187 | List queryWithCriteria(Criteria criteria) throws Exception; 188 | 189 | /** 190 | * 根据criteria判断是否有满足条件的数据 191 | * 192 | * @param criteria 查询条件 193 | * @return boolean 结果类型,数据是否存在 194 | * @throws Exception sql错误抛出异常 195 | */ 196 | boolean existsWithCriteria(Criteria criteria) throws Exception; 197 | 198 | /** 199 | * 条件查询 200 | * 201 | * @param criteria 查询条件 202 | * @param tRowMapper 自定义实体映射mapper 203 | * @return List 结果集 204 | * @throws Exception sql错误抛出异常 205 | */ 206 | List queryWithCriteria(Criteria criteria, RowMapper tRowMapper) throws Exception; 207 | 208 | /** 209 | * 根据条件查询 210 | * 211 | * @param criteria 查询条件 212 | * @return T 实体对象 213 | * @throws Exception sql错误抛出异常 214 | */ 215 | T queryOne(Criteria criteria) throws Exception; 216 | 217 | /** 218 | * 根据条件查询 219 | * 220 | * @param criteria 查询条件 221 | * @param tRowMapper 自定义实体映射mapper 222 | * @return T 实体对象 223 | * @throws Exception sql错误抛出异常 224 | */ 225 | T queryOne(Criteria criteria, RowMapper tRowMapper) throws Exception; 226 | 227 | /** 228 | * 根据sql查询 229 | * 230 | * @param sql sql拼接器 231 | * @param 查询结果类型 232 | * @throws Exception sql错误抛出异常 233 | */ 234 | Result queryWithSql(Class clss, SQL sql) throws Exception; 235 | 236 | /** 237 | * 根据sql更新 238 | * 239 | * @param sql sql拼接器 240 | * @return int 更新条目数量 241 | * @throws Exception sql错误抛出异常 242 | */ 243 | int updateWithSql(SQL sql) throws Exception; 244 | 245 | /** 246 | * 根据sql删除 247 | * 248 | * @param sql sql拼接器 249 | * @return int 删除条目数量 250 | * @throws Exception sql错误抛出异常 251 | */ 252 | int deleteWithSql(SQL sql) throws Exception; 253 | 254 | /** 255 | * 键值对查询 256 | * 257 | * @param sql sql拼接器 258 | * @param resultSetExtractor 结果抽取器 259 | * @param 键类型 260 | * @param 值类型 261 | * @return Map 返回类型Map 262 | * @throws Exception sql错误抛出异常 263 | */ 264 | Map queryMapWithSql(SQL sql, ResultSetExtractor> resultSetExtractor) throws Exception; 265 | 266 | /** 267 | * 根据条件查询Map集合 268 | * 269 | * @param sql sql拼接器 270 | * @return List 结果集 271 | * @throws Exception sql错误抛出异常 272 | */ 273 | List> queryMapsWithSql(SQL sql) throws Exception; 274 | 275 | /** 276 | * 根据sql查询一个int值 277 | * 278 | * @param sql sql拼接器 279 | * @return Integer 结果类型,一般为查询数量 280 | * @throws Exception sql错误抛出异常 281 | */ 282 | Integer queryIntegerWithSql(SQL sql) throws Exception; 283 | 284 | /** 285 | * 根据sql判断是否有满足条件的数据 286 | * 287 | * @param sql sql拼接器 288 | * @return boolean 结果类型,数据是否存在 289 | * @throws Exception sql错误抛出异常 290 | */ 291 | boolean existsWithSql(SQL sql) throws Exception; 292 | 293 | /** 294 | * 根据sql插入数据 295 | * 296 | * @param sql sql拼接器 297 | * @return int 更新条目数量 298 | * @throws Exception sql错误抛出异常 299 | */ 300 | int insertWithSql(SQL sql) throws Exception; 301 | 302 | /** 303 | * 根据sql创建表;如果有指定数据将数据插入 304 | * 305 | * @param sql sql拼接器 306 | * @return String 表名称 307 | * @throws Exception sql错误抛出异常 308 | */ 309 | String createWithSql(SQL sql) throws Exception; 310 | 311 | /** 312 | * 删除表 313 | * 314 | * @throws Exception sql错误抛出异常 315 | */ 316 | void drop() throws Exception; 317 | 318 | /** 319 | * 清除表数据和delete不同的是,该方法不需要where 320 | * 条件并且数据一旦清除不可恢复 321 | * 322 | * @throws Exception sql错误抛出异常 323 | */ 324 | void truncate() throws Exception; 325 | 326 | /** 327 | * 喝醉了干一些犯浑的事情,比如删除表,清楚数据 328 | * 329 | * @param sql sql拼接器 330 | * @throws Exception sql错误抛出异常 331 | */ 332 | void drunk(SQL sql) throws Exception; 333 | 334 | /** 335 | * 绑定指定key的数据源 336 | * 337 | * @param bindKey 数据源dataSource 338 | * @return EntityDao 当前的dao对象 339 | * @throws Exception sql错误抛出异常 340 | */ 341 | EntityDao bindKey(String bindKey) throws Exception; 342 | 343 | /** 344 | * 绑定指定组的数据源 345 | * 346 | * @param group 指定的数据源组 347 | * @param loadBalance 负载均衡策略 348 | * @return EntityDao 当前的dao对象 349 | * @throws Exception sql错误抛出异常 350 | */ 351 | EntityDao bindGroup(String group, Class loadBalance) throws Exception; 352 | 353 | /** 354 | * 绑定指定组的数据源 355 | * 356 | * @param group 指定的数据源组 357 | * @return EntityDao 当前的dao对象 358 | * @throws Exception sql错误抛出异常 359 | */ 360 | EntityDao bindGroup(String group) throws Exception; 361 | 362 | } 363 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and 10 | distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 13 | owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities 16 | that control, are controlled by, or are under common control with that entity. 17 | For the purposes of this definition, "control" means (i) the power, direct or 18 | indirect, to cause the direction or management of such entity, whether by 19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 20 | outstanding shares, or (iii) beneficial ownership of such entity. 21 | 22 | "You" (or "Your") shall mean an individual or Legal Entity exercising 23 | permissions granted by this License. 24 | 25 | "Source" form shall mean the preferred form for making modifications, including 26 | but not limited to software source code, documentation source, and configuration 27 | files. 28 | 29 | "Object" form shall mean any form resulting from mechanical transformation or 30 | translation of a Source form, including but not limited to compiled object code, 31 | generated documentation, and conversions to other media types. 32 | 33 | "Work" shall mean the work of authorship, whether in Source or Object form, made 34 | available under the License, as indicated by a copyright notice that is included 35 | in or attached to the work (an example is provided in the Appendix below). 36 | 37 | "Derivative Works" shall mean any work, whether in Source or Object form, that 38 | is based on (or derived from) the Work and for which the editorial revisions, 39 | annotations, elaborations, or other modifications represent, as a whole, an 40 | original work of authorship. For the purposes of this License, Derivative Works 41 | shall not include works that remain separable from, or merely link (or bind by 42 | name) to the interfaces of, the Work and Derivative Works thereof. 43 | 44 | "Contribution" shall mean any work of authorship, including the original version 45 | of the Work and any modifications or additions to that Work or Derivative Works 46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work 47 | by the copyright owner or by an individual or Legal Entity authorized to submit 48 | on behalf of the copyright owner. For the purposes of this definition, 49 | "submitted" means any form of electronic, verbal, or written communication sent 50 | to the Licensor or its representatives, including but not limited to 51 | communication on electronic mailing lists, source code control systems, and 52 | issue tracking systems that are managed by, or on behalf of, the Licensor for 53 | the purpose of discussing and improving the Work, but excluding communication 54 | that is conspicuously marked or otherwise designated in writing by the copyright 55 | owner as "Not a Contribution." 56 | 57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 58 | of whom a Contribution has been received by Licensor and subsequently 59 | incorporated within the Work. 60 | 61 | 2. Grant of Copyright License. 62 | 63 | Subject to the terms and conditions of this License, each Contributor hereby 64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 65 | irrevocable copyright license to reproduce, prepare Derivative Works of, 66 | publicly display, publicly perform, sublicense, and distribute the Work and such 67 | Derivative Works in Source or Object form. 68 | 69 | 3. Grant of Patent License. 70 | 71 | Subject to the terms and conditions of this License, each Contributor hereby 72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 73 | irrevocable (except as stated in this section) patent license to make, have 74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where 75 | such license applies only to those patent claims licensable by such Contributor 76 | that are necessarily infringed by their Contribution(s) alone or by combination 77 | of their Contribution(s) with the Work to which such Contribution(s) was 78 | submitted. If You institute patent litigation against any entity (including a 79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 80 | Contribution incorporated within the Work constitutes direct or contributory 81 | patent infringement, then any patent licenses granted to You under this License 82 | for that Work shall terminate as of the date such litigation is filed. 83 | 84 | 4. Redistribution. 85 | 86 | You may reproduce and distribute copies of the Work or Derivative Works thereof 87 | in any medium, with or without modifications, and in Source or Object form, 88 | provided that You meet the following conditions: 89 | 90 | You must give any other recipients of the Work or Derivative Works a copy of 91 | this License; and 92 | You must cause any modified files to carry prominent notices stating that You 93 | changed the files; and 94 | You must retain, in the Source form of any Derivative Works that You distribute, 95 | all copyright, patent, trademark, and attribution notices from the Source form 96 | of the Work, excluding those notices that do not pertain to any part of the 97 | Derivative Works; and 98 | If the Work includes a "NOTICE" text file as part of its distribution, then any 99 | Derivative Works that You distribute must include a readable copy of the 100 | attribution notices contained within such NOTICE file, excluding those notices 101 | that do not pertain to any part of the Derivative Works, in at least one of the 102 | following places: within a NOTICE text file distributed as part of the 103 | Derivative Works; within the Source form or documentation, if provided along 104 | with the Derivative Works; or, within a display generated by the Derivative 105 | Works, if and wherever such third-party notices normally appear. The contents of 106 | the NOTICE file are for informational purposes only and do not modify the 107 | License. You may add Your own attribution notices within Derivative Works that 108 | You distribute, alongside or as an addendum to the NOTICE text from the Work, 109 | provided that such additional attribution notices cannot be construed as 110 | modifying the License. 111 | You may add Your own copyright statement to Your modifications and may provide 112 | additional or different license terms and conditions for use, reproduction, or 113 | distribution of Your modifications, or for any such Derivative Works as a whole, 114 | provided Your use, reproduction, and distribution of the Work otherwise complies 115 | with the conditions stated in this License. 116 | 117 | 5. Submission of Contributions. 118 | 119 | Unless You explicitly state otherwise, any Contribution intentionally submitted 120 | for inclusion in the Work by You to the Licensor shall be under the terms and 121 | conditions of this License, without any additional terms or conditions. 122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of 123 | any separate license agreement you may have executed with Licensor regarding 124 | such Contributions. 125 | 126 | 6. Trademarks. 127 | 128 | This License does not grant permission to use the trade names, trademarks, 129 | service marks, or product names of the Licensor, except as required for 130 | reasonable and customary use in describing the origin of the Work and 131 | reproducing the content of the NOTICE file. 132 | 133 | 7. Disclaimer of Warranty. 134 | 135 | Unless required by applicable law or agreed to in writing, Licensor provides the 136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, 137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, 138 | including, without limitation, any warranties or conditions of TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are 140 | solely responsible for determining the appropriateness of using or 141 | redistributing the Work and assume any risks associated with Your exercise of 142 | permissions under this License. 143 | 144 | 8. Limitation of Liability. 145 | 146 | In no event and under no legal theory, whether in tort (including negligence), 147 | contract, or otherwise, unless required by applicable law (such as deliberate 148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be 149 | liable to You for damages, including any direct, indirect, special, incidental, 150 | or consequential damages of any character arising as a result of this License or 151 | out of the use or inability to use the Work (including but not limited to 152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or 153 | any and all other commercial damages or losses), even if such Contributor has 154 | been advised of the possibility of such damages. 155 | 156 | 9. Accepting Warranty or Additional Liability. 157 | 158 | While redistributing the Work or Derivative Works thereof, You may choose to 159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or 160 | other liability obligations and/or rights consistent with this License. However, 161 | in accepting such obligations, You may act only on Your own behalf and on Your 162 | sole responsibility, not on behalf of any other Contributor, and only if You 163 | agree to indemnify, defend, and hold each Contributor harmless for any liability 164 | incurred by, or claims asserted against, such Contributor by reason of your 165 | accepting any such warranty or additional liability. 166 | 167 | END OF TERMS AND CONDITIONS 168 | 169 | APPENDIX: How to apply the Apache License to your work 170 | 171 | To apply the Apache License to your work, attach the following boilerplate 172 | notice, with the fields enclosed by brackets "{}" replaced with your own 173 | identifying information. (Don't include the brackets!) The text should be 174 | enclosed in the appropriate comment syntax for the file format. We also 175 | recommend that a file or class name and description of purpose be included on 176 | the same "printed page" as the copyright notice for easier identification within 177 | third-party archives. 178 | 179 | Copyright 2018 SpringStudent 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 是什么 2 | 3 | GyJdbc基于jdbctemplate的类似JPA的持久层框架封装,使用优势: 4 | 5 | 1. **Dao层0代码,再也不需要为Dao层的方法名称命名掉头发。** 6 | 2. **链式SQL配合lambda表达式,既装B又简洁。** 7 | 3. **强悍的SQL拼接,支持作者已知的所有SQL语法。** 8 | 4. **学习成本极低,靠近SQL语法,开发者使用起来会像平时一样写SQL一样简单。** 9 | 5. **提供类JPA语法,类MongoTemplate的SQL拼接语法** 10 | 6. **支持多数据源,多数据源的负载均衡,仅需一个注解或者一个方法调用。** 11 | 12 | #### 快速开始 13 | 14 | **step1.添加maven坐标** 15 | 16 | ```xml 17 | 18 | 19 | io.github.springstudent 20 | GyJdbc 21 | 1.4.7.RELEASE 22 | 23 | ``` 24 | 25 | **step2.定义Pojo类,对应数据库中的一张表。** 26 | 27 | `@Table`注解,`name`定义pojo类与数据库表的关系,`pk`指定表的主键 28 | 29 | ```java 30 | 31 | @Table(name = "tb_user", pk = "id") 32 | public class TbUser { 33 | private String id; 34 | private String name; 35 | private String realName; 36 | private String pwd; 37 | private String email; 38 | private String mobile; 39 | private Date birth; 40 | private Integer age; 41 | private String career; 42 | private Integer isActive = 0; 43 | private Integer roleId; 44 | } 45 | ``` 46 | 47 | **step3.定义Dao与DaoImpl,分别继承自EntityDao和EntityDaoImpl** 48 | 49 | ```java 50 | public interface TbUserDao extends EntityDao { 51 | 52 | } 53 | 54 | @Repository 55 | public class TbUserDaoImpl extends EntityDaoImpl implements TbUserDao { 56 | 57 | } 58 | ``` 59 | 60 | **step4.在Service层注入Dao,使用EntityDao提供的方法完成增、删、改、查** 61 | 62 | 63 | 64 | ```java 65 | void save(T t)throws Exception; 66 | void batchSave(List list)throws Exception; 67 | int insertWithSql(SQL sql)throws Exception; 68 | ``` 69 | 70 | 71 | 72 | ```java 73 | void delete(Id id)throws Exception; 74 | void deleteWithCriteria(Criteria criteria)throws Exception; 75 | void batchDelete(List ids)throws Exception; 76 | int deleteWithSql(SQL sql)throws Exception; 77 | void truncate()throws Exception; 78 | void drop()throws Exception; 79 | void drunk(SQL sql)throws Exception; 80 | ``` 81 | 82 | 83 | 84 | ```java 85 | void update(T t)throws Exception; 86 | void batchUpdate(List list)throws Exception; 87 | int updateWithSql(SQL sql)throws Exception; 88 | ``` 89 | 90 | 91 | 92 | ```java 93 | T queryOne(Id id)throws Exception; 94 | List queryAll()throws Exception; 95 | PageResult pageQuery(Page page)throws Exception; 96 | PageResult pageQueryWithCriteria(Page page,Criteria criteria)throws Exception; 97 | List queryWithCriteria(Criteria criteria)throws Exception; 98 | Result queryWithSql(Class clss,SQL sql)throws Exception; 99 | List>queryMapsWithSql(SQL sql)throws Exception; 100 | Map queryMapWithSql(SQL sql,ResultSetExtractor>resultSetExtractor)throws Exception; 101 | 102 | ``` 103 | 104 | `Criteria语法示例:` 105 | 106 | ```java 107 | //where name = 'zhouning' 108 | new Criteria().where(TbUser::getName,"zhouning").andIfAbsent(TbUser::getName,null); 109 | //where name in ('zhouning','yinhw') 110 | new Criteria().in(TbUser::getName,Arrays.asList("zhouning","yinhw")); 111 | //where age < 28 order by age desc 112 | new Criteria().lt(TbUser::getAge,28).orderBy(new Sort(TbUser::getAge); 113 | //where age < 20 and (name like '%zhou%' or realName like 'zhouning') 114 | new Criteria().lt(TbUser::getAge,20).andCriteria(new Criteria().like(TbUser::getName,"zhou").orLike(TbUser::getRealName,"周")); 115 | ``` 116 | 117 | `SQL语法示例:` 118 | 119 | ```java 120 | new SQL().select(TbUser::getName,TbUser::getEmail,TbUser::getRealName,TbUser::getMobile).from(TbUser.class).where(TbUser::getIsActive,1); 121 | new SQL().select("age",countAs("age").as("num")).from(TbUser.class).orderBy(new Sort(TbUser::getAge)).groupBy(TbUser::getAge); 122 | new SQL().update(TbUser.class).set(TbUser::getRealName,"元林").set(TbUser::getEmail,"13888888888@163.com").where(TbUser::getName,"Smith"); 123 | new SQL().insertInto(TbAccount.class,"userName","realName").values("test","测试").values("test2","测试2"); 124 | new SQL().delete().from(TbUser.class).gt(TbUser::getAge,20); 125 | //类似MongoTemplate的Criteria拼接 126 | new SQL().select("*").from("table1").where("f1",1).and(Where.where("f2").like("a").or("f3").gte(1).and("f4").in(Arrays.asList(2,3,4))) 127 | //类似JPA的Predict使用 128 | List params=new ArrayList<>(); 129 | params.add(WhereParam.where("f1").like("v1")); 130 | params.add(WhereParam.where("f2").in(Arrays.asList(1,2,3))); 131 | sql=new SQL().select("*").from("table2").and(Opt.AND,params); 132 | ``` 133 | 134 | #### 谁在用Gyjdbc 135 | 136 | https://github.com/SpringStudent/remote-desktop-control 137 | 138 | https://github.com/SpringStudent/webrtc-meetings 139 | 140 | #### SQLInterceptor.java 141 | 最终拦截的方法的签名为entityDao.xxxSql,即方法参数传入的是SQL,beforeBuild在构建sql和参数之前执行,而afterSql在构建sql之后执行。可以通过实现该接口方便的给sql批量添加一些通用的查询字段、更新字段sql审计的逻辑,以下是一个具体点的demo 142 | ```java 143 | @Component 144 | public class SQLInterceptorImpl implements SQLInterceptor { 145 | 146 | @Override 147 | public void beforeBuild(SQLType sqlType, SqlModifier sqlModifier) throws Exception { 148 | //粗粒度 通过sql类型统一添加需要更新和插入的字段 149 | if (sqlType.equals(SQLType.Update)) { 150 | if (sqlModifier.tableName().startsWith("sys_tb_")) { 151 | sqlModifier.addUpdate("updateTime", new Date()); 152 | sqlModifier.addUpdate("updateUser", "admin"); 153 | } 154 | } else if (sqlType.equals(SQLType.Insert)) { 155 | if (sqlModifier.tableName().startsWith("sys_tb_")) { 156 | sqlModifier.addInsert("createTime", new Date()); 157 | sqlModifier.addInsert("createUser", "admin"); 158 | sqlModifier.addInsert("updateTime", new Date()); 159 | sqlModifier.addInsert("updateUser", "admin"); 160 | } 161 | } 162 | 163 | //精细粒度 根据sqlId添加相应的更新字段和查询条件 164 | if (sqlModifier.sqlId().equals("updateBirthAuto")) { 165 | sqlModifier.addUpdate("isActive", 0); 166 | } else if (sqlModifier.sqlId().equals("isDelete1")) { 167 | sqlModifier.addAnd(Where.where("isActive").equal(1)); 168 | } 169 | } 170 | 171 | @Override 172 | public void afterBuild(String sql, Object[] args) throws Exception { 173 | //sql审计 174 | System.out.println("sql:" + sql + " args:" + ArrayUtils.toString(args)); 175 | } 176 | } 177 | ``` 178 | 179 | #### sql语法 180 | 181 | #### https://github.com/hope-for/GyJdbc/blob/master/src/test/java/com/gysoft/jdbc/CriteriaTest.java 182 | 183 | #### 集成测试 184 | 185 | #### https://github.com/SpringStudent/GyJdbcTest 186 | 187 | #### 多数据源支持 188 | 189 | 开启AOP和引入切面增强类 190 | 191 | ```java 192 | @SpringBootApplication 193 | @EnableAspectJAutoProxy(proxyTargetClass = true) 194 | @Import(BindPointAspectRegistar.class) 195 | public class SystemApp { 196 | 197 | public static void main(String[] args) { 198 | SpringApplication.run(SystemApp.class, args); 199 | } 200 | 201 | } 202 | ``` 203 | 204 | 通过spring的xml配置 205 | 206 | ```xml 207 | 208 | 209 | ...省略 210 | 211 | 212 | 213 | ...省略 214 | 215 | 216 | 217 | ...省略 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | ``` 241 | 通过spring的bean配置 242 | 243 | ```java 244 | @Configuration 245 | public class DatasourceConf { 246 | @Bean(name = "primary") 247 | @Primary 248 | @ConfigurationProperties(prefix = "spring.datasource.primary") 249 | public HikariDataSource primary() { 250 | return new HikariDataSource(); 251 | } 252 | 253 | @Bean(name = "secondry") 254 | @ConfigurationProperties(prefix = "spring.datasource.secondry") 255 | public HikariDataSource secondry() { 256 | return new HikariDataSource(); 257 | } 258 | 259 | @Bean(name = "thrid") 260 | @ConfigurationProperties(prefix = "spring.datasource.thrid") 261 | public HikariDataSource thrid() { 262 | return new HikariDataSource(); 263 | } 264 | 265 | @Bean(name = "dataSource") 266 | public DataSource dataSource() { 267 | JdbcRoutingDataSource jdbcRoutingDataSource = new JdbcRoutingDataSource(); 268 | jdbcRoutingDataSource.setDefaultLookUpKey("primary"); 269 | 270 | Map targetDataSources = new HashMap<>(); 271 | targetDataSources.put("primary", primary()); 272 | targetDataSources.put("secondry", secondry()); 273 | targetDataSources.put("third", thrid()); 274 | jdbcRoutingDataSource.setTargetDataSources(targetDataSources); 275 | //配置分组用于负载均衡,如果无需负载均衡则可忽略 276 | Map dataSourceKeysGroup = new HashMap<>(); 277 | dataSourceKeysGroup.put("master","primary"); 278 | dataSourceKeysGroup.put("slave","secondry,thrid"); 279 | jdbcRoutingDataSource.setDataSourceKeysGroup(dataSourceKeysGroup); 280 | return jdbcRoutingDataSource; 281 | } 282 | 283 | @Bean(name = "jdbcTemplate") 284 | public JdbcTemplate jdbcTemplate() { 285 | return new JdbcTemplate(dataSource()); 286 | } 287 | } 288 | ``` 289 | **@Bindpoint注解绑定数据源** 290 | 291 | 绑定方法或者类级别的数据源,依赖于Spring Aop 292 | 293 | ```java 294 | //绑定数据源slaveGroup组,采用RandomLoadBalance策略(随机)的负载均衡策略选取数据源 295 | @BindPoint(group = "slaveGroup", loadBalance = RandomLoadBalance.class) 296 | //绑定指定slave2数据源 297 | @BindPoint(key = "slave2") 298 | ``` 299 | 300 | **EntityDao.binxxx方法绑定数据源** 301 | 302 | 绑定Sql级别的数据源 303 | 304 | ```java 305 | //SELECT * FROM tb_user where name in('zhouning','yinhw')将会在slave数据源上执行 306 | List tbUsers=tbUserDao.bindKey("slave").queryWithCriteria(new Criteria().in(TbUser::getName,Arrays.asList("zhouning","yinhw"))); 307 | //UPDATE tb_user set realName = "元林",email = "13888888888@163.com" WHERE name = "Smith" 308 | //采用轮询负载均衡策略在masterGroup组中选择一个数据源执行update操作 309 | tbUserDao.bindGroup("masterGroup",RoundbinLoadBalance.class).updateWithSql(new SQL().update(TbUser.class).set(TbUser::getRealName,"元林").set(TbUser::getEmail,"13888888888@163.com").where(TbUser::getName,"Smith")); 310 | ``` 311 | 312 | **FAQ** 313 | 314 | 数据源选择的优先级顺序: 315 | 316 | *entityDao.bindXxx* > *方法上@BindPoint* > *类上@BindPoint* > *JdbcRoutingDataSource.defaultLookUpKey* 317 | 318 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/AuxiliaryOperation.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import org.apache.commons.collections.CollectionUtils; 4 | import org.apache.commons.collections.MapUtils; 5 | import org.apache.commons.lang.ArrayUtils; 6 | import org.apache.commons.lang.StringUtils; 7 | 8 | import java.util.Collection; 9 | import java.util.Objects; 10 | import java.util.function.Predicate; 11 | 12 | /** 13 | * @author DJZ-HXF 14 | */ 15 | public interface AuxiliaryOperation> { 16 | 17 | S like(String key, Object value); 18 | 19 | S likeR(String key, Object value); 20 | 21 | S likeL(String key, Object value); 22 | 23 | S like(TypeFunction function, Object value); 24 | 25 | S likeR(TypeFunction function, Object value); 26 | 27 | S likeL(TypeFunction function, Object value); 28 | 29 | S and(String key, Object value); 30 | 31 | S and(TypeFunction function, Object value); 32 | 33 | S or(String key, Object value); 34 | 35 | S or(TypeFunction function, Object value); 36 | 37 | S orLike(String key, Object value); 38 | 39 | S orLike(TypeFunction function, Object value); 40 | 41 | S in(String key, Collection args); 42 | 43 | S in(TypeFunction function, Collection args); 44 | 45 | S notIn(String key, Collection args); 46 | 47 | S notIn(TypeFunction function, Collection args); 48 | 49 | S gt(String key, Object value); 50 | 51 | S gt(TypeFunction function, Object value); 52 | 53 | S gte(String key, Object value); 54 | 55 | S gte(TypeFunction function, Object value); 56 | 57 | S lt(String key, Object value); 58 | 59 | S lt(TypeFunction function, Object value); 60 | 61 | S let(String key, Object value); 62 | 63 | S let(TypeFunction function, Object value); 64 | 65 | S doNothing(); 66 | 67 | default S likeIfAbsent(String key, Object value) { 68 | return likeIfAbsent(key, value, getDefaultPredicate()); 69 | } 70 | 71 | default S likeIfAbsent(String key, Object value, Predicate predicate) { 72 | if (predicate.test(value)) { 73 | return like(key, value); 74 | } 75 | return doNothing(); 76 | } 77 | 78 | default S likeLIfAbsent(String key, Object value) { 79 | return likeLIfAbsent(key, value, getDefaultPredicate()); 80 | } 81 | 82 | default S likeLIfAbsent(String key, Object value, Predicate predicate) { 83 | if (predicate.test(value)) { 84 | return likeL(key, value); 85 | } 86 | return doNothing(); 87 | } 88 | 89 | default S likeRIfAbsent(String key, Object value) { 90 | return likeRIfAbsent(key, value, getDefaultPredicate()); 91 | } 92 | 93 | default S likeRIfAbsent(String key, Object value, Predicate predicate) { 94 | if (predicate.test(value)) { 95 | return likeR(key, value); 96 | } 97 | return doNothing(); 98 | } 99 | 100 | default S likeIfAbsent(TypeFunction function, Object value) { 101 | return likeIfAbsent(function, value, getDefaultPredicate()); 102 | } 103 | 104 | default S likeIfAbsent(TypeFunction function, Object value, Predicate predicate) { 105 | if (predicate.test(value)) { 106 | return like(function, value); 107 | } 108 | return doNothing(); 109 | } 110 | 111 | default S likeLIfAbsent(TypeFunction function, Object value) { 112 | return likeLIfAbsent(function, value, getDefaultPredicate()); 113 | } 114 | 115 | default S likeLIfAbsent(TypeFunction function, Object value, Predicate predicate) { 116 | if (predicate.test(value)) { 117 | return likeL(function, value); 118 | } 119 | return doNothing(); 120 | } 121 | 122 | default S likeRIfAbsent(TypeFunction function, Object value) { 123 | return likeRIfAbsent(function, value, getDefaultPredicate()); 124 | } 125 | 126 | default S likeRIfAbsent(TypeFunction function, Object value, Predicate predicate) { 127 | if (predicate.test(value)) { 128 | return likeR(function, value); 129 | } 130 | return doNothing(); 131 | } 132 | 133 | default S gtIfAbsent(String key, Object value) { 134 | return gtIfAbsent(key, value, getDefaultPredicate()); 135 | } 136 | 137 | default S gtIfAbsent(String key, Object value, Predicate predicate) { 138 | if (predicate.test(value)) { 139 | return gt(key, value); 140 | } 141 | return doNothing(); 142 | } 143 | 144 | default S gtIfAbsent(TypeFunction function, Object value) { 145 | return gtIfAbsent(function, value, getDefaultPredicate()); 146 | } 147 | 148 | default S gtIfAbsent(TypeFunction function, Object value, Predicate predicate) { 149 | if (predicate.test(value)) { 150 | return gt(function, value); 151 | } 152 | return doNothing(); 153 | } 154 | 155 | default S gteIfAbsent(String key, Object value) { 156 | return gteIfAbsent(key, value, getDefaultPredicate()); 157 | } 158 | 159 | default S gteIfAbsent(String key, Object value, Predicate predicate) { 160 | if (predicate.test(value)) { 161 | return gte(key, value); 162 | } 163 | return doNothing(); 164 | } 165 | 166 | default S gteIfAbsent(TypeFunction function, Object value) { 167 | return gteIfAbsent(function, value, getDefaultPredicate()); 168 | } 169 | 170 | default S gteIfAbsent(TypeFunction function, Object value, Predicate predicate) { 171 | if (predicate.test(value)) { 172 | return gte(function, value); 173 | } 174 | return doNothing(); 175 | } 176 | 177 | default S ltIfAbsent(String key, Object value) { 178 | return ltIfAbsent(key, value, getDefaultPredicate()); 179 | } 180 | 181 | default S ltIfAbsent(String key, Object value, Predicate predicate) { 182 | if (predicate.test(value)) { 183 | return lt(key, value); 184 | } 185 | return doNothing(); 186 | } 187 | 188 | default S ltIfAbsent(TypeFunction function, Object value) { 189 | return ltIfAbsent(function, value, getDefaultPredicate()); 190 | } 191 | 192 | default S ltIfAbsent(TypeFunction function, Object value, Predicate predicate) { 193 | if (predicate.test(value)) { 194 | return lt(function, value); 195 | } 196 | return doNothing(); 197 | } 198 | 199 | default S letIfAbsent(String key, Object value) { 200 | return letIfAbsent(key, value, getDefaultPredicate()); 201 | } 202 | 203 | default S letIfAbsent(String key, Object value, Predicate predicate) { 204 | if (predicate.test(value)) { 205 | return let(key, value); 206 | } 207 | return doNothing(); 208 | } 209 | 210 | default S letIfAbsent(TypeFunction function, Object value) { 211 | return letIfAbsent(function, value, getDefaultPredicate()); 212 | } 213 | 214 | default S letIfAbsent(TypeFunction function, Object value, Predicate predicate) { 215 | if (predicate.test(value)) { 216 | return let(function, value); 217 | } 218 | return doNothing(); 219 | } 220 | 221 | 222 | default S andIfAbsent(String key, Object value) { 223 | return andIfAbsent(key, value, getDefaultPredicate()); 224 | } 225 | 226 | default S andIfAbsent(String key, Object value, Predicate predicate) { 227 | if (predicate.test(value)) { 228 | return and(key, value); 229 | } 230 | return doNothing(); 231 | } 232 | 233 | default S andIfAbsent(TypeFunction function, Object value) { 234 | return andIfAbsent(function, value, getDefaultPredicate()); 235 | } 236 | 237 | default S andIfAbsent(TypeFunction function, Object value, Predicate predicate) { 238 | if (predicate.test(value)) { 239 | return and(function, value); 240 | } 241 | return doNothing(); 242 | } 243 | 244 | default S orIfAbsent(String key, Object value) { 245 | return orIfAbsent(key, value, getDefaultPredicate()); 246 | } 247 | 248 | default S orIfAbsent(String key, Object value, Predicate predicate) { 249 | if (predicate.test(value)) { 250 | return or(key, value); 251 | } 252 | return doNothing(); 253 | } 254 | 255 | default S orIfAbsent(TypeFunction function, Object value) { 256 | return orIfAbsent(function, value, getDefaultPredicate()); 257 | } 258 | 259 | default S orIfAbsent(TypeFunction function, Object value, Predicate predicate) { 260 | if (predicate.test(value)) { 261 | return or(function, value); 262 | } 263 | return doNothing(); 264 | } 265 | 266 | default S orLikeIfAbsent(String key, Object value) { 267 | return orLikeIfAbsent(key, value, getDefaultPredicate()); 268 | } 269 | 270 | default S orLikeIfAbsent(String key, Object value, Predicate predicate) { 271 | if (predicate.test(value)) { 272 | return orLike(key, value); 273 | } 274 | return doNothing(); 275 | } 276 | 277 | 278 | default S orLikeIfAbsent(TypeFunction function, Object value) { 279 | return orLikeIfAbsent(function, value, getDefaultPredicate()); 280 | } 281 | 282 | default S orLikeIfAbsent(TypeFunction function, Object value, Predicate predicate) { 283 | if (predicate.test(value)) { 284 | return orLike(function, value); 285 | } 286 | return doNothing(); 287 | } 288 | 289 | default S inIfAbsent(String key, Collection args) { 290 | return inIfAbsent(key, args, getDefaultPredicate()); 291 | } 292 | 293 | default S inIfAbsent(String key, Collection args, Predicate predicate) { 294 | if (predicate.test(args)) { 295 | return in(key, args); 296 | } 297 | return doNothing(); 298 | } 299 | 300 | default S inIfAbsent(TypeFunction function, Collection args) { 301 | return inIfAbsent(function, args, getDefaultPredicate()); 302 | } 303 | 304 | default S inIfAbsent(TypeFunction function, Collection args, Predicate predicate) { 305 | if (predicate.test(args)) { 306 | return in(function, args); 307 | } 308 | return doNothing(); 309 | } 310 | 311 | default S notInIfAbsent(String key, Collection args) { 312 | return notInIfAbsent(key, args, getDefaultPredicate()); 313 | } 314 | 315 | default S notInIfAbsent(String key, Collection args, Predicate predicate) { 316 | if (predicate.test(args)) { 317 | return notIn(key, args); 318 | } 319 | return doNothing(); 320 | } 321 | 322 | default S notInIfAbsent(TypeFunction function, Collection args) { 323 | return notInIfAbsent(function, args, getDefaultPredicate()); 324 | } 325 | 326 | default S notInIfAbsent(TypeFunction function, Collection args, Predicate predicate) { 327 | if (predicate.test(args)) { 328 | return notIn(function, args); 329 | } 330 | return doNothing(); 331 | } 332 | 333 | /** 334 | * 获取默认的判空断言 335 | */ 336 | static Predicate getDefaultPredicate() { 337 | return (t) -> { 338 | if (Objects.isNull(t)) { 339 | return false; 340 | } 341 | if (t instanceof String) { 342 | return StringUtils.isNotBlank((String) t); 343 | } 344 | if (t instanceof Collection) { 345 | return CollectionUtils.isNotEmpty((Collection) t); 346 | } 347 | if (t instanceof java.util.Map) { 348 | return MapUtils.isNotEmpty((java.util.Map) t); 349 | } 350 | if (t.getClass().isArray()) { 351 | return ArrayUtils.getLength(t) > 0; 352 | } 353 | if (t instanceof java.util.Optional) { 354 | return ((java.util.Optional) t).isPresent(); 355 | } 356 | return true; 357 | }; 358 | } 359 | 360 | } 361 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/AbstractCriteria.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import com.gysoft.jdbc.tools.SqlMakeTools; 4 | import org.apache.commons.collections.CollectionUtils; 5 | import org.apache.commons.lang.StringUtils; 6 | 7 | import java.util.*; 8 | import java.util.function.Consumer; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * @author 周宁 13 | */ 14 | public abstract class AbstractCriteria> implements AuxiliaryOperation { 15 | /** 16 | * 条件入参 17 | */ 18 | private List whereParams; 19 | /** 20 | * 排序入参 21 | */ 22 | private Set sorts; 23 | /** 24 | * 代理更复杂的sql拼接 25 | */ 26 | private List criteriaProxys; 27 | /** 28 | * 分组字段 29 | */ 30 | private Set groupFields; 31 | /** 32 | * having子句 33 | */ 34 | private Pair having; 35 | 36 | /** 37 | * 偏移量 38 | */ 39 | private int offset = -1; 40 | /** 41 | * 大小 42 | */ 43 | private int size; 44 | 45 | public AbstractCriteria() { 46 | whereParams = new ArrayList<>(); 47 | sorts = new LinkedHashSet<>(); 48 | criteriaProxys = new ArrayList<>(); 49 | groupFields = new LinkedHashSet<>(); 50 | } 51 | 52 | public S where(String key, Object value) { 53 | return this.where(key, "=", value); 54 | } 55 | 56 | public S where(String[] keys, Object value) { 57 | return this.where(keys, "=", value); 58 | } 59 | 60 | public S where(String[] keys, String opt, Object value) { 61 | if (keys == null || keys.length == 0) { 62 | throw new GyjdbcException("keys cannot be null or []"); 63 | } 64 | if (keys.length == 1) { 65 | return this.where(keys[0], opt, value); 66 | } else { 67 | StringBuilder columnsAppender = new StringBuilder(); 68 | columnsAppender.append("("); 69 | columnsAppender.append(StringUtils.join(keys, ",")); 70 | columnsAppender.append(")"); 71 | return this.where(columnsAppender.toString(), opt, value); 72 | } 73 | } 74 | 75 | public S where(TypeFunction function, Object value) { 76 | return this.where(TypeFunction.getLambdaColumnName(function), "=", value); 77 | } 78 | 79 | public S where(String key, String opt, Object value) { 80 | this.whereParams.add(new WhereParam(key, opt, value)); 81 | return self(); 82 | } 83 | 84 | private S self() { 85 | return (S) this; 86 | } 87 | 88 | public S where(TypeFunction function, String opt, Object value) { 89 | return this.where(TypeFunction.getLambdaColumnName(function), opt, value); 90 | } 91 | 92 | @Override 93 | public S like(String key, Object value) { 94 | return this.where(key, "LIKE", "%" + value + "%"); 95 | } 96 | 97 | @Override 98 | public S like(TypeFunction function, Object value) { 99 | return this.where(TypeFunction.getLambdaColumnName(function), "LIKE", "%" + value + "%"); 100 | } 101 | 102 | @Override 103 | public S likeR(String key, Object value) { 104 | return this.where(key, "LIKE", value + "%"); 105 | 106 | } 107 | 108 | @Override 109 | public S likeL(String key, Object value) { 110 | return this.where(key, "LIKE", "%" + value); 111 | } 112 | 113 | @Override 114 | public S likeR(TypeFunction function, Object value) { 115 | return this.where(TypeFunction.getLambdaColumnName(function), "LIKE", value + "%"); 116 | } 117 | 118 | @Override 119 | public S likeL(TypeFunction function, Object value) { 120 | return this.where(TypeFunction.getLambdaColumnName(function), "LIKE", "%" + value); 121 | } 122 | 123 | @Override 124 | public S gt(String key, Object value) { 125 | return this.where(key, ">", value); 126 | } 127 | 128 | @Override 129 | public S gt(TypeFunction function, Object value) { 130 | return this.where(TypeFunction.getLambdaColumnName(function), ">", value); 131 | } 132 | 133 | @Override 134 | public S gte(String key, Object value) { 135 | return this.where(key, ">=", value); 136 | } 137 | 138 | @Override 139 | public S gte(TypeFunction function, Object value) { 140 | return this.where(TypeFunction.getLambdaColumnName(function), ">=", value); 141 | } 142 | 143 | @Override 144 | public S lt(String key, Object value) { 145 | return this.where(key, "<", value); 146 | } 147 | 148 | @Override 149 | public S lt(TypeFunction function, Object value) { 150 | return this.where(TypeFunction.getLambdaColumnName(function), "<", value); 151 | } 152 | 153 | @Override 154 | public S let(String key, Object value) { 155 | return this.where(key, "<=", value); 156 | } 157 | 158 | @Override 159 | public S let(TypeFunction function, Object value) { 160 | return this.where(TypeFunction.getLambdaColumnName(function), "<=", value); 161 | } 162 | 163 | @Override 164 | public S doNothing() { 165 | return self(); 166 | } 167 | 168 | public S notEqual(String key, Object value) { 169 | return this.where(key, "<>", value); 170 | } 171 | 172 | public S notEqual(TypeFunction function, Object value) { 173 | return this.where(TypeFunction.getLambdaColumnName(function), "<>", value); 174 | } 175 | 176 | public S isNull(String key) { 177 | return this.where(key, "IS", "NULL"); 178 | } 179 | 180 | public S isNull(TypeFunction function) { 181 | return this.where(TypeFunction.getLambdaColumnName(function), "IS", "NULL"); 182 | } 183 | 184 | public S isNotNull(String key) { 185 | return this.where(key, "IS", "NOT NULL"); 186 | } 187 | 188 | public S isNotNull(TypeFunction function) { 189 | return this.where(TypeFunction.getLambdaColumnName(function), "IS", "NOT NULL"); 190 | } 191 | 192 | @Override 193 | public S and(String key, Object value) { 194 | return this.where(key, value); 195 | } 196 | 197 | @Override 198 | public S and(TypeFunction function, Object value) { 199 | return this.where(TypeFunction.getLambdaColumnName(function), value); 200 | } 201 | 202 | public S and(String key, String opt, Object value) { 203 | return this.where(key, opt, value); 204 | } 205 | 206 | public S and(TypeFunction function, String opt, Object value) { 207 | return this.where(TypeFunction.getLambdaColumnName(function), opt, value); 208 | } 209 | 210 | @Override 211 | public S or(String key, Object value) { 212 | return this.or(key, "=", value); 213 | } 214 | 215 | @Override 216 | public S or(TypeFunction function, Object value) { 217 | return this.or(TypeFunction.getLambdaColumnName(function), "=", value); 218 | } 219 | 220 | @Override 221 | public S orLike(String key, Object value) { 222 | return this.or(key, "like", "%" + value + "%"); 223 | } 224 | 225 | @Override 226 | public S orLike(TypeFunction function, Object value) { 227 | return this.or(TypeFunction.getLambdaColumnName(function), "like", "%" + value + "%"); 228 | } 229 | 230 | public S or(String key, String opt, Object value) { 231 | if (CollectionUtils.isEmpty(this.whereParams)) { 232 | throw new GyjdbcException("sql error,condition \"or\" must be following after \"where\"!"); 233 | } 234 | return this.where(" OR " + key, opt, value); 235 | } 236 | 237 | public S exists(SQL sql) { 238 | return this.where("EXISTS", "", sql); 239 | } 240 | 241 | public S notExists(SQL sql) { 242 | return this.where("NOT EXISTS", "", sql); 243 | } 244 | 245 | public S or(TypeFunction function, String opt, Object value) { 246 | return this.or(TypeFunction.getLambdaColumnName(function), opt, value); 247 | } 248 | 249 | public S orBetweenAnd(String key, Object v1, Object v2) { 250 | return this.or(key, "BETWEEN ? AND ?", new Pair<>(v1, v2)); 251 | } 252 | 253 | public S orBetweenAnd(TypeFunction function, Object v1, Object v2) { 254 | return this.or(TypeFunction.getLambdaColumnName(function), "BETWEEN ? AND ?", new Pair<>(v1, v2)); 255 | } 256 | 257 | public S in(String key, SQL sql) { 258 | return this.where(key, "IN", sql); 259 | } 260 | 261 | public S in(TypeFunction function, SQL sql) { 262 | return this.where(TypeFunction.getLambdaColumnName(function), "IN", sql); 263 | } 264 | 265 | @Override 266 | public S in(String key, Collection args) { 267 | return this.where(key, "IN", args); 268 | } 269 | 270 | @Override 271 | public S in(TypeFunction function, Collection args) { 272 | return this.where(TypeFunction.getLambdaColumnName(function), "IN", args); 273 | } 274 | 275 | @Override 276 | public S notIn(String key, Collection args) { 277 | return this.where(key, "NOT IN", args); 278 | } 279 | 280 | @Override 281 | public S notIn(TypeFunction function, Collection args) { 282 | return this.where(TypeFunction.getLambdaColumnName(function), "NOT IN", args); 283 | } 284 | 285 | public S notIn(String key, SQL sql) { 286 | return this.where(key, "NOT IN", sql); 287 | } 288 | 289 | public S notIn(TypeFunction function, SQL sql) { 290 | return this.where(TypeFunction.getLambdaColumnName(function), "NOT IN", sql); 291 | } 292 | 293 | public S betweenAnd(String key, Object v1, Object v2) { 294 | return this.where(key, "BETWEEN ? AND ?", new Pair<>(v1, v2)); 295 | } 296 | 297 | public S betweenAnd(TypeFunction function, Object v1, Object v2) { 298 | return this.where(TypeFunction.getLambdaColumnName(function), "BETWEEN ? AND ?", new Pair<>(v1, v2)); 299 | } 300 | 301 | public S andCriteria(Criteria criteria) { 302 | return criteria(criteria, "AND"); 303 | } 304 | 305 | public S orCriteria(Criteria criteria) { 306 | if (CollectionUtils.isEmpty(whereParams)) { 307 | throw new GyjdbcException("sql error,condition \"orCriteria\" must be following after \"where\"!"); 308 | } 309 | return criteria(criteria, "OR"); 310 | } 311 | 312 | public S andCriteria(Consumer consumer) { 313 | Criteria sub = new Criteria(); 314 | consumer.accept(sub); 315 | return andCriteria(sub); 316 | } 317 | 318 | public S orCriteria(Consumer consumer) { 319 | Criteria sub = new Criteria(); 320 | consumer.accept(sub); 321 | return orCriteria(sub); 322 | } 323 | 324 | public S and(Where where) { 325 | return criteria(where.getCriteria(), "WHEREAND"); 326 | } 327 | 328 | public S or(Where where) { 329 | return criteria(where.getCriteria(), "WHEREOR"); 330 | } 331 | 332 | public S and(Opt opt, List whereParams) { 333 | return and(buildWhere(opt, whereParams.toArray(new WhereParam[whereParams.size()]))); 334 | } 335 | 336 | public S and(Opt opt, WhereParam... whereParams) { 337 | return and(buildWhere(opt, whereParams)); 338 | } 339 | 340 | public S or(Opt opt, List whereParams) { 341 | return or(buildWhere(opt, whereParams.toArray(new WhereParam[whereParams.size()]))); 342 | } 343 | 344 | public S or(Opt opt, WhereParam... whereParams) { 345 | return or(buildWhere(opt, whereParams)); 346 | } 347 | 348 | public S andWhere(Opt opt, List whereParams) { 349 | return andCriteria(buildWhere(opt, whereParams.toArray(new WhereParam[whereParams.size()])).getCriteria()); 350 | } 351 | 352 | public S andWhere(Opt opt, WhereParam... whereParams) { 353 | return andCriteria(buildWhere(opt, whereParams).getCriteria()); 354 | } 355 | 356 | public S andWhere(Where where) { 357 | return andCriteria(where.getCriteria()); 358 | } 359 | 360 | public S orWhere(Opt opt, List whereParams) { 361 | return orCriteria(buildWhere(opt, whereParams.toArray(new WhereParam[whereParams.size()])).getCriteria()); 362 | } 363 | 364 | public S orWhere(Where where) { 365 | return orCriteria(where.getCriteria()); 366 | } 367 | 368 | public S orWhere(Opt opt, WhereParam... whereParams) { 369 | return orCriteria(buildWhere(opt, whereParams).getCriteria()); 370 | } 371 | 372 | public Where buildWhere(Opt opt, WhereParam... whereParams) { 373 | WhereParam first = whereParams[0]; 374 | Where where = new Where(first.getKey()); 375 | where = whereParam(first, where); 376 | for (int i = 1; i < whereParams.length; i++) { 377 | WhereParam wp = whereParams[i]; 378 | if (opt.equals(Opt.AND)) { 379 | where = where.and(wp.getKey()); 380 | } else { 381 | where = where.or(wp.getKey()); 382 | } 383 | where = whereParam(wp, where); 384 | } 385 | return where; 386 | } 387 | 388 | private Where whereParam(WhereParam wp, Where where) { 389 | if (wp.getOptEnum().equals(WhereParam.OptEnum.Equal)) { 390 | where = where.equal(wp.getValue()); 391 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.BetweenAnd)) { 392 | Pair pair = (Pair) wp.getValue(); 393 | where = where.betweenAnd(pair.getFirst(), pair.getSecond()); 394 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.NotEqual)) { 395 | where = where.notEqual(wp.getValue()); 396 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.Gt)) { 397 | where = where.gt(wp.getValue()); 398 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.Gte)) { 399 | where = where.gte(wp.getValue()); 400 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.Lt)) { 401 | where = where.lt(wp.getValue()); 402 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.Let)) { 403 | where = where.let(wp.getValue()); 404 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.IsNull)) { 405 | where = where.isNull(); 406 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.IsNotNull)) { 407 | where = where.isNotNull(); 408 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.Exists)) { 409 | where = where.exists((SQL) wp.getValue()); 410 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.NotExists)) { 411 | where = where.notExists((SQL) wp.getValue()); 412 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.Like)) { 413 | where = where.like(wp.getValue()); 414 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.In)) { 415 | where = where.in((Collection) wp.getValue()); 416 | } else if (wp.getOptEnum().equals(WhereParam.OptEnum.NotIn)) { 417 | where = where.notIn((Collection) wp.getValue()); 418 | } 419 | return where; 420 | } 421 | 422 | private S criteria(Criteria criteria, String criteriaType) { 423 | if (CollectionUtils.isNotEmpty(criteria.getSorts())) { 424 | throw new GyjdbcException("unsupport doCriteria operate"); 425 | } 426 | //如果子查询中的子查询条件为空直接返回 427 | if (CollectionUtils.isEmpty(criteria.getWhereParams())) { 428 | return self(); 429 | } 430 | if (CollectionUtils.isEmpty(whereParams)) { 431 | whereParams.add(new WhereParam()); 432 | } 433 | CriteriaProxy criteriaProxy = new CriteriaProxy(); 434 | Pair pair = SqlMakeTools.doCriteria(criteria, new StringBuilder()); 435 | criteriaProxy.setWhereParamsIndex(whereParams.size() + 1); 436 | criteriaProxy.setSql(new StringBuilder(pair.getFirst().replace("WHERE", "").trim())); 437 | criteriaProxy.setParams(pair.getSecond()); 438 | criteriaProxy.setCriteriaType(criteriaType); 439 | criteriaProxys.add(criteriaProxy); 440 | return self(); 441 | } 442 | 443 | public S groupBy(String... fields) { 444 | groupFields.addAll(Arrays.stream(fields).collect(Collectors.toList())); 445 | return self(); 446 | } 447 | 448 | public S groupBy(TypeFunction... functions) { 449 | groupFields.addAll(Arrays.stream(functions).map(function -> TypeFunction.getLambdaColumnName(function)).collect(Collectors.toList())); 450 | return self(); 451 | } 452 | 453 | public S having(String funcField, String opt, Object value) { 454 | return having(new Criteria().where(funcField, opt, value)); 455 | } 456 | 457 | public S having(Criteria criteria) { 458 | having = SqlMakeTools.doCriteria(criteria, new StringBuilder()); 459 | having.setFirst(having.getFirst().replace("WHERE ", "")); 460 | return self(); 461 | } 462 | 463 | public S orderBy(Sort... sort) { 464 | sorts.addAll(Arrays.stream(sort).collect(Collectors.toList())); 465 | return self(); 466 | } 467 | 468 | public S limit(int offset, int size) { 469 | this.offset = offset; 470 | this.size = size; 471 | return self(); 472 | } 473 | 474 | public S limit(int offset) { 475 | this.offset = offset; 476 | return self(); 477 | } 478 | 479 | public List getWhereParams() { 480 | return whereParams; 481 | } 482 | 483 | public Set getSorts() { 484 | return sorts; 485 | } 486 | 487 | public List getCriteriaProxys() { 488 | return criteriaProxys; 489 | } 490 | 491 | public Set getGroupFields() { 492 | return groupFields; 493 | } 494 | 495 | public Pair getHaving() { 496 | return having; 497 | } 498 | 499 | public int getOffset() { 500 | return offset; 501 | } 502 | 503 | public int getSize() { 504 | return size; 505 | } 506 | } 507 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/bean/SQL.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.bean; 2 | 3 | import com.gysoft.jdbc.dao.EntityDao; 4 | import com.gysoft.jdbc.tools.CollectionUtil; 5 | import com.gysoft.jdbc.tools.EntityTools; 6 | import org.apache.commons.collections.CollectionUtils; 7 | import org.apache.commons.lang.StringUtils; 8 | 9 | import java.util.*; 10 | import java.util.function.Consumer; 11 | import java.util.stream.Collectors; 12 | 13 | /** 14 | * @author 周宁 15 | */ 16 | public class SQL extends AbstractCriteria { 17 | /** 18 | * sql类型 19 | */ 20 | private String sqlType; 21 | /** 22 | * 表名称 23 | */ 24 | private String tbName; 25 | /** 26 | * 表的别名 27 | */ 28 | private String aliasName; 29 | /** 30 | * 将sql作为表的别名 31 | */ 32 | private String asTable; 33 | /** 34 | * 标识从from(SQL c,String fromAsTable) 35 | */ 36 | private String fromAsTable; 37 | /** 38 | * 删除语句中表的别名 39 | */ 40 | private String deleteAliasName; 41 | /** 42 | * 连接 43 | */ 44 | private List joins; 45 | /** 46 | * 子查询条件 47 | */ 48 | private List subSqls; 49 | /** 50 | * sql管道拼接 51 | */ 52 | private SQLPiepline sqlPiepline; 53 | /** 54 | * 表元数据 55 | */ 56 | private TableMeta tableMeta; 57 | /** 58 | * 被查询的字段 59 | */ 60 | private List selectFields; 61 | /** 62 | * 插入数据 63 | */ 64 | private List insertValues; 65 | 66 | /** 67 | * 插入sql 68 | */ 69 | private Pair> insert; 70 | 71 | /** 72 | * 待更新的字段和相应的值 73 | */ 74 | private List kvs; 75 | /** 76 | * 连接类型 77 | */ 78 | private String unionType; 79 | 80 | /** 81 | * 喝醉了的,代表人很糊涂删除表或者清楚数据 82 | */ 83 | private Drunk drunk; 84 | 85 | private SqlModifier sqlModifier; 86 | 87 | private String id; 88 | 89 | public SQL() { 90 | this(null); 91 | } 92 | 93 | public SQL(String id) { 94 | sqlModifier = new SqlModifier(this); 95 | sqlPiepline = new SQLPiepline(this); 96 | selectFields = new ArrayList<>(); 97 | kvs = new ArrayList<>(); 98 | joins = new ArrayList<>(); 99 | subSqls = new ArrayList<>(); 100 | insertValues = new ArrayList<>(); 101 | insert = new Pair<>(); 102 | this.id = id; 103 | } 104 | 105 | public SQL from(SQL... cc) { 106 | for (SQL c : cc) { 107 | c.getSqlPiepline().getSqlNexts().forEach(sqlNext -> { 108 | SQL s = sqlNext.getSql(); 109 | if (sqlNext.getUnionType() != null) { 110 | s.setUnionType(sqlNext.getUnionType()); 111 | } else { 112 | s.setUnionType(","); 113 | } 114 | subSqls.add(s); 115 | }); 116 | } 117 | return this; 118 | } 119 | 120 | public SQL from(SQL c, String fromAsTable) { 121 | this.fromAsTable = fromAsTable; 122 | c.getSqlPiepline().getSqlNexts().forEach(sqlNext -> { 123 | SQL s = sqlNext.getSql(); 124 | if (sqlNext.getUnionType() != null) { 125 | s.setUnionType(sqlNext.getUnionType()); 126 | } else { 127 | s.setUnionType(","); 128 | } 129 | subSqls.add(s); 130 | }); 131 | return this; 132 | } 133 | 134 | public SQL union() { 135 | SQL next = new SQL(); 136 | sqlPiepline.add(next, "UNION"); 137 | next.setSqlPiepline(sqlPiepline); 138 | return next; 139 | } 140 | 141 | public SQL unionAll() { 142 | SQL next = new SQL(); 143 | sqlPiepline.add(next, "UNION ALL"); 144 | next.setSqlPiepline(sqlPiepline); 145 | return next; 146 | } 147 | 148 | public SQL select(Object... fields) { 149 | selectFields.addAll(Arrays.stream(fields).collect(Collectors.toList())); 150 | //复合查询insert select语法BUG修复 151 | if (this.sqlType == null) { 152 | this.sqlType = EntityDao.SQL_SELECT; 153 | } 154 | return this; 155 | } 156 | 157 | public SQL select(TypeFunction... functions) { 158 | selectFields.addAll(Arrays.stream(functions).map(function -> TypeFunction.getLambdaColumnName(function)).collect(Collectors.toList())); 159 | //复合查询insert select语法BUG修复 160 | if (this.sqlType == null) { 161 | this.sqlType = EntityDao.SQL_SELECT; 162 | } 163 | return this; 164 | } 165 | 166 | public SQL update(String table) { 167 | this.tbName = table; 168 | this.sqlType = EntityDao.SQL_UPDATE; 169 | return this; 170 | } 171 | 172 | public SQL update(String table, String aliasName) { 173 | this.aliasName = aliasName; 174 | return update(table); 175 | } 176 | 177 | public SQL update(Class clss) { 178 | this.tbName = EntityTools.getTableName(clss); 179 | this.sqlType = EntityDao.SQL_UPDATE; 180 | return this; 181 | } 182 | 183 | public SQL update(Class clss, String aliasName) { 184 | this.aliasName = aliasName; 185 | return update(EntityTools.getTableName(clss)); 186 | } 187 | 188 | public SQL delete(String deleteAliasName) { 189 | this.deleteAliasName = deleteAliasName; 190 | this.sqlType = EntityDao.SQL_DELETE; 191 | return this; 192 | } 193 | 194 | public SQL delete(String... deleteAliasNames) { 195 | this.deleteAliasName = Arrays.stream(deleteAliasNames).collect(Collectors.joining(",")); 196 | this.sqlType = EntityDao.SQL_DELETE; 197 | return this; 198 | } 199 | 200 | public SQL delete() { 201 | this.sqlType = EntityDao.SQL_DELETE; 202 | return this; 203 | } 204 | 205 | public SQL insertInto(String table, String... fields) { 206 | insert.setFirst(table); 207 | insert.setSecond(Arrays.stream(fields).collect(Collectors.toList())); 208 | this.sqlType = EntityDao.SQL_INSERT; 209 | return this; 210 | } 211 | 212 | public SQL replaceInto(String table, String... fields) { 213 | insert.setFirst(table); 214 | insert.setSecond(Arrays.stream(fields).collect(Collectors.toList())); 215 | this.sqlType = EntityDao.SQL_REPLACE; 216 | return this; 217 | } 218 | 219 | public SQL insertIgnoreInto(String table, String... fields) { 220 | insert.setFirst(table); 221 | insert.setSecond(Arrays.stream(fields).collect(Collectors.toList())); 222 | this.sqlType = EntityDao.SQL_INSERTIGNORE; 223 | return this; 224 | } 225 | 226 | 227 | public SQL insertInto(String table, TypeFunction... functions) { 228 | insert.setFirst(table); 229 | insert.setSecond(Arrays.stream(functions).map(f -> TypeFunction.getLambdaColumnName(f)).collect(Collectors.toList())); 230 | this.sqlType = EntityDao.SQL_INSERT; 231 | 232 | return this; 233 | } 234 | 235 | public SQL replaceInto(String table, TypeFunction... functions) { 236 | insert.setFirst(table); 237 | insert.setSecond(Arrays.stream(functions).map(f -> TypeFunction.getLambdaColumnName(f)).collect(Collectors.toList())); 238 | this.sqlType = EntityDao.SQL_REPLACE; 239 | return this; 240 | } 241 | 242 | 243 | public SQL insertIgnoreInto(String table, TypeFunction... functions) { 244 | insert.setFirst(table); 245 | insert.setSecond(Arrays.stream(functions).map(f -> TypeFunction.getLambdaColumnName(f)).collect(Collectors.toList())); 246 | this.sqlType = EntityDao.SQL_INSERTIGNORE; 247 | return this; 248 | } 249 | 250 | 251 | public SQL insertInto(String table) { 252 | insert.setFirst(table); 253 | this.sqlType = EntityDao.SQL_INSERT; 254 | return this; 255 | } 256 | 257 | public SQL replaceInto(String table) { 258 | insert.setFirst(table); 259 | this.sqlType = EntityDao.SQL_REPLACE; 260 | return this; 261 | } 262 | 263 | 264 | public SQL insertIgnoreInto(String table) { 265 | insert.setFirst(table); 266 | this.sqlType = EntityDao.SQL_INSERTIGNORE; 267 | return this; 268 | } 269 | 270 | public SQL insertInto(Class clss, String... fields) { 271 | return insertInto(EntityTools.getTableName(clss), fields); 272 | } 273 | 274 | public SQL replaceInto(Class clss, String... fields) { 275 | return replaceInto(EntityTools.getTableName(clss), fields); 276 | } 277 | 278 | public SQL insertInto(Class clss, TypeFunction... functions) { 279 | return insertInto(EntityTools.getTableName(clss), functions); 280 | } 281 | 282 | public SQL replaceInto(Class clss, TypeFunction... functions) { 283 | return replaceInto(EntityTools.getTableName(clss), functions); 284 | } 285 | 286 | public SQL insertInto(Class clss) { 287 | return insertInto(EntityTools.getTableName(clss)); 288 | } 289 | 290 | public SQL replaceInto(Class clss) { 291 | return replaceInto(EntityTools.getTableName(clss)); 292 | } 293 | 294 | public SQL insertIgnoreInto(Class clss, String... fields) { 295 | return insertIgnoreInto(EntityTools.getTableName(clss), fields); 296 | } 297 | 298 | public SQL insertIgnoreInto(Class clss, TypeFunction... functions) { 299 | return insertIgnoreInto(EntityTools.getTableName(clss), functions); 300 | } 301 | 302 | public SQL insertIgnoreInto(Class clss) { 303 | return insertIgnoreInto(EntityTools.getTableName(clss)); 304 | } 305 | 306 | public SQL truncate() { 307 | sqlType = EntityDao.SQL_TRUNCATE; 308 | drunk = new Drunk(); 309 | return this; 310 | } 311 | 312 | public SQL table(String... tables) { 313 | drunk.setTables(Arrays.stream(tables).collect(Collectors.toSet())); 314 | return this; 315 | } 316 | 317 | public SQL table(Class... clss) { 318 | drunk.setTables(Arrays.stream(clss).map(EntityTools::getTableName).collect(Collectors.toSet())); 319 | return this; 320 | } 321 | 322 | public SQL drop() { 323 | sqlType = EntityDao.SQL_DROP; 324 | drunk = new Drunk(); 325 | return this; 326 | } 327 | 328 | public SQL ifExists() { 329 | drunk.setIfExists(true); 330 | return this; 331 | } 332 | 333 | public SQL set(String key, Object value) { 334 | kvs.add(new Pair(key, value)); 335 | return this; 336 | } 337 | 338 | public SQL set(TypeFunction function, Object value) { 339 | kvs.add(new Pair(TypeFunction.getLambdaColumnName(function), value)); 340 | return this; 341 | } 342 | 343 | public SQL as(String aliasName) { 344 | this.aliasName = aliasName; 345 | return this; 346 | } 347 | 348 | public SQL asTable(String aliasName) { 349 | this.asTable = aliasName; 350 | return this; 351 | } 352 | 353 | public SQL from(Class clss) { 354 | tbName = EntityTools.getTableName(clss); 355 | return this; 356 | } 357 | 358 | public SQL from(String tbName) { 359 | this.tbName = tbName; 360 | return this; 361 | } 362 | 363 | public SQL from(String tbName, String aliasName) { 364 | this.tbName = tbName; 365 | return as(aliasName); 366 | } 367 | 368 | public SQL from(Class clss, String aliasName) { 369 | tbName = EntityTools.getTableName(clss); 370 | return as(aliasName); 371 | } 372 | 373 | public SQL leftJoin(Joins.On on) { 374 | on.setJoinType(JoinType.LeftJoin); 375 | return join(on); 376 | } 377 | 378 | public SQL leftJoin(Object table, String alias, Consumer joinConsumer) { 379 | return join(table, alias, joinConsumer, JoinType.LeftJoin); 380 | } 381 | 382 | public SQL rightJoin(Joins.On on) { 383 | on.setJoinType(JoinType.RightJoin); 384 | return join(on); 385 | } 386 | 387 | public SQL rightJoin(Object table, String alias, Consumer joinConsumer) { 388 | return join(table, alias, joinConsumer, JoinType.RightJoin); 389 | } 390 | 391 | public SQL innerJoin(Joins.On on) { 392 | on.setJoinType(JoinType.InnerJoin); 393 | return join(on); 394 | } 395 | 396 | public SQL innerJoin(Object table, String alias, Consumer joinConsumer) { 397 | return join(table, alias, joinConsumer, JoinType.InnerJoin); 398 | } 399 | 400 | public SQL natureJoin(Joins.BaseJoin as) { 401 | as.setJoinType(JoinType.NatureJoin); 402 | joins.add(as); 403 | return this; 404 | } 405 | 406 | public SQL natureJoin(Object table, String alias, Consumer joinConsumer) { 407 | return join(table, alias, joinConsumer, JoinType.NatureJoin); 408 | } 409 | 410 | private SQL join(Joins.On join) { 411 | joins.add(join); 412 | return this; 413 | } 414 | 415 | public SQL join(Object table, String alias, Consumer joinConsumer, JoinType joinType) { 416 | Joins.As as = null; 417 | if (table instanceof Class) { 418 | as = new Joins().with((Class) table).as(alias); 419 | } else if (table instanceof String) { 420 | as = new Joins().with((String) table).as(alias); 421 | } else if (table instanceof SQL) { 422 | as = new Joins().with((SQL) table).as(alias); 423 | } 424 | as.setJoinType(joinType); 425 | joinConsumer.accept(as.on()); 426 | joins.add(as); 427 | return this; 428 | } 429 | 430 | public SQL join(JoinType joinType, Object table, String aliasName) { 431 | Joins.As as = null; 432 | if (table instanceof Class) { 433 | as = new Joins().with((Class) table).as(aliasName); 434 | } else if (table instanceof String) { 435 | as = new Joins().with((String) table).as(aliasName); 436 | } else if (table instanceof SQL) { 437 | as = new Joins().with((SQL) table).as(aliasName); 438 | } 439 | as.setJoinType(joinType); 440 | joins.add(as); 441 | return this; 442 | } 443 | 444 | public SQL join(JoinType joinType, Object table) { 445 | Joins.With with = null; 446 | if (table instanceof Class) { 447 | with = new Joins().with((Class) table); 448 | } else if (table instanceof String) { 449 | with = new Joins().with((String) table); 450 | } else if (table instanceof SQL) { 451 | with = new Joins().with((SQL) table); 452 | } 453 | with.setJoinType(joinType); 454 | joins.add(with); 455 | return this; 456 | } 457 | 458 | public SQL leftJoin(Object table, String aliasName) { 459 | return join(JoinType.LeftJoin, table, aliasName); 460 | } 461 | 462 | public SQL leftJoin(Object table) { 463 | return join(JoinType.LeftJoin, table); 464 | } 465 | 466 | public SQL rightJoin(Object table, String aliasName) { 467 | return join(JoinType.RightJoin, table, aliasName); 468 | } 469 | 470 | public SQL rightJoin(Object table) { 471 | return join(JoinType.RightJoin, table); 472 | } 473 | 474 | public SQL innerJoin(Object table, String aliasName) { 475 | return join(JoinType.InnerJoin, table, aliasName); 476 | } 477 | 478 | public SQL innerJoin(Object table) { 479 | return join(JoinType.InnerJoin, table); 480 | } 481 | 482 | public SQL natureJoin(Object table, String aliasName) { 483 | return join(JoinType.NatureJoin, table, aliasName); 484 | } 485 | 486 | public SQL natureJoin(Object table) { 487 | return join(JoinType.NatureJoin, table); 488 | } 489 | 490 | public SQL on(String field, String field2) { 491 | Object obj = joins.get(joins.size() - 1); 492 | if (obj instanceof Joins.With) { 493 | joins.remove(obj); 494 | Joins.On on = ((Joins.With) obj).on(field, field2); 495 | joins.add(on); 496 | } else if (obj instanceof Joins.As) { 497 | joins.remove(obj); 498 | Joins.On on = ((Joins.As) obj).on(field, field2); 499 | joins.add(on); 500 | } else { 501 | ((Joins.On) obj).on(field, field2); 502 | } 503 | return this; 504 | } 505 | 506 | public SQL on(String field, String opt, Object field2) { 507 | Object as = joins.get(joins.size() - 1); 508 | if (as instanceof Joins.On) { 509 | ((Joins.On) as).and(field, opt, field2); 510 | } else { 511 | throw new GyjdbcException("the sql has no join condition"); 512 | } 513 | return this; 514 | } 515 | 516 | public SQL values(Object... values) { 517 | insertValues.add(values); 518 | return this; 519 | } 520 | 521 | public SQL values(List values) { 522 | insertValues.addAll(values); 523 | return this; 524 | } 525 | 526 | public Table create() { 527 | this.sqlType = EntityDao.SQL_CREATE; 528 | return new Table(this); 529 | } 530 | 531 | public SQL onDuplicateKeyUpdate(String key, Object value) { 532 | kvs.add(new Pair(key, value)); 533 | return this; 534 | } 535 | 536 | public SQL onDuplicateKeyUpdate(TypeFunction function, Object value) { 537 | kvs.add(new Pair(TypeFunction.getLambdaColumnName(function), value)); 538 | return this; 539 | } 540 | 541 | void setTableMeta(TableMeta tableMeta) { 542 | this.tableMeta = tableMeta; 543 | } 544 | 545 | void setInsertValues(List insertValues) { 546 | this.insertValues = insertValues; 547 | } 548 | 549 | void setTbName(String tbName) { 550 | this.tbName = tbName; 551 | } 552 | 553 | void setSqlType(String sqlType) { 554 | this.sqlType = sqlType; 555 | } 556 | 557 | void setSqlPiepline(SQLPiepline sqlPiepline) { 558 | this.sqlPiepline = sqlPiepline; 559 | } 560 | 561 | void setUnionType(String unionType) { 562 | this.unionType = unionType; 563 | } 564 | 565 | public String getSqlType() { 566 | return sqlType; 567 | } 568 | 569 | public String getTbName() { 570 | return tbName; 571 | } 572 | 573 | public String getAliasName() { 574 | return aliasName; 575 | } 576 | 577 | public String getAsTable() { 578 | return asTable; 579 | } 580 | 581 | public String getFromAsTable() { 582 | return fromAsTable; 583 | } 584 | 585 | public String getDeleteAliasName() { 586 | return deleteAliasName; 587 | } 588 | 589 | public List getJoins() { 590 | return joins; 591 | } 592 | 593 | public List getSubSqls() { 594 | return subSqls; 595 | } 596 | 597 | public SQLPiepline getSqlPiepline() { 598 | return sqlPiepline; 599 | } 600 | 601 | public TableMeta getTableMeta() { 602 | return tableMeta; 603 | } 604 | 605 | public List getSelectFields() { 606 | return selectFields; 607 | } 608 | 609 | public List getInsertValues() { 610 | return insertValues; 611 | } 612 | 613 | public Pair> getInsert() { 614 | return insert; 615 | } 616 | 617 | public List getKvs() { 618 | return kvs; 619 | } 620 | 621 | public String getUnionType() { 622 | return unionType; 623 | } 624 | 625 | public Drunk getDrunk() { 626 | return drunk; 627 | } 628 | 629 | public SqlModifier getModifier() { 630 | return sqlModifier; 631 | } 632 | 633 | public String getId() { 634 | if (StringUtils.isNotEmpty(id)) { 635 | return id; 636 | } else { 637 | return System.currentTimeMillis() + ":" + sqlModifier.sqlType() + ":" + sqlModifier.tableName(); 638 | } 639 | } 640 | 641 | } 642 | -------------------------------------------------------------------------------- /src/main/java/com/gysoft/jdbc/dao/SpringJdbc.java: -------------------------------------------------------------------------------- 1 | package com.gysoft.jdbc.dao; 2 | 3 | import com.gysoft.jdbc.bean.GyjdbcException; 4 | import com.gysoft.jdbc.bean.Page; 5 | import com.gysoft.jdbc.bean.PageResult; 6 | import org.apache.commons.lang.ArrayUtils; 7 | import org.springframework.dao.support.DataAccessUtils; 8 | import org.springframework.jdbc.core.*; 9 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; 10 | import org.springframework.jdbc.core.namedparam.NamedParameterUtils; 11 | 12 | import java.math.BigDecimal; 13 | import java.sql.*; 14 | import java.util.Date; 15 | import java.util.*; 16 | 17 | /** 18 | * @author 周宁 19 | */ 20 | public class SpringJdbc implements ISpringJdbc { 21 | 22 | private JdbcTemplate jdbcTemplate; 23 | 24 | private static final int BATCH_PAGE_SIZE=2000; 25 | 26 | private static final Map paramSymbol = new HashMap(); 27 | 28 | @Override 29 | public String insertForId(String sql) throws Exception { 30 | return this.insertForId(sql, null); 31 | } 32 | 33 | @Override 34 | public JdbcTemplate getJdbcTemplate() { 35 | return jdbcTemplate; 36 | } 37 | 38 | public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { 39 | this.jdbcTemplate = jdbcTemplate; 40 | } 41 | 42 | @Override 43 | public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() { 44 | return new NamedParameterJdbcTemplate(jdbcTemplate); 45 | } 46 | 47 | @Override 48 | public String insertForId(final String sql, final Object[] args) throws Exception { 49 | String id = jdbcTemplate.execute((ConnectionCallback) con -> { 50 | PreparedStatement ps = (PreparedStatement) con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);// 传入参数:Statement.RETURN_GENERATED_KEYS 51 | if (args != null) { 52 | for (int i = 1; i <= args.length; i++) { 53 | Object arg = args[i - 1]; 54 | setParamater(ps, i, arg); 55 | } 56 | } 57 | ps.executeUpdate();// 执行sql 58 | ResultSet rs = ps.getGeneratedKeys();// 获取结果 59 | if (rs.next()) { 60 | return rs.getString(1);// 取得ID 61 | } else { 62 | return null; 63 | } 64 | }); 65 | return id; 66 | } 67 | 68 | @Override 69 | public int batchInsert(String sql, List batchArgs) throws Exception { 70 | return this.batchInsert(sql, batchArgs, null, 0); 71 | } 72 | 73 | @Override 74 | public int batchInsert(String sql, List batchArgs, int batchPageSize) throws Exception { 75 | return this.batchInsert(sql, batchArgs, null, batchPageSize); 76 | } 77 | 78 | @Override 79 | public int batchInsert(String sql, List batchArgs, int[] types) throws Exception { 80 | return this.batchInsert(sql, batchArgs, types, 0); 81 | } 82 | 83 | @Override 84 | public int batchInsert(String sql, List batchArgs, int[] types, int batchPageSize) throws Exception { 85 | if (batchPageSize <= 0) { 86 | batchPageSize = BATCH_PAGE_SIZE; 87 | } 88 | sql = sql.trim(); 89 | if (sql.endsWith(";")) { 90 | sql = sql.substring(0, sql.length() - 1); 91 | } 92 | int index = sql.toLowerCase().indexOf("values"); 93 | if (index == -1) { 94 | throw new GyjdbcException("此sql语句不能执行批量插入操作"); 95 | } 96 | index = sql.indexOf("(", index);// 查找values后第一个左括号位置 97 | String sqlLeft = sql.substring(0, index); 98 | String sqlRight = sql.substring(index); 99 | int batchSize = batchArgs.size(); 100 | int resultSize = 0; 101 | // 插入完整页的数据 102 | int wholeLength = batchSize / batchPageSize; 103 | StringBuffer sqlJoin = new StringBuffer(); 104 | if (wholeLength > 0) { 105 | sqlJoin.append(sqlLeft); 106 | sqlJoin.append(sqlRight); 107 | for (int i = 0; i < batchPageSize - 1; i++) { 108 | sqlJoin.append(",").append(sqlRight); 109 | } 110 | List params = new ArrayList(batchPageSize * batchArgs.get(0).length); 111 | int[] argTypes = null; 112 | if (types != null) { 113 | argTypes = new int[batchPageSize * types.length]; 114 | int length = types.length; 115 | for (int i = 0; i < batchPageSize; i++) { 116 | for (int j = 0; j < types.length; j++) { 117 | argTypes[i * length + j] = types[j]; 118 | } 119 | } 120 | } 121 | for (int i = 0; i < wholeLength; i++) { 122 | params.clear(); 123 | for (int j = 0; j < batchPageSize; j++) { 124 | Object[] args = batchArgs.get(i * batchPageSize + j); 125 | for (Object arg : args) { 126 | params.add(arg); 127 | } 128 | } 129 | if (argTypes == null) { 130 | resultSize += jdbcTemplate.update(sqlJoin.toString(), params.toArray()); 131 | } else { 132 | resultSize += jdbcTemplate.update(sqlJoin.toString(), params.toArray(), argTypes); 133 | } 134 | } 135 | } 136 | // 插入剩余的数据 137 | int surplusSize = batchSize % batchPageSize; 138 | if (surplusSize > 0) { 139 | sqlJoin.setLength(0); 140 | sqlJoin.append(sqlLeft); 141 | sqlJoin.append(sqlRight); 142 | for (int i = 0; i < surplusSize - 1; i++) { 143 | sqlJoin.append(",").append(sqlRight); 144 | } 145 | List params = new ArrayList(surplusSize * batchArgs.get(0).length); 146 | int[] argTypes = null; 147 | if (types != null) { 148 | argTypes = new int[surplusSize * types.length]; 149 | int length = types.length; 150 | for (int i = 0; i < surplusSize; i++) { 151 | for (int j = 0; j < types.length; j++) { 152 | argTypes[i * length + j] = types[j]; 153 | } 154 | } 155 | } 156 | for (int j = 0; j < surplusSize; j++) { 157 | Object[] args = batchArgs.get(wholeLength * batchPageSize + j); 158 | for (Object arg : args) { 159 | params.add(arg); 160 | } 161 | } 162 | if (argTypes == null) { 163 | resultSize += jdbcTemplate.update(sqlJoin.toString(), params.toArray()); 164 | } else { 165 | resultSize += jdbcTemplate.update(sqlJoin.toString(), params.toArray(), argTypes); 166 | } 167 | } 168 | return resultSize; 169 | } 170 | 171 | @Override 172 | public void batchUpdate(String sql, List batchArgs) throws Exception { 173 | this.batchUpdate(sql, batchArgs, null, 0); 174 | } 175 | 176 | @Override 177 | public void batchUpdate(String sql, List batchArgs, int batchPageSize) throws Exception { 178 | this.batchUpdate(sql, batchArgs, null, batchPageSize); 179 | } 180 | 181 | @Override 182 | public void batchUpdate(String sql, List batchArgs, int[] types, int batchPageSize) throws Exception { 183 | if (batchPageSize <= 0) { 184 | batchPageSize = BATCH_PAGE_SIZE; 185 | } 186 | sql = sql.trim(); 187 | if (sql.endsWith(";")) { 188 | sql = sql.substring(0, sql.length() - 1); 189 | } 190 | int batchSize = batchArgs.size(); 191 | // 插入完整页的数据 192 | int wholeLength = batchSize / batchPageSize; 193 | if (wholeLength > 0) { 194 | List params = new ArrayList(); 195 | int[] argTypes = null; 196 | if (types != null) { 197 | argTypes = new int[batchPageSize * types.length]; 198 | int length = types.length; 199 | for (int i = 0; i < batchPageSize; i++) { 200 | for (int j = 0; j < types.length; j++) { 201 | argTypes[i * length + j] = types[j]; 202 | } 203 | } 204 | } 205 | for (int i = 0; i < wholeLength; i++) { 206 | params.clear(); 207 | for (int j = 0; j < batchPageSize; j++) { 208 | Object[] args = batchArgs.get(i * batchPageSize + j); 209 | params.add(args); 210 | } 211 | if (argTypes == null) { 212 | jdbcTemplate.batchUpdate(sql, params); 213 | } else { 214 | jdbcTemplate.batchUpdate(sql, params, argTypes); 215 | } 216 | } 217 | } 218 | // 插入剩余的数据 219 | int surplusSize = batchSize % batchPageSize; 220 | if (surplusSize > 0) { 221 | List params = new ArrayList(); 222 | int[] argTypes = null; 223 | if (types != null) { 224 | argTypes = new int[surplusSize * types.length]; 225 | int length = types.length; 226 | for (int i = 0; i < surplusSize; i++) { 227 | for (int j = 0; j < types.length; j++) { 228 | argTypes[i * length + j] = types[j]; 229 | } 230 | } 231 | } 232 | for (int j = 0; j < surplusSize; j++) { 233 | Object[] args = batchArgs.get(wholeLength * batchPageSize + j); 234 | params.add(args); 235 | } 236 | if (argTypes == null) { 237 | jdbcTemplate.batchUpdate(sql.toString(), params); 238 | } else { 239 | jdbcTemplate.update(sql.toString(), params, argTypes); 240 | } 241 | } 242 | } 243 | 244 | 245 | @Override 246 | public void batchUpdate(String sql, List batchArgs, int[] types) throws Exception { 247 | this.batchUpdate(sql, batchArgs, types, 0); 248 | } 249 | 250 | 251 | @Override 252 | public int update(String sql, Object[] args) throws Exception { 253 | Object[] obj = this.changeMessage(sql, args); 254 | return jdbcTemplate.update((String) obj[0], (Object[]) obj[1], (int[]) obj[2]); 255 | } 256 | 257 | @Override 258 | public T query(String sql, ResultSetExtractor rse) throws Exception { 259 | return jdbcTemplate.query(sql, rse); 260 | } 261 | 262 | @Override 263 | public T query(String sql, Object[] args, ResultSetExtractor rse) throws Exception { 264 | Object[] obj = this.changeMessage(sql, args); 265 | return jdbcTemplate.query((String) obj[0], (Object[]) obj[1], (int[]) obj[2], rse); 266 | } 267 | 268 | @Override 269 | public List query(String sql, RowMapper rowMapper) throws Exception { 270 | return jdbcTemplate.query(sql, rowMapper); 271 | } 272 | 273 | @Override 274 | public List query(String sql, Object[] args, RowMapper rowMapper) throws Exception { 275 | Object[] obj = this.changeMessage(sql, args); 276 | return jdbcTemplate.query((String) obj[0], (Object[]) obj[1], (int[]) obj[2], rowMapper); 277 | } 278 | 279 | @Override 280 | public List query(String sql, Class elementType) throws Exception { 281 | return jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(elementType)); 282 | } 283 | 284 | @Override 285 | public List query(String sql, Object[] args, Class elementType) throws Exception { 286 | Object[] obj = this.changeMessage(sql, args); 287 | return jdbcTemplate.query((String) obj[0], (Object[]) obj[1], (int[]) obj[2], 288 | BeanPropertyRowMapper.newInstance(elementType)); 289 | } 290 | 291 | @Override 292 | public T queryForObject(String sql, Class requiredType) throws Exception { 293 | return jdbcTemplate.queryForObject(sql, requiredType); 294 | } 295 | 296 | @Override 297 | public T queryForObject(String sql, Object[] args, Class requiredType) throws Exception { 298 | List results = null; 299 | if (args != null && args.length > 0) { 300 | Object[] obj = this.changeMessage(sql, args); 301 | sql = (String) obj[0]; 302 | args = (Object[]) obj[1]; 303 | int[] argTypes = (int[]) obj[2]; 304 | results = jdbcTemplate.query(sql, args, argTypes, BeanPropertyRowMapper.newInstance(requiredType)); 305 | } else { 306 | results = jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(requiredType)); 307 | } 308 | return DataAccessUtils.singleResult(results); 309 | } 310 | 311 | @Override 312 | public List query(String sql, Map paramMap, Class elementType) throws Exception { 313 | Object[] args = NamedParameterUtils.buildValueArray(sql,paramMap); 314 | sql = NamedParameterUtils.parseSqlStatementIntoString(sql); 315 | return this.query(sql,args,elementType); 316 | } 317 | 318 | @Override 319 | public List> queryForList(String sql, Object[] args) throws Exception { 320 | Object[] obj = this.changeMessage(sql, args); 321 | return jdbcTemplate.queryForList((String) obj[0], (Object[]) obj[1]); 322 | } 323 | 324 | @SuppressWarnings({ "rawtypes", "unchecked" }) 325 | @Override 326 | public PageResult queryForPageResult(Page page, String sql, Object[] args, Class requiredType) throws Exception { 327 | Object[] obj = this.changeMessage(sql, args); 328 | String baseSql = (String) obj[0]; 329 | Object[] params = (Object[]) obj[1]; 330 | String pageSql = "SELECT SQL_CALC_FOUND_ROWS * FROM (" + baseSql + ") temp LIMIT ?,?"; 331 | params = ArrayUtils.add(params, page.getOffset()); 332 | params = ArrayUtils.add(params, page.getPageSize()); 333 | List paged = jdbcTemplate.query(pageSql, params, BeanPropertyRowMapper.newInstance(requiredType)); 334 | String countSql = "SELECT FOUND_ROWS() "; 335 | int count = jdbcTemplate.queryForObject(countSql, Integer.class); 336 | return new PageResult(paged, count); 337 | } 338 | 339 | @Override 340 | public PageResult queryForPageResult(Page page, String sql, Map paramMap, Class requiredType) throws Exception { 341 | Object[] args = NamedParameterUtils.buildValueArray(sql,paramMap); 342 | sql = NamedParameterUtils.parseSqlStatementIntoString(sql); 343 | return this.queryForPageResult(page, sql, args, requiredType); 344 | } 345 | 346 | private Object[] changeMessage(String sql, Object[] args) throws Exception { 347 | List params = new ArrayList(); 348 | List types = new ArrayList(); 349 | List paramList = new ArrayList(); 350 | for (int i = 0; i < args.length; i++) { 351 | Object arg = args[i]; 352 | if (arg.getClass().isArray()) { 353 | Object[] array = (Object[]) arg; 354 | if (array.length == 0) { 355 | throw new GyjdbcException("Array param can not be empty!"); 356 | } 357 | Integer type = null; 358 | for (Object obj : array) { 359 | if (type == null) { 360 | type = this.getTypes(obj); 361 | } 362 | params.add(obj); 363 | types.add(type); 364 | } 365 | if (array.length > 1) { 366 | paramList.add(new Object[]{i, getParamSymbol(array.length)}); 367 | } 368 | } else if (Collection.class.isAssignableFrom(arg.getClass())) { 369 | Collection list = (Collection) arg; 370 | if (list.size() == 0) { 371 | throw new GyjdbcException("Collection param can not be empty!"); 372 | } 373 | Integer type = null; 374 | for (Object obj : list) { 375 | if (type == null) { 376 | type = this.getTypes(obj); 377 | } 378 | params.add(obj); 379 | types.add(type); 380 | } 381 | if (list.size() > 1) { 382 | paramList.add(new Object[]{i, getParamSymbol(list.size())}); 383 | } 384 | } else { 385 | params.add(arg); 386 | types.add(this.getTypes(arg)); 387 | } 388 | } 389 | // 根据序号替换单个?为多个数组? 390 | if (!paramList.isEmpty()) { 391 | StringBuffer sqlb = new StringBuffer(); 392 | String sqls = sql.toString(); 393 | int count = -1; 394 | int index = -1; 395 | for (Object[] obj : paramList) { 396 | int paramIndex = (Integer) obj[0]; 397 | while (true) { 398 | count++; 399 | index = sqls.indexOf("?", index + 1); 400 | if (index == -1) { 401 | throw new GyjdbcException("Paramater size > '?' size!"); 402 | } 403 | if (paramIndex == count) { 404 | sqlb.append(sqls.substring(0, index)).append((String) obj[1]); 405 | sqls = sqls.substring(index + 1); 406 | index = -1; 407 | break; 408 | } 409 | } 410 | } 411 | sqlb.append(sqls); 412 | sql = sqlb.toString(); 413 | } 414 | 415 | int[] tys = new int[types.size()]; 416 | for (int i = 0; i < types.size(); i++) { 417 | tys[i] = types.get(i); 418 | } 419 | return new Object[]{sql, params.toArray(), tys}; 420 | } 421 | 422 | private int getTypes(Object arg) { 423 | if (String.class.equals(arg.getClass())) { 424 | return Types.VARCHAR; 425 | } else if (int.class.equals(arg.getClass()) || Integer.class.equals(arg.getClass())) { 426 | return Types.INTEGER; 427 | } else if (double.class.equals(arg.getClass()) || Double.class.equals(arg.getClass())) { 428 | return Types.DOUBLE; 429 | } else if (Date.class.isAssignableFrom(arg.getClass())) { 430 | return Types.TIMESTAMP; 431 | } else if (long.class.equals(arg.getClass()) || Long.class.equals(arg.getClass())) { 432 | return Types.BIGINT; 433 | } else if (float.class.equals(arg.getClass()) || Float.class.equals(arg.getClass())) { 434 | return Types.FLOAT; 435 | } else if (boolean.class.equals(arg.getClass()) || Boolean.class.equals(arg.getClass())) { 436 | return Types.BOOLEAN; 437 | } else if (short.class.equals(arg.getClass()) || Short.class.equals(arg.getClass())) { 438 | return Types.INTEGER; 439 | } else if (byte.class.equals(arg.getClass()) || Byte.class.equals(arg.getClass())) { 440 | return Types.INTEGER; 441 | } else if (BigDecimal.class.equals(arg.getClass())) { 442 | return Types.DECIMAL; 443 | } else { 444 | return Types.OTHER; 445 | } 446 | } 447 | 448 | private void setParamater(PreparedStatement ps, int i, Object arg) throws SQLException { 449 | if (String.class.equals(arg.getClass())) { 450 | ps.setString(i, (String) arg); 451 | } else if (int.class.equals(arg.getClass()) || Integer.class.equals(arg.getClass())) { 452 | ps.setInt(i, (Integer) arg); 453 | } else if (double.class.equals(arg.getClass()) || Double.class.equals(arg.getClass())) { 454 | ps.setDouble(i, (Double) arg); 455 | } else if (Date.class.isAssignableFrom(arg.getClass())) { 456 | ps.setTimestamp(i, new Timestamp(((Date) arg).getTime())); 457 | } else if (long.class.equals(arg.getClass()) || Long.class.equals(arg.getClass())) { 458 | ps.setLong(i, (Long) arg); 459 | } else if (float.class.equals(arg.getClass()) || Float.class.equals(arg.getClass())) { 460 | ps.setFloat(i, (Float) arg); 461 | } else if (boolean.class.equals(arg.getClass()) || Boolean.class.equals(arg.getClass())) { 462 | ps.setBoolean(i, (Boolean) arg); 463 | } else if (short.class.equals(arg.getClass()) || Short.class.equals(arg.getClass())) { 464 | ps.setShort(i, (Short) arg); 465 | } else if (byte.class.equals(arg.getClass()) || Byte.class.equals(arg.getClass())) { 466 | ps.setByte(i, (Byte) arg); 467 | } else if (BigDecimal.class.equals(arg.getClass())) { 468 | ps.setBigDecimal(i, (BigDecimal) arg); 469 | } else { 470 | throw new GyjdbcException("参数" + i + "属于未知的参数类型!"); 471 | } 472 | } 473 | 474 | private String getParamSymbol(int size) { 475 | String result = paramSymbol.get(size); 476 | if (result == null) { 477 | synchronized (paramSymbol) { 478 | StringBuffer sb = new StringBuffer("?"); 479 | for (int i = 1; i < size; i++) { 480 | sb.append(",?"); 481 | } 482 | result = sb.toString(); 483 | paramSymbol.put(size, result); 484 | } 485 | } 486 | return result; 487 | } 488 | } 489 | --------------------------------------------------------------------------------