diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c30588f --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.project +.classpath +.settings +/resources/ +/.gradle/ +/bin/ +/build/ +/WebContent/WEB-INF/lib/ +/WebContent/WEB-INF/classes/ +/src/main/resources/application.properties +/tmp/ + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..cc01f6e --- /dev/null +++ b/build.gradle @@ -0,0 +1,27 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java Library project to get you started. + * For more details take a look at the Java Libraries chapter in the Gradle + * user guide available at https://docs.gradle.org/4.5.1/userguide/java_library_plugin.html + */ + +plugins { + // Apply the java-library plugin to add support for Java Library + id 'java' + id 'eclipse' + id 'application' +} + +jar.enabled = true +group = 'com.taover.repository' + +dependencies { + compile("org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final") + compile('org.springframework:spring-jdbc:4.3.9.RELEASE') + compile('mysql:mysql-connector-java') +} + +repositories { + jcenter() +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..c44b679 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..568c50b --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..dcb5c10 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at https://docs.gradle.org/4.5.1/userguide/multi_project_builds.html + */ + +rootProject.name = 'com-taover-repository' diff --git a/src/main/java/com/taover/repository/CustomJdbcTemplate.java b/src/main/java/com/taover/repository/CustomJdbcTemplate.java new file mode 100644 index 0000000..ad38da6 --- /dev/null +++ b/src/main/java/com/taover/repository/CustomJdbcTemplate.java @@ -0,0 +1,703 @@ +package com.taover.repository; + +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.persistence.Column; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.util.StringUtils; + +/** + * + * @author root + * + * @param + * @param + */ +public class CustomJdbcTemplate { + @Resource + private JdbcTemplate jdbcTemplateRead; + @Resource + private JdbcTemplate jdbcTemplateWrite; + + private Map beanToTableField; + private Map tableToBeanField; + private String tableFieldNameListGapWithComma; + private String idTableFieldName; + private String idBeanFieldName; + private String dbName; + private String tableName; + private Class tClassInfo; + private CustomJdbcTemplateRowMapper customJdbcTemplateRowMapper; + + public CustomJdbcTemplateRowMapper getCustomJdbcTemplateRowMapper(){ + return this.customJdbcTemplateRowMapper; + } + + public CustomJdbcTemplate() throws Exception{ + //获取泛型类Class + this.tClassInfo = (Class)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + + //检查实体声明 + Table annoTable = (Table) tClassInfo.getAnnotation(Table.class); + if(annoTable == null){ + throw new Exception("DAO层初始化失败,失败原因:"+tClassInfo.getName()+"实体类,没有@Table注解指定表名"); + } + this.tableName = annoTable.name(); + if(annoTable.schema() != null){ + this.dbName = annoTable.schema(); + }else if(annoTable.catalog() != null){ + this.dbName = annoTable.catalog(); + } + + //初始化数据 + beanToTableField = new HashMap(); + tableToBeanField = new HashMap(); + tableFieldNameListGapWithComma = ""; + Field[] declaredFields = tClassInfo.getDeclaredFields(); + for(int i=0; i + * 例如:HelloWorld->HELLO_WORLD + * @param name 转换前的驼峰式命名的字符串 + * @return 转换后下划线大写方式命名的字符串 + */ + public String camelToUnderline(String name) { + StringBuilder result = new StringBuilder(); + if (name != null && name.length() > 0) { + // 将第一个字符处理成大写 + result.append(name.substring(0, 1).toUpperCase()); + // 循环处理其余字符 + for (int i = 1; i < name.length(); i++) { + String s = name.substring(i, i + 1); + // 在大写字母前添加下划线 + if (Character.isUpperCase(s.charAt(0)) && Character.isLetter(s.charAt(0))) { + result.append("_"); + } + // 其他字符直接转成大写 + result.append(s.toUpperCase()); + } + } + return result.toString(); + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。
+ * 例如:HELLO_WORLD->HelloWorld + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public String underlineToCamel(String name) { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) { + // 没必要转换 + return ""; + } else if (!name.contains("_")) { + // 不含下划线,仅将首字母小写 + return name.substring(0, 1).toLowerCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String camels[] = name.split("_"); + for (String camel : camels) { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) { + continue; + } + // 处理真正的驼峰片段 + if (result.length() == 0) { + // 第一个驼峰片段,全部字母都小写 + result.append(camel.toLowerCase()); + } else { + // 其他的驼峰片段,首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + } + return result.toString(); + } + + public void appendWhereCondition(StringBuffer sql, StringBuffer pql, List list, List condition) { + if (condition == null || condition.size() == 0) return; + Object[] con = condition.get(0); + int iLen = condition.size(); + sql.append(" WHERE "); + pql.append(" WHERE "); + sql.append(con[0]); + pql.append(con[0]); + if (null != con[1] && con[1] != "" && con[1] != "useArg[0]") { + sql.append(" " + con[1] + " ?"); + pql.append(" " + con[1] + " " + con[2]); + list.add(con[2]); + } + for (int i = 1; i < iLen; i++) { + con = condition.get(i); + sql.append(" AND "); + pql.append(" AND "); + sql.append(con[0]); + pql.append(con[0]); + if (null == con[1] || "" == con[1] || con[1] == "useArg[0]") continue; + sql.append(" " + con[1] + " ?"); + pql.append(" " + con[1] + " " + con[2]); + list.add(con[2]); + } + } + + public void appendWhereConditionForCount(StringBuffer sql, List condition) { + if (condition == null || condition.size() == 0) return; + Object[] con = condition.get(0); + int iLen = condition.size(); + sql.append(" WHERE "); + sql.append(con[0]); + if (null != con[1] && con[1] != "" && con[1] != "useArg[0]") { + sql.append(" " + con[1] + " ?"); + } + for (int i = 1; i < iLen; i++) { + con = condition.get(i); + sql.append(" AND "); + sql.append(con[0]); + if (null == con[1] || "" == con[1] || con[1] == "useArg[0]") continue; + sql.append(" " + con[1] + " ?"); + } + } + + public void appendSql(StringBuffer sql, StringBuffer pql, List list, List obj) { + for (Object[] arg : obj) { + String opt = "="; + if (arg.length > 2) { + opt = (String)arg[2]; + } + if (opt.equals("=")) { + sql.append(" " + arg[0] + " = ?,"); + pql.append(" " + arg[0] + " = " + arg[1] + ","); + } else { + sql.append(" " + arg[0] + " = " + arg[0] + " + ?,"); + pql.append(" " + arg[0] + " = " + arg[0] + " + " + arg[1] + ","); + } + list.add(arg[1]); + } + } + + private String getTableSql(){ + return "".equals(this.dbName)?"`"+this.tableName+"`":("`"+this.dbName+"`.`"+this.tableName+"`"); + } + + /** + * 按主键查询 + */ + public T findEntityByID(ID id) { + return findEntityByID(id, true, false); + } + + /** + * 按主键查询 + * isLock 是否锁定, 默认不锁 + * fromWriteDB 是否从写库读写,默认从读库查询 + */ + public T findEntityByID(ID id, boolean fromWriteDB, boolean isLock) { + StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); + StringBuffer pql = new StringBuffer(sql.toString()); + sql.append(" WHERE "+idTableFieldName+" = ?"); + pql.append(" WHERE "+idTableFieldName+" = " + id); + if (isLock) { + sql.append(" FOR UPDATE"); + pql.append(" FOR UPDATE"); + } + T result = null; + try { + result = (T) (fromWriteDB ? jdbcTemplateWrite : jdbcTemplateRead).queryForObject(sql.toString(), this.customJdbcTemplateRowMapper, id); + }catch(Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return result; + } + + /** + * 根据条件List查询 + * Object[]数组长度是3 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public T findEntityByCondition(List condition) throws Exception { + List tempList = findListByCondition(condition, null, false); + if(tempList == null || tempList.size() == 0){ + return null; + } + if(tempList != null && tempList.size() == 1){ + return tempList.get(0); + }else{ + throw new Exception("数据库存在多条记录满足条件"); + } + } + + /** + * 根据条件sql查询 + * sqlCondition 为where 后面的条件。 + */ + public T findEntityBySql(String sqlCondition) throws Exception{ + List tempList = findListBySql(sqlCondition, false); + if(tempList == null || tempList.size() == 0){ + return null; + } + if(tempList != null && tempList.size() == 1){ + return tempList.get(0); + }else{ + throw new Exception("数据库存在多条记录满足条件"); + } + } + + /** + * 根据条件List查询 + * Object[]数组长度是3 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public List findListByCondition(List condition) { + return findListByCondition(condition,null, false); + } + + /** + * 根据条件List查询 + * Object[]数组长度是3 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public List findListByCondition(List condition, String sortCondition, boolean fromWriteDB) { + StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); + StringBuffer pql = new StringBuffer(sql.toString()); + List list = new ArrayList(); + this.appendWhereCondition(sql, pql, list, condition); + if(!StringUtils.isEmpty(sortCondition)){ + sql.append(" " + sortCondition + " "); + pql.append(" " + sortCondition + " "); + } + List resultList = null; + try { + resultList = (fromWriteDB ? jdbcTemplateWrite : jdbcTemplateRead).query(sql.toString(), this.customJdbcTemplateRowMapper, list.toArray()); + return resultList; + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return null; + } + + /** + * 根据条件sql查询 + * sqlCondition 为where 后面的条件。 + */ + public List findListBySql(String sqlCondition) { + return findListBySql(sqlCondition, false); + } + + /** + * 根据条件sql查询 + * sqlCondition 为where 后面的条件。 + */ + public List findListBySql(String sqlCondition, boolean fromWriteDB) { + StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE " + sqlCondition); + List resultList = null; + try { + resultList = (fromWriteDB ? jdbcTemplateWrite : jdbcTemplateRead).query(sql.toString(), this.customJdbcTemplateRowMapper); + return resultList; + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return null; + } + + /** + * 按条件分页查询 + * Object[]数组长度是3 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public Map findPageByCondition(List condition,int page, int pageSize) { + return findPageByCondition(condition, null , page, pageSize, false); + } + + /** + * 按条件分页查询 + * Object[]数组长度是3 + * Object[]第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + * boolean isUseCache, 是否用缓存,默认用。 + * boolean isAddCache, 是否添加缓存,默认添加。 + */ + public Map findPageByCondition(List condition,String sortCondition, int page, int pageSize, boolean fromWriteDB) { + StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); + StringBuffer pql = new StringBuffer(sql.toString()); + StringBuffer sqlCount = new StringBuffer("SELECT COUNT(1) rowCount FROM "+this.getTableSql()); + + List count_list = new ArrayList(); + List page_list = new ArrayList(); + this.appendWhereConditionForCount(sqlCount, condition); + this.appendWhereCondition(sql, pql, count_list, condition); + for (int i = 0; i < count_list.size(); i++) + page_list.add(count_list.get(i)); + + page_list.add((page - 1) * pageSize); + page_list.add(pageSize); + + if(!StringUtils.isEmpty(sortCondition)){ + sql.append(" " + sortCondition + " "); + pql.append(" " + sortCondition + " "); + } + + String pageSql = sql.toString() + " limit ?, ?"; + + List resultList = null; + try { + Map totalRowsMap = (fromWriteDB ? jdbcTemplateWrite : jdbcTemplateRead).queryForMap(sqlCount.toString(), count_list.toArray()) ; + + Map resultMap = new HashMap(); + resultMap.put("page", page); + resultMap.put("total", totalRowsMap.get("rowCount")); + resultList = (fromWriteDB ? jdbcTemplateWrite : jdbcTemplateRead).query(pageSql.toString(), this.customJdbcTemplateRowMapper, page_list.toArray()); + resultMap.put("rows", resultList); + return resultMap; + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return null; + } + + /** + * 按sql分页查询, sqlCondition为where 后条件sql + */ + public Map findPageBySql(String sqlCondition, int page, int pageSize) { + return findPageBySql(sqlCondition, page, pageSize, false); + } + + /** + * 按sql分页查询, sqlCondition为where 后条件sql + */ + public Map findPageBySql(String sqlCondition, int page, int pageSize,boolean fromWriteDB) { + StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE " + sqlCondition ); + StringBuffer sqlCount = new StringBuffer("SELECT count(1) rowCount FROM "+this.getTableSql()+" WHERE " + sqlCondition); + String pageSql = sql.toString() + " limit ?, ?"; + String pagePql = sql.toString() + " limit " + ((page -1) * pageSize) + ", " + (page * pageSize); + List page_list = new ArrayList(); + page_list.add((page - 1) * pageSize); + page_list.add(page * pageSize); + + + List resultList = null; + try { + + Map totalRowsMap = (fromWriteDB ? jdbcTemplateWrite : jdbcTemplateRead).queryForMap(sqlCount.toString()); + + Map resultMap = new HashMap(); + resultMap.put("page", page); + resultMap.put("total", totalRowsMap.get("rowCount")); + resultList = (fromWriteDB ? jdbcTemplateWrite : jdbcTemplateRead).query(pageSql.toString(), this.customJdbcTemplateRowMapper, page_list.toArray()); + resultMap.put("rows", resultList); + return resultMap; + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return null; + } + + /** + * 添加 + */ + public BigInteger addEntityForAutoincrementId(T entity) { + StringBuffer sqlForLog = new StringBuffer("INSERT INTO "+this.getTableSql()+"("); + StringBuffer sqlValueForLog = new StringBuffer(") VALUES ("); + StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"("); + StringBuffer sqlColumnPart = new StringBuffer(") VALUES ("); + List paramList = new ArrayList(); + + Iterator beanFieldIter = this.beanToTableField.keySet().iterator(); + while(beanFieldIter.hasNext()){ + String beanFieldName = beanFieldIter.next(); + String tableFieldName = this.beanToTableField.get(beanFieldName); + Field beanField; + Object beanFieldValue = null; + try { + beanField = this.tClassInfo.getDeclaredField(beanFieldName); + beanField.setAccessible(true); + beanFieldValue = beanField.get(entity); + } catch (Exception e) { + e.printStackTrace(); + } + + if(tableFieldName == null || beanFieldName == null || beanFieldValue == null){ + continue; + } + + sqlForLog.append("`"+tableFieldName+"`,"); + sqlValueForLog.append(beanFieldValue.toString()+","); + sqlInsertPart.append("`"+tableFieldName+"`,"); + sqlColumnPart.append(" ?,"); + paramList.add(beanFieldValue); + } + //打印日志内容 + sqlForLog.substring(0, sqlForLog.length()-1); + sqlForLog.append(") VALUES ("); + sqlForLog.append(sqlValueForLog+")"); + //UtilsLog.infoForMessage(sqlForLog.toString(), this.getClass()); + + //执行SQL + String exeSql = sqlInsertPart.substring(0, sqlInsertPart.length()-1)+sqlColumnPart.substring(0, sqlColumnPart.length()-1)+")"; + try { + jdbcTemplateWrite.update(exeSql, paramList.toArray()); + Map lastInsertIdMap = jdbcTemplateWrite.queryForMap("SELECT LAST_INSERT_ID() lastInsertId"); + return (BigInteger)lastInsertIdMap.get("lastInsertId"); + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return null; + } + + /** + * 批量添加 + */ + public List addEntityList(List entityList) { + List result = new ArrayList(); + for (T entity : entityList) { + result.add(addEntityForAutoincrementId(entity)); + } + return result; + } + + /** + * 按ID删除 + */ + public int deleteEntityByID(ID id) { + StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+" WHERE"); + StringBuffer pql = new StringBuffer(sql.toString()); + pql.append(" "+this.idTableFieldName+" = " + id); + sql.append(" "+this.idTableFieldName+" = ?"); + //UtilsLog.infoForMessage(pql.toString(), this.getClass()); + return jdbcTemplateWrite.update(sql.toString(), id); + } + /** + * 删除按List条件 + * Object[]数组长度是3 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public int deleteEntityByCondition(List condition) throws Exception{ + if (null == condition || condition.size() == 0) { + throw new Exception("没有传入条件,请至少传入一个筛选条件"); + } + + List list = new ArrayList(); + StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+""); + StringBuffer pql = new StringBuffer(sql.toString()); + this.appendWhereCondition(sql, pql, list, condition); + try { + return jdbcTemplateWrite.update( sql.toString(), list.toArray()); + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return 0; + } + + /** + * 删除按condition条件 + * 建议使用deleteTByCondition(List condition), 如果removeTByCondition(List condition)满足不了where条件可以使用此方法。 + * condition为where后面的条件,condition不能为空。 + */ + public int deleteEntityBySql(String sqlCondition) throws Exception{ + if("".equals(sqlCondition)) { + throw new Exception("没有传入条件,请至少传入一个筛选条件"); + } + StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+" WHERE "); + try { + return jdbcTemplateWrite.update( sql.toString() + sqlCondition); + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return 0; + } + + /** + * 根据list对象逐个删除。 + */ + public List deleteEntityList(List entityList) { + List result = new ArrayList(); + for (T entity : entityList) { + Field beanField; + Object beanFieldValue = Integer.valueOf(0); + try { + beanField = this.tClassInfo.getDeclaredField(this.idBeanFieldName); + beanField.setAccessible(true); + beanFieldValue = beanField.get(entity); + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + result.add(deleteEntityByID((ID)beanFieldValue)); + } + return result; + } + + /** + * 根据ID修改指定的值 + */ + public int updateEntityById(List changeList, ID id) throws Exception{ + if(null == id){ + throw new Exception("请求条件异常,没有传入主键ID!"); + } + + StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET"); + StringBuffer pql = new StringBuffer(sql.toString()); + List list = new ArrayList(); + for (int i = 0, iLen = changeList.size(); i < iLen; i++) { + String name = (String) changeList.get(i)[0]; + Object value = changeList.get(i)[1]; + String variationOpt = "="; + if (changeList.get(i).length > 2) + variationOpt = (String)changeList.get(i)[2]; + if (variationOpt.equals("=")) { + sql.append(" " + name + " = ?,"); + list.add(value); + if (value == null) { + pql.append(" " + name + "=null,"); + } else { + pql.append(" " + name + "=\"" + value.toString() + "\","); + } + } else { + sql.append(" " + name + " = " + name + " + ?,"); + list.add(value); + pql.append(" " + name + " = " + name + " + " + value.toString() + ","); + } + } + + //记录SQL + String pwhere = " WHERE "+this.idTableFieldName+"=\"" + id + "\""; + //UtilsLog.infoForMessage(pql.toString()+pwhere, this.getClass()); + + try { + String where = " WHERE "+this.idTableFieldName+"=?"; + String updateSql = sql.substring(0, sql.length()-1)+where; + list.add(id); + return jdbcTemplateWrite.update(updateSql, list.toArray()); + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return 0; + } + + /** + * List updateObj 要修改成的值,数组长度为2,第一个值为列名,第二个值是要改成的值。 + * List condition 修改的条件, 数组长度是3, 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public int updateEntityByCondition(List updateObj, List condition) throws Exception{ + if (null == updateObj || updateObj.size() == 0) { + throw new Exception("请求条件异常,请求条件List updateObj不能为空!"); + } + if (null == condition || condition.size() == 0) { + throw new Exception("请求条件异常,请求条件List condition不能为空!"); + } + + StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET"); + StringBuffer pql = new StringBuffer(sql.toString()); + List list = new ArrayList(); + this.appendSql(sql, pql, list, updateObj); + + StringBuffer where = new StringBuffer(""); + StringBuffer pwhere = new StringBuffer(""); + this.appendWhereCondition(where, pwhere, list, condition); + + //UtilsLog.infoForMessage(pql.toString()+pwhere.toString(), this.getClass()); + + String updateSql = sql.substring(0, sql.length()-1)+where.toString(); + try { + return jdbcTemplateWrite.update(updateSql, list.toArray()); + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return 0; + } + + /** + * List updateObj 要修改成的值,数组长度为2,第一个值为列名,第二个值是要改成的值。 + * String sqlCondition 修改的条件。 + */ + public int updateEntityBySql(List updateObj, String sqlCondition) throws Exception{ + if (null == updateObj || updateObj.size() == 0) { + throw new Exception("请求条件异常,请求条件List updateObj不能为空!"); + } + if ("".equals(sqlCondition)) { + throw new Exception("请求条件异常,请求条件sqlCondition不能为空!"); + } + + StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET"); + StringBuffer pql = new StringBuffer(sql.toString()); + List list = new ArrayList(); + this.appendSql(sql, pql, list, updateObj); + + try { + String updateSql = sql.toString().substring(0, sql.length()-1) + " WHERE "+sqlCondition; + return jdbcTemplateWrite.update(updateSql, list.toArray()); + } catch (Exception e) { + UtilsLog.errorForException(e, this.getClass()); + } + return 0; + } + + public Map getPageData(String coreSql, String orderByPartSql, Integer page, Integer pageSize){ + //构造查询语句 + String querySql = coreSql+orderByPartSql+UtilsSql.getLimitCondition(page, pageSize); + + //构造统计计数语句 + String countSql = "select count(*) rows from ("+coreSql+" ) t "; + + //执行查询 + List> queryData = new ArrayList>(); + Map countData = new HashMap(); + try{ + queryData = this.jdbcTemplateRead.queryForList(querySql); + countData = this.jdbcTemplateRead.queryForMap(countSql); + }catch(Exception e){ + countData.put("rows", "0"); + + UtilsLog.errorForException(e, this.getClass()); + } + + return UtilsSql.createPage(page, Integer.valueOf(countData.get("rows").toString()), queryData); + } +} diff --git a/src/main/java/com/taover/repository/CustomJdbcTemplateRowMapper.java b/src/main/java/com/taover/repository/CustomJdbcTemplateRowMapper.java new file mode 100644 index 0000000..a0875ff --- /dev/null +++ b/src/main/java/com/taover/repository/CustomJdbcTemplateRowMapper.java @@ -0,0 +1,47 @@ +package com.taover.repository; + +import java.lang.reflect.Field; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; + +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.rowset.ResultSetWrappingSqlRowSetMetaData; + +public class CustomJdbcTemplateRowMapper implements RowMapper{ + private Class classInfo; + private Map tableToBeanMap; + + public CustomJdbcTemplateRowMapper(Class classInfo, Map tableToBeanMap) { + this.classInfo = classInfo; + this.tableToBeanMap = tableToBeanMap; + } + + @Override + public Object mapRow(ResultSet rs, int index) throws SQLException { + Object targetObj; + try { + targetObj = this.classInfo.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + ResultSetWrappingSqlRowSetMetaData wapping = new ResultSetWrappingSqlRowSetMetaData(rs.getMetaData()); + int columnCount = wapping.getColumnCount(); + for (int i = 1; i<=columnCount; i++) { + String tableFieldName = wapping.getColumnLabel(i); + String beanFieldName = this.tableToBeanMap.get(tableFieldName); + Object value = rs.getObject(i); + try { + if(null != value && beanFieldName != null){ + Field beanField = this.classInfo.getDeclaredField(beanFieldName); + beanField.setAccessible(true); + beanField.set(targetObj, value); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + return targetObj; + } +} diff --git a/src/main/java/com/taover/repository/UtilsLog.java b/src/main/java/com/taover/repository/UtilsLog.java new file mode 100644 index 0000000..d754aea --- /dev/null +++ b/src/main/java/com/taover/repository/UtilsLog.java @@ -0,0 +1,74 @@ +package com.taover.repository; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +public class UtilsLog { + private static Map logByClassName = new HashMap(); + + /** + * 输出日志文本 + * @param message + * @param infoClass + */ + public static void infoForMessage(String message, Class infoClass){ + String className = infoClass.getName(); + Log log = logByClassName.get(infoClass.getName()); + if(log == null){ + log = LogFactory.getLog(infoClass); + if(log == null){ + return; + } + logByClassName.put(className, log); + } + log.info(message); + } + + /** + * 输出日志Exception内容 + * @param e + * @param infoClass + */ + public static String infoForException(Exception e, Class infoClass){ + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + UtilsLog.infoForMessage(sw.toString(), infoClass); + return sw.toString(); + } + + /** + * 输出文本内容 + * @param message + * @param infoClass + */ + public static void errorForMessage(String message, Class infoClass){ + String className = infoClass.getName(); + Log log = logByClassName.get(infoClass.getName()); + if(log == null){ + log = LogFactory.getLog(infoClass); + if(log == null){ + return; + } + logByClassName.put(className, log); + } + log.error(message); + } + + /** + * 输出日志Exception信息 + * @param e + * @param infoClass + */ + public static String errorForException(Exception e, Class infoClass){ + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + UtilsLog.errorForMessage(sw.toString(), infoClass); + return sw.toString(); + } +} diff --git a/src/main/java/com/taover/repository/UtilsSql.java b/src/main/java/com/taover/repository/UtilsSql.java new file mode 100644 index 0000000..7accb8c --- /dev/null +++ b/src/main/java/com/taover/repository/UtilsSql.java @@ -0,0 +1,86 @@ +package com.taover.repository; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.util.StringUtils; + +public class UtilsSql { + + /** + * 获取排序字符串 + * @param sort + * @param order + * @param columnPreffix + * @return + */ + public static String getSortCondition(String sort, String order, String columnPreffix){ + String underScoreSort = UtilsString.underscoreName(sort).toLowerCase(); + if(StringUtils.isEmpty(columnPreffix)){ + columnPreffix = ""; + } + String sortCondition = " "; + if(!StringUtils.isEmpty(underScoreSort)){ + sortCondition = " order by "; + String[] sortArr = underScoreSort.split(","); + if(StringUtils.isEmpty(order)){ + sortCondition += columnPreffix+sortArr[0]+" DESC "; + for(int i=1; i createPage(int page, int rows, Object data){ + Map pageData = new HashMap(); + pageData.put("page", page); + pageData.put("rows", rows); + pageData.put("data", data); + return pageData; + } +} diff --git a/src/main/java/com/taover/repository/UtilsString.java b/src/main/java/com/taover/repository/UtilsString.java new file mode 100644 index 0000000..ebc3dc7 --- /dev/null +++ b/src/main/java/com/taover/repository/UtilsString.java @@ -0,0 +1,237 @@ +package com.taover.repository; + +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class UtilsString { + /** + * 格式化日期区间字符串 + * @param source + * @param splitStr + * @param dateFormat + * @return + * @throws Exception + */ + public static Date[] getDateFromString(String source, String splitStr, String dateFormat) throws Exception{ + Date[] resultObj = new Date[2]; + Date createdAtStart = null; + Date createdAtEnd = null; + if(source != null && !"".equals(source)){ + String[] createdAtArr = source.split(splitStr); + SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); + if(createdAtArr.length > 0){ + createdAtStart = sdf.parse(createdAtArr[0]); + } + if(createdAtArr.length > 1){ + createdAtEnd = sdf.parse(createdAtArr[1]); + } + } + resultObj[0] = createdAtStart; + resultObj[1] = createdAtEnd; + return resultObj; + } + + /** + * 获取URL path部分 + * @param url + * @return + */ + public static String getUrlPath(String url){ + if(url == null){ + return null; + } + if(url.startsWith("http")){ + try{ + URL dataUrl = new URL(url); + return dataUrl.getPath(); + }catch(Exception e){ + e.printStackTrace(); + } + } + return url; + } + + /** + * 在compares字符数组查找pattern字符串,找到则返回字串在数组中的索引,未找到返回-1 + * @param pattern + * @param compares + * @return + */ + public static int getStringIndex(String pattern, String compares[]){ + //参数检验 + if(pattern==null || compares==null){ + return -1; + } + + //循环遍历compares + for(int i=0; iLong.MAX_VALUE || value0; --i){ + long baseDiv = (long) Math.pow(10, i-1); + long baseRand = (long) Math.pow(10, i); + long currentDigit = value % baseRand / baseDiv; + if(currentDigit == 0){ + result = result + preffixChar; + }else{ + result = result + currentDigit; + } + } + return result; + } + + /** + * 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。
+ * 例如:HelloWorld->HELLO_WORLD + * @param name 转换前的驼峰式命名的字符串 + * @return 转换后下划线大写方式命名的字符串 + */ + public static String underscoreName(String name) { + StringBuilder result = new StringBuilder(); + if (name != null && name.length() > 0) { + // 将第一个字符处理成大写 + result.append(name.substring(0, 1).toUpperCase()); + // 循环处理其余字符 + for (int i = 1; i < name.length(); i++) { + String s = name.substring(i, i + 1); + // 在大写字母前添加下划线 + if (Character.isUpperCase(s.charAt(0)) && Character.isLetter(s.charAt(0))) { + result.append("_"); + } + // 其他字符直接转成大写 + result.append(s.toUpperCase()); + } + } + return result.toString(); + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。
+ * 例如:HELLO_WORLD->HelloWorld + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String camelName(String name) { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) { + // 没必要转换 + return ""; + } else if (!name.contains("_")) { + // 不含下划线,仅将首字母小写 + return name.substring(0, 1).toLowerCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String camels[] = name.split("_"); + for (String camel : camels) { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) { + continue; + } + // 处理真正的驼峰片段 + if (result.length() == 0) { + // 第一个驼峰片段,全部字母都小写 + result.append(camel.toLowerCase()); + } else { + // 其他的驼峰片段,首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + } + return result.toString(); + } + + public static String getRandomStr(int digitNum){ + int numStartZero = 48; + int charStartUpperA = 65; + int charStartLowerA = 97; + int numSelectCount = 10; + int charSelectCount = 26; + int numCount = numSelectCount+2*charSelectCount; + String randomResult = ""; + for(int i=0; i