diff --git a/.travis.yml b/.travis.yml index a1407b9..9e0d03b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,5 +2,5 @@ language: java jdk: - oraclejdk8 script: - - mvn install -Dmaven.test.skip=true + - mvn compile -Dmaven.test.skip=true diff --git a/README.md b/README.md index 7c08f45..d5104a6 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,13 @@ ## 更新日志 +### v0.2.2 + +1. 修复 `in` 查询问题 +2. 添加单条自定义类型查询 +3. 添加查询自定义类型列表 +4. SQL关键词大写 + ### v0.2.0 1. 使用Java8重构 diff --git a/pom.xml b/pom.xml index 9828cd3..9314df1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.bladejava blade-jdbc - 0.2.2-alpha1 + 0.2.2-RELEASE jar blade-jdbc @@ -53,8 +53,8 @@ org.projectlombok lombok - 1.16.16 - compile + 1.16.18 + provided diff --git a/src/main/java/com/blade/jdbc/Base.java b/src/main/java/com/blade/jdbc/Base.java index cfa3317..585617e 100644 --- a/src/main/java/com/blade/jdbc/Base.java +++ b/src/main/java/com/blade/jdbc/Base.java @@ -18,11 +18,19 @@ public final class Base { public static Sql2o open(String url, String user, String password) { sql2o = new Sql2o(url, user, password); + log.info("⬢ Blade-JDBC initializing"); return sql2o; } public static Sql2o open(DataSource dataSource) { sql2o = new Sql2o(dataSource); + log.info("⬢ Blade-JDBC initializing"); + return sql2o; + } + + public static Sql2o open(Sql2o sql2o_) { + sql2o = sql2o_; + log.info("⬢ Blade-JDBC initializing"); return sql2o; } @@ -35,14 +43,12 @@ public static Sql2o open(DataSource dataSource) { public static T atomic(Supplier supplier) { T result = null; try { - connectionThreadLocal.remove(); - connectionThreadLocal.set(sql2o.beginTransaction()); - try (Connection con = connectionThreadLocal.get()) { - result = supplier.get(); - con.commit(); - } + Connection connection = sql2o.beginTransaction(); + connectionThreadLocal.set(connection); + result = supplier.get(); + connection.commit(); } catch (RuntimeException e) { - log.info("Transaction rollback"); + log.warn("Transaction rollback"); connectionThreadLocal.get().rollback(); throw e; } finally { diff --git a/src/main/java/com/blade/jdbc/Const.java b/src/main/java/com/blade/jdbc/Const.java new file mode 100644 index 0000000..f75e633 --- /dev/null +++ b/src/main/java/com/blade/jdbc/Const.java @@ -0,0 +1,25 @@ +package com.blade.jdbc; + +/** + * Blade JDBC Const + * + * @author biezhi + * @date 2017/11/10 + */ +public interface Const { + + String SPACE = " "; + String SQL_AND = "AND"; + String SQL_OR = "OR"; + String SQL_WHERE = "WHERE"; + String SQL_IN = "IN"; + String SQL_INSERT = "INSERT INTO"; + + String SQL_QM = "?"; + String EXECUTE_SQL_PREFIX = "⬢ Execute SQL"; + String PARAMETER_PREFIX = "⬢ Parameters "; + + char IN_START = '('; + char IN_END = ')'; + +} diff --git a/src/main/java/com/blade/jdbc/core/ActiveRecord.java b/src/main/java/com/blade/jdbc/core/ActiveRecord.java index 95394e3..5e89f0e 100644 --- a/src/main/java/com/blade/jdbc/core/ActiveRecord.java +++ b/src/main/java/com/blade/jdbc/core/ActiveRecord.java @@ -7,17 +7,26 @@ import com.blade.jdbc.page.PageRow; import com.blade.jdbc.utils.Unchecked; import lombok.Setter; +import lombok.extern.slf4j.Slf4j; import org.sql2o.Connection; import org.sql2o.Query; import org.sql2o.Sql2o; import java.io.Serializable; -import java.lang.invoke.SerializedLambda; -import java.lang.reflect.Method; import java.util.*; import java.util.function.Supplier; +import java.util.stream.Collectors; import java.util.stream.Stream; +import static com.blade.jdbc.Const.*; + +/** + * ActiveRecord Parent Class + * + * @author biezhi + * @date 2017/11/10 + */ +@Slf4j public class ActiveRecord implements Serializable { @Transient @@ -30,10 +39,6 @@ public class ActiveRecord implements Serializable { @Transient private Set saveOrUpdateProperties = new TreeSet<>(); - @Transient - private List whereKeys = new ArrayList<>(); - private List whereVals = new ArrayList<>(); - public ActiveRecord() { } @@ -44,58 +49,6 @@ public Sql2o getSql2o() { return Base.sql2o; } - public T where(LambdaExpression action) { - action.apply((T) this); - - SerializedLambda lambda = getSerializedLambda(action); - - System.out.println("lambdaClassName:" + lambda.getImplClass()); - System.out.println("lambdaMethodName:" + lambda.getImplMethodName()); - - return null; - } - - // getting the SerializedLambda - public SerializedLambda getSerializedLambda(LambdaExpression action) { - for (Class clazz = action.getClass(); clazz != null; clazz = clazz.getSuperclass()) { - try { - Method replaceMethod = clazz.getDeclaredMethod("writeReplace"); - replaceMethod.setAccessible(true); - Object serializedForm = replaceMethod.invoke(action); - - if (serializedForm instanceof SerializedLambda) { - return (SerializedLambda) serializedForm; - } - } catch (NoSuchMethodError e) { - // fall through the loop and try the next class - } catch (Throwable t) { - throw new RuntimeException("Error while extracting serialized lambda", t); - } - } - throw new RuntimeException("writeReplace method not found"); - } - - // getting the synthetic static lambda method - public static Method getLambdaMethod(SerializedLambda lambda) throws Exception { - String implClassName = lambda.getImplClass().replace('/', '.'); - Class implClass = Class.forName(implClassName); - - String lambdaName = lambda.getImplMethodName(); - - for (Method m : implClass.getDeclaredMethods()) { - if (m.getName().equals(lambdaName)) { - return m; - } - } - - throw new Exception("Lambda Method not found"); - } - - public T is(Object value) { - - return (T) this; - } - public T where(String key, Object value) { return this.where(key, "=", value); } @@ -107,7 +60,7 @@ public T where(String key, String opt, Object value) { } public T like(String key, Object value) { - return this.where(key, "like", value); + return this.where(key, "LIKE", value); } public T and(String key, Object value) { @@ -123,31 +76,29 @@ public T or(String key, Object value) { } public T or(String key, String opt, Object value) { - return this.where(" or " + key, opt, value); + return this.where(" OR " + key, opt, value); } - // TODO - public T between(String key, Object val1, Object val2) { - // date between ? and ? - this.whereValues.add(WhereParam.builder().key(key).opt("between").value(val1).build()); - this.saveOrUpdateProperties.add(key); - return (T) this; + public T in(String key, List args) { + return this.where(key, "IN", args); } public S save() { QueryMeta queryMeta = SqlBuilder.buildInsertSql(this); try (Connection con = getConn()) { - return (S) con.createQuery(queryMeta.getSql()).bind(this).executeUpdate().getKey(); + log.debug(EXECUTE_SQL_PREFIX + " => {}", queryMeta.getSql()); + Query query = con.createQuery(queryMeta.getSql()).bind(this); + return (S) query.executeUpdate().getKey(); } } - public void update(Serializable pk) { - this.update(getPk(), pk); + public int update(Serializable pk) { + return this.update(getPk(), pk); } - public void update(String field, Object value) { + public int update(String field, Object value) { this.whereValues.add(WhereParam.builder().key(field).opt("=").value(value).build()); - this.update(); + return this.update(); } public int update() { @@ -157,57 +108,88 @@ public int update() { return result; } - public void execute(String sql, Object... params) { + public int execute(String sql, Object... params) { int pos = 1; - while (sql.indexOf("?") != -1) { - sql = sql.replaceFirst("\\?", ":p" + pos); + while (sql.contains(SQL_QM)) { + sql = sql.replaceFirst("\\?", ":p" + (pos++)); } - invoke(new QueryMeta(sql, params)); + return invoke(new QueryMeta(sql, params)); } private int invoke(QueryMeta queryMeta) { - if (null == Base.connectionThreadLocal.get()) { - try (Connection con = getSql2o().open()) { - return con.createQuery(queryMeta.getSql()).withParams(queryMeta.getParams()).executeUpdate().getResult(); + log.debug(EXECUTE_SQL_PREFIX + " => {}", queryMeta.getSql()); + log.debug(PARAMETER_PREFIX + " => {}", Arrays.toString(queryMeta.getParams())); + Connection con = getConn(); + try { + Query query = con.createQuery(queryMeta.getSql()).withParams(queryMeta.getParams()); + if (queryMeta.hasColumnMapping()) { + queryMeta.getColumnMapping().forEach(query::addColumnMapping); + } + return query.executeUpdate().getResult(); + } finally { + if (Base.connectionThreadLocal.get() == null) { + if (null != con) { + con.close(); + } } - } else { - Connection con = getConn(); - return con.createQuery(queryMeta.getSql()).withParams(queryMeta.getParams()).executeUpdate().getResult(); } } private Connection getConn() { - return null != Base.connectionThreadLocal.get() ? Base.connectionThreadLocal.get() : getSql2o().open(); + Connection connection = Base.connectionThreadLocal.get(); + if (null != connection) { + return connection; + } + return getSql2o().open(); } public T query(String sql, Object... args) { + return this.query((Class) getClass(), sql, args); + } + + public T query(Class type, String sql, Object... args) { int pos = 1; - while (sql.indexOf("?") != -1) { - sql = sql.replaceFirst("\\?", ":p" + pos); + while (sql.indexOf(SQL_QM) != -1) { + sql = sql.replaceFirst("\\?", ":p" + (pos++)); } - Class type = (Class) getClass(); try (Connection con = getSql2o().open()) { + log.debug(EXECUTE_SQL_PREFIX + " => {}", sql); + log.debug(PARAMETER_PREFIX + " => {}", Arrays.toString(args)); this.cleanParam(); - return con.createQuery(sql).withParams(args) - .executeAndFetchFirst(type); + Query query = con.createQuery(sql).withParams(args).throwOnMappingFailure(false); + QueryMeta queryMeta = SqlBuilder.buildFindAllSql(this, null); + if (queryMeta.hasColumnMapping()) { + queryMeta.getColumnMapping().forEach(query::addColumnMapping); + } + return query.executeAndFetchFirst(type); } } public List queryAll(String sql, Object... args) { + return this.queryAll((Class) getClass(), sql, args); + } + + public List queryAll(Class type, String sql, Object... args) { int pos = 1; - while (sql.indexOf("?") != -1) { - sql = sql.replaceFirst("\\?", ":p" + pos); + while (sql.indexOf(SQL_QM) != -1) { + sql = sql.replaceFirst("\\?", ":p" + (pos++)); } PageRow pageRow = Base.pageLocal.get(); String limit = SqlBuilder.appendLimit(pageRow); if (null != limit) { sql += limit; } - Class type = (Class) getClass(); + args = args == null ? new Object[]{} : args; try (Connection con = getSql2o().open()) { + log.debug(EXECUTE_SQL_PREFIX + " => {}", sql); + log.debug(PARAMETER_PREFIX + " => {}", Arrays.toString(args)); this.cleanParam(); - return con.createQuery(sql).withParams(args) - .executeAndFetch(type); + Query query = con.createQuery(sql).withParams(args).throwOnMappingFailure(false); + QueryMeta queryMeta = SqlBuilder.buildFindAllSql(this, null); + if (queryMeta.hasColumnMapping()) { + queryMeta.getColumnMapping().forEach(query::addColumnMapping); + } + return query.executeAndFetch(type); } } @@ -215,62 +197,68 @@ public List findAll() { return this.findAll(null); } - public List findAll(Supplier... conditions) { + public List findAll(Class type, Supplier... conditions) { QueryMeta queryMeta = SqlBuilder.buildFindAllSql(this, conditions); - Class type = (Class) getClass(); try (Connection con = getSql2o().open()) { - Query query = con.createQuery(queryMeta.getSql()).withParams(queryMeta.getParams()); + log.debug(EXECUTE_SQL_PREFIX + " => {}", queryMeta.getSql()); + log.debug(PARAMETER_PREFIX + " => {}", Arrays.toString(queryMeta.getParams())); + this.cleanParam(); + Query query = con.createQuery(queryMeta.getSql()).withParams(queryMeta.getParams()).throwOnMappingFailure(false); if (queryMeta.hasColumnMapping()) { queryMeta.getColumnMapping().forEach(query::addColumnMapping); } - this.cleanParam(); return query.executeAndFetch(type); } } + public List findAll(Supplier... conditions) { + return this.findAll((Class) getClass(), conditions); + } + public Page page(int page, int limit) { - return this.page(new PageRow(page, limit)); + return this.page(page, limit, null); + } + + public Page page(int page, int limit, String orderBy) { + return this.page(new PageRow(page, limit), orderBy); } public Page page(PageRow pageRow) { - return page(pageRow, null, null); + return page(pageRow, null); + } + + public Page page(PageRow pageRow, String orderBy) { + QueryMeta queryMeta = SqlBuilder.buildFindAllSql(this, null); + return page(pageRow, queryMeta.getSql(), orderBy, queryMeta.getParams()); } public Page page(PageRow pageRow, String sql, Object... params) { + return page(pageRow, sql, null, params); + } + + public Page page(PageRow pageRow, String sql, String orderBy, Object... params) { Base.pageLocal.set(pageRow); int page = pageRow.getPage(); int limit = pageRow.getLimit(); if (null != sql) { int pos = 1; - while (sql.indexOf("?") != -1) { - sql = sql.replaceFirst("\\?", ":p" + pos); + while (sql.indexOf(SQL_QM) != -1) { + sql = sql.replaceFirst("\\?", ":p" + (pos++)); } + } else { + sql = "SELECT * FROM " + getTableName(); } - String countSql = "select count(*) from (" + sql + ") tmp"; + String countSql = "SELECT COUNT(0) FROM (" + sql + ") tmp"; long count = this.count(countSql, params); - List list = this.queryAll(sql, params); + if (null != orderBy) { + sql += " ORDER BY " + orderBy; + } - Page pageBean = new Page<>(); - pageBean.setTotalRow(count); + List list = this.queryAll(sql, params); + Page pageBean = new Page<>(count, page, limit); pageBean.setRows(list); - pageBean.setPage(page); - pageBean.setTotalPages(count / limit + (count % limit != 0 ? 1 : 0)); - if (pageBean.getTotalPages() > page) { - pageBean.setNextPage(page + 1); - } else { - pageBean.setNextPage(page); - } - if (page > 1) { - if (page > pageBean.getTotalPages()) { - pageBean.setPrevPage(1); - } else { - pageBean.setPrevPage(page - 1); - } - } else { - pageBean.setPrevPage(1); - } Base.pageLocal.remove(); return pageBean; } @@ -280,8 +268,11 @@ public T find() { Class type = (Class) getClass(); try (Connection con = getSql2o().open()) { this.cleanParam(); - Query query = con.createQuery(queryMeta.getSql()) - .withParams(queryMeta.getParams()); + + log.debug(EXECUTE_SQL_PREFIX + " => {}", queryMeta.getSql()); + log.debug(PARAMETER_PREFIX + " => {}", Arrays.toString(queryMeta.getParams())); + + Query query = con.createQuery(queryMeta.getSql()).withParams(queryMeta.getParams()).throwOnMappingFailure(false); if (queryMeta.hasColumnMapping()) { queryMeta.getColumnMapping().forEach(query::addColumnMapping); } @@ -289,15 +280,17 @@ public T find() { } } - public T find(Serializable id) { - String sql = "select * from " + getTableName() + " where " + getPk() + " = :p1"; + public T find(Class type, Serializable id) { + String sql = "SELECT * FROM " + getTableName() + " WHERE " + getPk() + " = :p1"; QueryMeta queryMeta = new QueryMeta(); SqlBuilder.mapping(queryMeta, this.getClass()); - - Class type = (Class) getClass(); try (Connection con = getSql2o().open()) { this.cleanParam(); - Query query = con.createQuery(sql).withParams(id); + + log.debug(EXECUTE_SQL_PREFIX + " => {}", sql); + log.debug(PARAMETER_PREFIX + " => [{}]", id); + + Query query = con.createQuery(sql).withParams(id).throwOnMappingFailure(false); if (queryMeta.hasColumnMapping()) { queryMeta.getColumnMapping().forEach(query::addColumnMapping); } @@ -305,10 +298,18 @@ public T find(Serializable id) { } } + public T find(Serializable id) { + return find((Class) getClass(), id); + } + private long count(boolean cleanParam) { QueryMeta queryMeta = SqlBuilder.buildCountSql(this); try (Connection con = getSql2o().open()) { if (cleanParam) this.cleanParam(); + + log.debug(EXECUTE_SQL_PREFIX + " => {}", queryMeta.getSql()); + log.debug(PARAMETER_PREFIX + " => {}", Arrays.toString(queryMeta.getParams())); + return con.createQuery(queryMeta.getSql()) .withParams(queryMeta.getParams()) .executeAndFetchFirst(Long.class); @@ -322,10 +323,15 @@ public long count() { public long count(String sql, Object... args) { int pos = 1; while (sql.indexOf("?") != -1) { - sql = sql.replaceFirst("\\?", ":p" + pos); + sql = sql.replaceFirst("\\?", ":p" + (pos++)); } + args = args == null ? new Object[]{} : args; try (Connection con = getSql2o().open()) { this.cleanParam(); + + log.debug(EXECUTE_SQL_PREFIX + " => {}", sql); + log.debug(PARAMETER_PREFIX + " => {}", Arrays.toString(args)); + return con.createQuery(sql).withParams(args) .executeAndFetchFirst(Long.class); } @@ -335,33 +341,34 @@ String getTableName() { Class modelType = getClass(); Table table = modelType.getAnnotation(Table.class); if (null != table) { - return table.value().toLowerCase(); + return table.value(); } - return modelType.getSimpleName().toLowerCase(); + return modelType.getSimpleName(); } private String getPk() { Class modelType = getClass(); Table table = modelType.getAnnotation(Table.class); if (null != table) { - return table.pk().toLowerCase(); + return table.pk(); } return "id"; } - public void delete() { + public int delete() { QueryMeta queryMeta = SqlBuilder.buildDeleteSql(this); - this.invoke(queryMeta); + int result = this.invoke(queryMeta); this.cleanParam(); + return result; } - public void delete(Serializable pk) { - this.delete(getPk(), pk); + public int delete(Serializable pk) { + return this.delete(getPk(), pk); } - public void delete(String field, Object value) { + public int delete(String field, Object value) { whereValues.add(WhereParam.builder().key(field).opt("=").value(value).build()); - this.delete(); + return this.delete(); } private void cleanParam() { diff --git a/src/main/java/com/blade/jdbc/core/LambdaExpression.java b/src/main/java/com/blade/jdbc/core/LambdaExpression.java deleted file mode 100644 index 9ec6480..0000000 --- a/src/main/java/com/blade/jdbc/core/LambdaExpression.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.blade.jdbc.core; - -import java.io.Serializable; -import java.util.function.Function; - -/** - * @author biezhi - * @date 2017/8/21 - */ -@FunctionalInterface -public interface LambdaExpression extends Function, Serializable { - -} diff --git a/src/main/java/com/blade/jdbc/core/OrderBy.java b/src/main/java/com/blade/jdbc/core/OrderBy.java index 5910820..4b76144 100644 --- a/src/main/java/com/blade/jdbc/core/OrderBy.java +++ b/src/main/java/com/blade/jdbc/core/OrderBy.java @@ -14,11 +14,11 @@ private OrderBy(String orderBy) { } public static OrderBy asc(String field) { - return new OrderBy(field + " asc"); + return new OrderBy(field + " ASC"); } public static OrderBy desc(String field) { - return new OrderBy(field + " desc"); + return new OrderBy(field + " DESC"); } public static OrderBy of(String orderBy) { diff --git a/src/main/java/com/blade/jdbc/core/SqlBuilder.java b/src/main/java/com/blade/jdbc/core/SqlBuilder.java index 99620c3..5892a7b 100644 --- a/src/main/java/com/blade/jdbc/core/SqlBuilder.java +++ b/src/main/java/com/blade/jdbc/core/SqlBuilder.java @@ -17,6 +17,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static com.blade.jdbc.Const.*; + /** * SQl构造器 * @@ -34,11 +36,11 @@ class SqlBuilder { static QueryMeta buildInsertSql(ActiveRecord activeRecord) { QueryMeta queryMeta = new QueryMeta(); String tableName = activeRecord.getTableName(); - StringBuilder sb = new StringBuilder("insert into "); + StringBuilder sb = new StringBuilder(SQL_INSERT + " "); sb.append(tableName); sb.append(" ("); - StringBuffer values = new StringBuffer(" values ("); + StringBuffer values = new StringBuffer(" VALUES ("); Stream.of(activeRecord.getClass().getDeclaredFields()) .filter(field -> null == field.getAnnotation(Transient.class)) .forEach(field -> { @@ -71,21 +73,24 @@ static QueryMeta buildUpdateSql(ActiveRecord activeRecord) { QueryMeta queryMeta = new QueryMeta(); String sql; String tableName = activeRecord.getTableName(); - StringBuilder sb = new StringBuilder("update "); + StringBuilder sb = new StringBuilder("UPDATE "); sb.append(tableName); - sb.append(" set "); + sb.append(" SET "); final int[] pos = {1}; List list = parseSet(activeRecord, pos, sb); - sb.append("where "); + sb.append(SQL_WHERE).append(SPACE); activeRecord.whereValues.forEach(where -> { - sb.append(where.getKey()).append(" ").append(where.getOpt()).append(" ").append(":p").append(pos[0]++).append(" and "); + sb.append(where.getKey()).append(SPACE) + .append(where.getOpt()).append(SPACE) + .append(":p").append(pos[0]++).append(SPACE).append(SQL_AND).append(SPACE); list.add(where.getValue()); }); - sql = sb.toString().replace(", where ", " where ").replace("and or", "or"); - if (sql.endsWith("and ")) { + sql = sb.toString().replace(", " + SQL_WHERE + SPACE, SPACE + SQL_WHERE + SPACE) + .replace(SQL_AND + SPACE + SQL_OR, SQL_OR); + if (sql.endsWith(SQL_AND + SPACE)) { sql = sql.substring(0, sql.length() - 5); } @@ -172,7 +177,7 @@ static QueryMeta buildFindAllSql(ActiveRecord activeRecord, Supplier list = parseWhere(activeRecord, pos, sqlBuf); @@ -196,7 +201,7 @@ static QueryMeta buildCountSql(ActiveRecord activeRecord) { */ static QueryMeta buildDeleteSql(ActiveRecord activeRecord) { QueryMeta queryMeta = new QueryMeta(); - StringBuilder sqlBuf = new StringBuilder("delete from " + activeRecord.getTableName()); + StringBuilder sqlBuf = new StringBuilder("DELETE FROM " + activeRecord.getTableName()); int[] pos = {1}; List list = parseWhere(activeRecord, pos, sqlBuf); @@ -204,8 +209,8 @@ static QueryMeta buildDeleteSql(ActiveRecord activeRecord) { if (activeRecord.whereValues.isEmpty()) { throw new RuntimeException("Delete operation must take conditions."); } else { - if (sqlBuf.indexOf(" where ") == -1) { - sqlBuf.append(" where "); + if (sqlBuf.indexOf(SPACE + SQL_WHERE + SPACE) == -1) { + sqlBuf.append(SPACE + SQL_WHERE + SPACE); } } @@ -216,8 +221,8 @@ static QueryMeta buildDeleteSql(ActiveRecord activeRecord) { String sql = sqlBuf.toString(); - sql = sql.replace(", where", " where").replace("and or", "or"); - if (sql.endsWith("and ")) { + sql = sql.replace(", WHERE", " WHERE").replace("AND OR", "OR"); + if (sql.endsWith(SQL_AND + SPACE)) { sql = sql.substring(0, sql.length() - 5); } @@ -237,12 +242,21 @@ static QueryMeta buildDeleteSql(ActiveRecord activeRecord) { */ private static List andWhere(ActiveRecord activeRecord, int[] pos, StringBuilder sqlBuf) { if (!activeRecord.whereValues.isEmpty()) { - if (sqlBuf.indexOf(" where ") == -1) { - sqlBuf.append(" where "); + if (sqlBuf.indexOf(SPACE + SQL_WHERE + SPACE) == -1) { + sqlBuf.append(SPACE + SQL_WHERE + SPACE); } return activeRecord.whereValues.stream() .map(where -> { - sqlBuf.append(where.getKey()).append(" ").append(where.getOpt()).append(" ").append(":p").append(pos[0]++).append(" and "); + String c = where.getOpt(); + sqlBuf.append(where.getKey()).append(" ").append(c).append(" "); + if (c.equals(SQL_IN)) { + sqlBuf.append(IN_START); + } + sqlBuf.append(":p").append(pos[0]++); + if (c.equals(SQL_IN)) { + sqlBuf.append(IN_END); + } + sqlBuf.append(" AND "); return where.getValue(); }) .collect(Collectors.toList()); @@ -266,12 +280,12 @@ private static List parseWhere(ActiveRecord activeRecord, int[] pos, Str return field.get(activeRecord); })) .map(field -> Unchecked.wrap(() -> { - if (sqlBuf.indexOf(" where ") == -1) { - sqlBuf.append(" where "); + if (sqlBuf.indexOf(SPACE + SQL_WHERE + SPACE) == -1) { + sqlBuf.append(SPACE + SQL_WHERE + SPACE); } Object value = field.get(activeRecord); Pair pair = getColumnName(field); - sqlBuf.append(pair.getRight()).append(" = ").append(":p").append(pos[0]++).append(" and "); + sqlBuf.append(pair.getRight()).append(" = ").append(":p").append(pos[0]++).append(" AND "); return value; })) .collect(Collectors.toList()); @@ -285,7 +299,7 @@ private static List parseWhere(ActiveRecord activeRecord, int[] pos, Str * @return 返回sql语句 */ private static String parseFieldsSql(String tableName, Supplier[] conditions) { - final String[] sql = {"select * from " + tableName}; + final String[] sql = {"SELECT * FROM " + tableName}; if (null == conditions) { return sql[0]; } @@ -295,7 +309,7 @@ private static String parseFieldsSql(String tableName, Supplier[] .ifPresent(conditionEnumSupplier -> { Fields fields = (Fields) conditionEnumSupplier; Set fieldsSet = fields.getFields(); - sql[0] = "select " + fieldsSet.stream().collect(Collectors.joining(",")) + " from " + tableName; + sql[0] = "SELECT " + fieldsSet.stream().collect(Collectors.joining(",")) + " FROM " + tableName; }); return sql[0]; } @@ -307,8 +321,8 @@ private static String parseFieldsSql(String tableName, Supplier[] * @return 返回过滤后的sql */ private static String sqlFilter(String sql) { - sql = sql.replace(", where", " where").replace("and or", "or"); - if (sql.endsWith(" and ")) { + sql = sql.replace(", WHERE", " WHERE").replace("AND OR", "OR"); + if (sql.endsWith(SPACE + SQL_AND + SPACE)) { sql = sql.substring(0, sql.length() - 5); } if (sql.endsWith(", ")) { @@ -321,7 +335,7 @@ public static String appendLimit(PageRow pageRow) { if (null == pageRow) { return null; } - return String.format(" limit %s, %s", pageRow.getOffset(), pageRow.getLimit()); + return String.format(" LIMIT %s, %s", pageRow.getOffset(), pageRow.getLimit()); } private static String parseOrderBySql(Supplier[] conditions) { @@ -334,7 +348,7 @@ private static String parseOrderBySql(Supplier[] conditions) { .findFirst() .ifPresent(conditionEnumSupplier -> { OrderBy orderBy = (OrderBy) conditionEnumSupplier; - sql[0] = " order by " + orderBy.getOrderBy(); + sql[0] = " ORDER BY " + orderBy.getOrderBy(); }); return sql[0]; } @@ -349,8 +363,7 @@ private static List parseSet(ActiveRecord activeRecord, int[] pos, Strin .map(field -> Unchecked.wrap(() -> { Object value = field.get(activeRecord); Pair pair = getColumnName(field); - - sqlBuf.append(pair.getRight()).append(" = ").append(":p").append(pos[0]++).append(", "); + sqlBuf.append(pair.getLeft()).append(" = ").append(":p").append(pos[0]++).append(", "); return value; })) .collect(Collectors.toList()); diff --git a/src/main/java/com/blade/jdbc/page/Page.java b/src/main/java/com/blade/jdbc/page/Page.java index b27ebba..5ed645c 100644 --- a/src/main/java/com/blade/jdbc/page/Page.java +++ b/src/main/java/com/blade/jdbc/page/Page.java @@ -1,7 +1,6 @@ package com.blade.jdbc.page; import lombok.Data; -import lombok.ToString; import java.util.List; import java.util.function.Function; @@ -14,33 +13,119 @@ * @date 2017/7/24 */ @Data -@ToString public class Page { - private long page; - private long prevPage; - private long nextPage; - private long totalPages; - private long totalRow; + // 当前页 + private int pageNum = 1; + // 每页多少条 + private int limit = 10; + // 上一页 + private int prevPage = 1; + // 下一页 + private int nextPage = 1; + // 总页数 + private int totalPages = 1; + // 总记录数 + private long totalRows = 0L; + // 记录行 private List rows; + //是否为第一页 + private boolean isFirstPage = false; + + //是否为最后一页 + private boolean isLastPage = false; + + //是否有前一页 + private boolean hasPrevPage = false; + + //是否有下一页 + private boolean hasNextPage = false; + + //导航页码数 + private int navPages = 8; + + //所有导航页号 + private int[] navPageNums; public Page map(Function mapper) { - Page page = new Page<>(); + Page page = new Page<>(this.totalRows, this.pageNum, this.limit); page.setRows(rows.stream().map(mapper).collect(Collectors.toList())); - page.setPage(this.page); - page.setNextPage(this.nextPage); - page.setPrevPage(this.prevPage); - page.setTotalPages(this.totalPages); - page.setTotalRow(this.totalRow); return page; } - public boolean hasNext() { - return this.nextPage > this.page; + public Page() { + } + + public Page(long total, int page, int limit) { + init(total, page, limit); + } + + private void init(long total, int pageNum, int limit) { + //设置基本参数 + this.totalRows = total; + this.limit = limit; + this.totalPages = (int) ((this.totalRows - 1) / this.limit + 1); + + //根据输入可能错误的当前号码进行自动纠正 + if (pageNum < 1) { + this.pageNum = 1; + } else if (pageNum > this.totalPages) { + this.pageNum = this.totalPages; + } else { + this.pageNum = pageNum; + } + + //基本参数设定之后进行导航页面的计算 + this.calcNavigatePageNumbers(); + + //以及页面边界的判定 + judgePageBoudary(); + } + + private void calcNavigatePageNumbers() { + //当总页数小于或等于导航页码数时 + if (this.totalPages <= navPages) { + navPageNums = new int[totalPages]; + for (int i = 0; i < totalPages; i++) { + navPageNums[i] = i + 1; + } + } else { + //当总页数大于导航页码数时 + navPageNums = new int[navPages]; + int startNum = pageNum - navPages / 2; + int endNum = pageNum + navPages / 2; + if (startNum < 1) { + startNum = 1; + // 最前navPageCount页 + for (int i = 0; i < navPages; i++) { + navPageNums[i] = startNum++; + } + } else if (endNum > totalPages) { + endNum = totalPages; + //最后navPageCount页 + for (int i = navPages - 1; i >= 0; i--) { + navPageNums[i] = endNum--; + } + } else { + //所有中间页 + for (int i = 0; i < navPages; i++) { + navPageNums[i] = startNum++; + } + } + } } - public boolean hasPrev() { - return this.prevPage < this.page; + private void judgePageBoudary() { + isFirstPage = pageNum == 1; + isLastPage = pageNum == totalPages && pageNum != 1; + hasPrevPage = pageNum != 1; + hasNextPage = pageNum != totalPages; + if (hasNextPage) { + nextPage = pageNum + 1; + } + if (hasPrevPage) { + prevPage = pageNum - 1; + } } -} +} \ No newline at end of file diff --git a/src/test/java/com/blade/jdbc/test/BaseTestCase.java b/src/test/java/com/blade/jdbc/test/BaseTestCase.java index 853c3c6..155c648 100644 --- a/src/test/java/com/blade/jdbc/test/BaseTestCase.java +++ b/src/test/java/com/blade/jdbc/test/BaseTestCase.java @@ -1,16 +1,34 @@ package com.blade.jdbc.test; import com.blade.jdbc.Base; +import com.blade.jdbc.test.model.User; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; import org.junit.Before; +import org.junit.Test; +import org.sql2o.Connection; +import org.sql2o.Sql2o; + +import java.util.List; /** * Created by biezhi on 03/07/2017. */ -public abstract class BaseTestCase { +public class BaseTestCase { @Before public void before() { - Base.open("jdbc:mysql://localhost:3306/demo", "root", "123456"); + HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:mysql://localhost:3306/demo"); + config.setUsername("root"); + config.setPassword("123456"); + config.addDataSourceProperty("cachePrepStmts", "true"); + config.addDataSourceProperty("prepStmtCacheSize", "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + + HikariDataSource ds = new HikariDataSource(config); + Base.open(ds); +// Base.open("jdbc:mysql://localhost:3306/demo", "root", "123456"); } } diff --git a/src/test/java/com/blade/jdbc/test/PageTest.java b/src/test/java/com/blade/jdbc/test/PageTest.java index 3dd6ea0..870cc3c 100644 --- a/src/test/java/com/blade/jdbc/test/PageTest.java +++ b/src/test/java/com/blade/jdbc/test/PageTest.java @@ -15,6 +15,9 @@ public void test1() { User user = new User(); Page page = user.page(1, 3); System.out.println(page); + + page = user.page(1, 3, "age desc"); + System.out.println(page); } @Test diff --git a/src/test/java/com/blade/jdbc/test/ReadTest.java b/src/test/java/com/blade/jdbc/test/ReadTest.java index c967686..2284c1d 100644 --- a/src/test/java/com/blade/jdbc/test/ReadTest.java +++ b/src/test/java/com/blade/jdbc/test/ReadTest.java @@ -5,6 +5,8 @@ import com.blade.jdbc.test.model.User; import org.junit.Test; +import java.lang.reflect.Array; +import java.util.Arrays; import java.util.List; /** @@ -45,8 +47,6 @@ public void test3() { List list = user.where("username", "jack").findAll(); System.out.println(list); -// user.where(User::getUsername).is("jack").findAll(); - list = user.findAll(Fields.of("username"), OrderBy.desc("id")); System.out.println(list); @@ -69,8 +69,12 @@ public void test5() { @Test public void test6() { User user = new User(); - System.out.println(user.query("select * from t_user order by id desc")); - System.out.println(user.query("select * from t_user where id = ?", 1)); + + List list = user.queryAll("select * from t_user order by id desc"); + System.out.println(list); + + User one = user.query("select * from t_user where id = ?", 1); + System.out.println(one); } @Test @@ -87,4 +91,12 @@ public void testLike() { List users = user.like("username", "%jac%").and("age", ">", 18).findAll(); System.out.println(users); } + + @Test + public void testIn() { + User user = new User(); + List ids = Arrays.asList(1, 2, 3, 4); + List users = user.in("id", ids).findAll(); + System.out.println(users); + } } \ No newline at end of file diff --git a/src/test/java/com/blade/jdbc/test/TransactionTest.java b/src/test/java/com/blade/jdbc/test/TransactionTest.java index 9cf71ea..11ccd71 100644 --- a/src/test/java/com/blade/jdbc/test/TransactionTest.java +++ b/src/test/java/com/blade/jdbc/test/TransactionTest.java @@ -15,7 +15,7 @@ public void test1() { User user = new User(); user.setPassword("999"); user.update(42); -// int a = 1 / 0; + int a = 1 / 0; System.out.println("aasdasd"); return true; }); diff --git a/src/test/java/com/blade/jdbc/test/UpdateTest.java b/src/test/java/com/blade/jdbc/test/UpdateTest.java index 2cfb0d4..9f54e4c 100644 --- a/src/test/java/com/blade/jdbc/test/UpdateTest.java +++ b/src/test/java/com/blade/jdbc/test/UpdateTest.java @@ -21,6 +21,7 @@ public void test1() { public void test2() { User user = new User(); user.setAge(19); + user.setRealName("aaa"); // update t_user set age = ? where id = ? user.update(43); }