@@ -0,0 +1,10 @@ | |||
**/target/ | |||
**/resources/code/ | |||
/.idea/ | |||
*.iml | |||
/logs | |||
.classpath | |||
.project | |||
.factorypath | |||
**/.settings/ | |||
.vscode/ |
@@ -0,0 +1,78 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<parent> | |||
<artifactId>codeGenerate</artifactId> | |||
<groupId>com.qmrz</groupId> | |||
<version>1.0</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>code-generator</artifactId> | |||
<packaging>jar</packaging> | |||
<dependencies> | |||
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-maven-plugin --> | |||
<dependency> | |||
<groupId>org.mybatis.generator</groupId> | |||
<artifactId>mybatis-generator-maven-plugin</artifactId> | |||
<version>1.3.7</version> | |||
</dependency> | |||
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core --> | |||
<dependency> | |||
<groupId>org.mybatis.generator</groupId> | |||
<artifactId>mybatis-generator-core</artifactId> | |||
<version>1.3.7</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.qmrz</groupId> | |||
<artifactId>common</artifactId> | |||
<version>1.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>mysql</groupId> | |||
<artifactId>mysql-connector-java</artifactId> | |||
<version>8.0.11</version> | |||
</dependency> | |||
<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker --> | |||
<dependency> | |||
<groupId>org.freemarker</groupId> | |||
<artifactId>freemarker</artifactId> | |||
<version>2.3.28</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.testng</groupId> | |||
<artifactId>testng</artifactId> | |||
<version>RELEASE</version> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<finalName>CodeGenerator</finalName> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-maven-plugin</artifactId> | |||
<configuration> | |||
<fork>true</fork> | |||
<mainClass>com.qmrz.CodeGenerator</mainClass> | |||
<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments> | |||
</configuration> | |||
<executions> | |||
<execution> | |||
<configuration> | |||
<classifier>exec</classifier> | |||
</configuration> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -0,0 +1,20 @@ | |||
package com.qmrz; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.boot.SpringApplication; | |||
import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; | |||
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration; | |||
import org.springframework.cache.annotation.EnableCaching; | |||
import org.springframework.transaction.annotation.EnableTransactionManagement; | |||
@Slf4j | |||
@SpringBootApplication(exclude={RedisAutoConfiguration.class, | |||
RedisRepositoriesAutoConfiguration.class}) | |||
@EnableTransactionManagement | |||
@EnableCaching | |||
public class CodeGenerator { | |||
public static void main(String[] args) { | |||
SpringApplication.run(CodeGenerator.class, args); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
package com.qmrz.generator; | |||
import com.qmrz.service.TableService; | |||
import com.qmrz.utils.CGHelper; | |||
import com.qmrz.utils.Fn; | |||
import com.qmrz.utils.MapUtil; | |||
import com.qmrz.utils.SpringContextUtil; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
/** | |||
* api同步代码 生成 | |||
*/ | |||
public class ApiSyncGenerator { | |||
private TableService tableService; | |||
private String dbName; | |||
public ApiSyncGenerator(String dbName) { | |||
tableService = SpringContextUtil.getBean(TableService.class); | |||
this.dbName = dbName; | |||
} | |||
public void generator() { | |||
List<Map> tableList = tableService.getTableList(dbName); | |||
List<Map> columnList = tableService.getColumnList(dbName); | |||
GeneratorUtil.setColumnShowName(columnList); | |||
Map result = columnList.stream().collect(Collectors.groupingBy(map -> map.get("table_name"), Collectors.toList())); | |||
CGHelper cgHelper = new CGHelper("api_sync.ftl", dbName); | |||
tableList.forEach(item -> { | |||
String table_name = item.get("table_name").toString(); | |||
String table_name2 = Fn.firstUpperCase(table_name); | |||
item.put("columnList", result.get(table_name)); | |||
item.put("dbname", dbName); | |||
item.put("table_name2",table_name2);//首字母大写 | |||
cgHelper.generator("api_sync", table_name2 + "Sync.java", item); | |||
}); | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
package com.qmrz.generator; | |||
import com.qmrz.service.TableService; | |||
import com.qmrz.utils.CGHelper; | |||
import com.qmrz.utils.Fn; | |||
import com.qmrz.utils.SpringContextUtil; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
/** | |||
* Controller生成 | |||
*/ | |||
public class ControllerGenerator { | |||
private TableService tableService; | |||
private String dbName; | |||
public ControllerGenerator(String dbName) { | |||
tableService = SpringContextUtil.getBean(TableService.class); | |||
this.dbName = dbName; | |||
} | |||
public void generator() { | |||
List<Map> tableList = tableService.getTableList(dbName); | |||
List<Map> columnList = tableService.getColumnList(dbName); | |||
GeneratorUtil.setColumnShowName(columnList); | |||
Map result = columnList.stream().collect(Collectors.groupingBy(map -> map.get("table_name"), Collectors.toList())); | |||
CGHelper cgHelper = new CGHelper("controller.ftl", dbName); | |||
tableList.forEach(item -> { | |||
String table_name = item.get("table_name").toString(); | |||
String table_name2 = Fn.firstUpperCase(table_name); | |||
item.put("columnList", result.get(table_name)); | |||
item.put("dbname", dbName); | |||
item.put("table_name2", table_name2);//首字母大写 | |||
cgHelper.generator("controller", table_name2 + "Controller.java", item); | |||
}); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
package com.qmrz.generator; | |||
import com.qmrz.service.TableService; | |||
import com.qmrz.utils.CGHelper; | |||
import com.qmrz.utils.MapUtil; | |||
import com.qmrz.utils.SpringContextUtil; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
/** | |||
* 数据库字典生成 | |||
*/ | |||
public class DBReadmeGenerator { | |||
private TableService tableService; | |||
private String dbName; | |||
public DBReadmeGenerator(String dbName) { | |||
tableService = SpringContextUtil.getBean(TableService.class); | |||
this.dbName = dbName; | |||
} | |||
public void generator() { | |||
List<Map> tableList = tableService.getTableList(dbName); | |||
List<Map> columnList = tableService.getColumnList(dbName); | |||
Map result = columnList.stream().collect(Collectors.groupingBy(map -> map.get("table_name"), Collectors.toList())); | |||
CGHelper cgHelperTable = new CGHelper("db_tables_readme.md", dbName); | |||
cgHelperTable.generator("", "db_tables.md", MapUtil.newMap() | |||
.put("dbname", dbName) | |||
.put("tableList", tableList) | |||
.getMap() | |||
); | |||
CGHelper cgHelper = new CGHelper("db_readme.md", dbName); | |||
tableList.forEach(item -> { | |||
String table_name = item.get("table_name").toString(); | |||
item.put("columnList", result.get(table_name)); | |||
item.put("dbname", dbName); | |||
cgHelper.generator("readme", "db_" + table_name + ".md", item); | |||
}); | |||
} | |||
} |
@@ -0,0 +1,29 @@ | |||
package com.qmrz.generator; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* 生成基础工具 | |||
* @Author: suger | |||
*/ | |||
public class GeneratorUtil { | |||
/** | |||
* 增加显示名 | |||
* @param columnList | |||
*/ | |||
public static void setColumnShowName(List<Map> columnList){ | |||
for (Map item : columnList) { | |||
String column_name_show_name = String.valueOf(item.get("column_comment")); | |||
int space_indexof = column_name_show_name.indexOf(" "); | |||
if (space_indexof > 0) { | |||
column_name_show_name = column_name_show_name.substring(0, space_indexof).trim(); | |||
} | |||
if (column_name_show_name.trim().length() == 0) { | |||
column_name_show_name = String.valueOf(item.get("column_name")).trim(); | |||
} | |||
item.put("column_name_show_name", column_name_show_name);//获取注释的第一个单词,到英文空格为止 | |||
} | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.qmrz.generator; | |||
import com.qmrz.service.TableService; | |||
import com.qmrz.utils.CGHelper; | |||
import com.qmrz.utils.MapUtil; | |||
import com.qmrz.utils.SpringContextUtil; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
public class InterfaceReadmeGenerator { | |||
private TableService tableService; | |||
private String dbName; | |||
public InterfaceReadmeGenerator(String dbName) { | |||
tableService = SpringContextUtil.getBean(TableService.class); | |||
this.dbName = dbName; | |||
} | |||
public void generator() { | |||
List<Map> tableList = tableService.getTableList(dbName); | |||
List<Map> columnList = tableService.getColumnList(dbName); | |||
Map result = columnList.stream().collect(Collectors.groupingBy(map -> map.get("table_name"), Collectors.toList())); | |||
CGHelper cgHelperTable = new CGHelper("inteface_tables_readme.md", dbName); | |||
cgHelperTable.generator("", "inteface_tables_readme.md", MapUtil.newMap() | |||
.put("dbname", dbName) | |||
.put("tableList", tableList) | |||
.getMap() | |||
); | |||
CGHelper cgHelper = new CGHelper("inteface_tables_readme.md", dbName); | |||
tableList.forEach(item -> { | |||
String table_name = item.get("table_name").toString(); | |||
item.put("columnList", result.get(table_name)); | |||
item.put("dbname", dbName); | |||
item.put("filename", "inteface_" + table_name + "_readme.md"); | |||
cgHelper.generator("readme", "inteface_" + table_name + "_readme.md", item); | |||
}); | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.qmrz.generator; | |||
import com.qmrz.service.TableService; | |||
import com.qmrz.utils.CGHelper; | |||
import com.qmrz.utils.Fn; | |||
import com.qmrz.utils.MapUtil; | |||
import com.qmrz.utils.SpringContextUtil; | |||
import org.apache.commons.lang.StringUtils; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
/** | |||
* Mapper生成 | |||
*/ | |||
public class MapperGenerator { | |||
private TableService tableService; | |||
private String dbName; | |||
public MapperGenerator(String dbName) { | |||
tableService = SpringContextUtil.getBean(TableService.class); | |||
this.dbName = dbName; | |||
} | |||
public void generator() { | |||
List<Map> tableList = tableService.getTableList(dbName); | |||
List<Map> columnList = tableService.getColumnList(dbName); | |||
Map result = columnList.stream().collect(Collectors.groupingBy(map -> map.get("table_name"), Collectors.toList())); | |||
CGHelper cgHelper = new CGHelper("mapper.ftl", dbName); | |||
tableList.forEach(item -> { | |||
String table_name = item.get("table_name").toString(); | |||
String table_name2 = Fn.firstUpperCase(table_name); | |||
item.put("columnList", result.get(table_name)); | |||
item.put("dbname", dbName); | |||
item.put("table_name2",table_name2);//首字母大写 | |||
cgHelper.generator("mapper", table_name2 + "Mapper.xml", item); | |||
}); | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
package com.qmrz.generator; | |||
import com.qmrz.service.TableService; | |||
import com.qmrz.utils.CGHelper; | |||
import com.qmrz.utils.Fn; | |||
import com.qmrz.utils.SpringContextUtil; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
/** | |||
* Service生成 | |||
*/ | |||
public class ServiceGenerator { | |||
private TableService tableService; | |||
private String dbName; | |||
public ServiceGenerator(String dbName) { | |||
tableService = SpringContextUtil.getBean(TableService.class); | |||
this.dbName = dbName; | |||
} | |||
public void generator() { | |||
List<Map> tableList = tableService.getTableList(dbName); | |||
List<Map> columnList = tableService.getColumnList(dbName); | |||
Map result = columnList.stream().collect(Collectors.groupingBy(map -> map.get("table_name"), Collectors.toList())); | |||
CGHelper cgHelper = new CGHelper("service.ftl", dbName); | |||
tableList.forEach(item -> { | |||
String table_name = item.get("table_name").toString(); | |||
String table_name2 = Fn.firstUpperCase(table_name); | |||
item.put("columnList", result.get(table_name)); | |||
item.put("dbname", dbName); | |||
item.put("table_name2",table_name2);//首字母大写 | |||
cgHelper.generator("service", table_name2 + "Service.java", item); | |||
}); | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
package com.qmrz.generator; | |||
import com.qmrz.service.TableService; | |||
import com.qmrz.utils.CGHelper; | |||
import com.qmrz.utils.Fn; | |||
import com.qmrz.utils.SpringContextUtil; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
/** | |||
* ServiceImpl生成 | |||
*/ | |||
public class ServiceImplGenerator { | |||
private TableService tableService; | |||
private String dbName; | |||
public ServiceImplGenerator(String dbName) { | |||
tableService = SpringContextUtil.getBean(TableService.class); | |||
this.dbName = dbName; | |||
} | |||
public void generator() { | |||
List<Map> tableList = tableService.getTableList(dbName); | |||
List<Map> columnList = tableService.getColumnList(dbName); | |||
Map result = columnList.stream().collect(Collectors.groupingBy(map -> map.get("table_name"), Collectors.toList())); | |||
CGHelper cgHelper = new CGHelper("serviceImpl.ftl", dbName); | |||
tableList.forEach(item -> { | |||
String table_name = item.get("table_name").toString(); | |||
String table_name2 = Fn.firstUpperCase(table_name); | |||
item.put("columnList", result.get(table_name)); | |||
item.put("dbname", dbName); | |||
item.put("table_name2",table_name2);//首字母大写 | |||
cgHelper.generator("serviceImpl", table_name2 + "ServiceImpl.java", item); | |||
}); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
package com.qmrz.service.Impl; | |||
import com.qmrz.service.TableService; | |||
import com.qmrz.utils.DBHelper; | |||
import com.qmrz.utils.MapUtil; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.stereotype.Service; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* 表结构查询 | |||
*/ | |||
@Service | |||
public class TableServiceImpl implements TableService { | |||
@Autowired | |||
DBHelper dbHelper; | |||
/** | |||
* 获取指定数据库的所有表结构 | |||
* @param dbName | |||
* @return | |||
*/ | |||
@Override | |||
public List<Map> getColumnList(String dbName) { | |||
return dbHelper.selectList("TableMapper.getColumnList" | |||
, MapUtil.newMap() | |||
.put("dbname", dbName) | |||
.getMap() | |||
); | |||
} | |||
/** | |||
* 获取指定数据库的所有表 | |||
* @param dbName | |||
* @return | |||
*/ | |||
@Override | |||
public List<Map> getTableList(String dbName) { | |||
return dbHelper.selectList("TableMapper.getTableList" | |||
, MapUtil.newMap() | |||
.put("dbname", dbName) | |||
.getMap() | |||
); | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
package com.qmrz.service; | |||
import java.util.List; | |||
import java.util.Map; | |||
public interface TableService { | |||
List<Map> getColumnList(String dbName); | |||
List<Map> getTableList(String dbName); | |||
} |
@@ -0,0 +1,70 @@ | |||
package com.qmrz.utils; | |||
import freemarker.template.Configuration; | |||
import freemarker.template.Template; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.lang.StringUtils; | |||
import java.io.*; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
* 生成帮助类(CodeGenerator) | |||
*/ | |||
@Slf4j | |||
public class CGHelper { | |||
private final String templatePath = "src/main/resources/template"; | |||
private String savePath; | |||
private String ftlName; | |||
public CGHelper(String ftlName, String saveDir) { | |||
this.ftlName = ftlName; | |||
this.savePath = "src/main/resources/code/" + saveDir; | |||
} | |||
/** | |||
* 写入文件 | |||
* | |||
* @param saveFileName | |||
* @param viewModel | |||
*/ | |||
public void generator(String saveDir, String saveFileName, Map viewModel) { | |||
Configuration configuration = new Configuration(); | |||
configuration.setClassicCompatible(true); | |||
Writer out = null; | |||
try { | |||
configuration.setDirectoryForTemplateLoading(new File(templatePath)); | |||
Template template = configuration.getTemplate(ftlName); | |||
String save; | |||
if (StringUtils.isEmpty(saveDir)) { | |||
save = savePath; | |||
} else { | |||
save = savePath + "\\" + saveDir; | |||
} | |||
File fileDir = new File(save); | |||
if (!fileDir.exists() && !fileDir.isDirectory()) { | |||
fileDir.mkdirs(); | |||
} | |||
File docFile = new File(save + "\\" + saveFileName); | |||
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile))); | |||
template.process(viewModel, out); | |||
log.info("成功生成:" + saveFileName); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} finally { | |||
try { | |||
if (null != out) { | |||
out.flush(); | |||
} | |||
} catch (Exception e2) { | |||
e2.printStackTrace(); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
server: | |||
port: 109086 | |||
sys: | |||
name: 代码生成 | |||
spring: | |||
application: | |||
name: code-generator | |||
db: | |||
driver: com.mysql.cj.jdbc.Driver | |||
# url: jdbc:mysql://qmrz.cpowvfndzbei.rds.cn-northwest-1.amazonaws.com.cn:3306/qmrz?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC | |||
url: jdbc:mysql://qmrz-ga.cpowvfndzbei.rds.cn-northwest-1.amazonaws.com.cn:3306/qmrzga-dev?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC | |||
username: qmrz | |||
password: Qmrz2018 | |||
logging: | |||
level: | |||
com.ab.domain.mapper: debug | |||
@@ -0,0 +1,36 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | |||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
<mapper namespace="com.qmrz.domain.mapper.TableMapper"> | |||
<select id="getColumnList" parameterType="Map" resultType="Map"> | |||
select | |||
TABLE_NAME as table_name | |||
,COLUMN_NAME as column_name | |||
,COLUMN_COMMENT as column_comment | |||
,DATA_TYPE as data_type | |||
,COLUMN_TYPE as column_type | |||
,IS_NULLABLE as is_nullable | |||
,COLUMN_DEFAULT as column_default | |||
,COLUMN_KEY as column_key | |||
,CHARACTER_SET_NAME as character_set_name | |||
,COLLATION_NAME as collation_name | |||
from INFORMATION_SCHEMA.Columns | |||
where table_schema=#{dbname} | |||
order by ORDINAL_POSITION asc | |||
</select> | |||
<select id="getTableList" parameterType="Map" resultType="Map"> | |||
select | |||
TABLE_NAME as table_name | |||
,TABLE_COMMENT as table_comment | |||
,TABLE_COLLATION as table_collation | |||
,ENGINE as engine | |||
from information_schema.tables | |||
where table_schema=#{dbname} and table_type='BASE TABLE'; | |||
</select> | |||
</mapper> |
@@ -0,0 +1,114 @@ | |||
package com.qmrz.syncapi; | |||
import com.alibaba.fastjson.JSONArray; | |||
import com.qmrz.exception.ABException; | |||
import com.qmrz.utils.*; | |||
import lombok.extern.slf4j.Slf4j; | |||
import java.time.LocalDateTime; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* 同步 ${table_name},${table_comment} | |||
*/ | |||
@Slf4j | |||
public class ${table_name2}Sync extends BaseSync { | |||
private String syncStartDate; | |||
private String syncEndDate; | |||
public ${table_name2}Sync(String syncStartDate, String syncEndDate) { | |||
this.syncStartDate = syncStartDate; | |||
//结束日期需要加一天,api同步时不包含结束日期 | |||
this.syncEndDate = DateTimeUtil.datePlus(syncEndDate, 1); | |||
} | |||
@Override | |||
protected Map<String, String> getSyncFieldMapping() { | |||
//注意:不包含createtime,若是子表,则外键ID也不包含 | |||
Map<String, String> fieldMapping = new HashMap<>(); | |||
<#list columnList as item> | |||
<#if item.column_name != "createtime"> | |||
fieldMapping.put("${item.column_name}", "${item.column_name_show_name}"); | |||
</#if> | |||
</#list> | |||
return fieldMapping; | |||
} | |||
public JSONArray getOtherList() { | |||
throw new ABException("方法未实现"); | |||
//return this.getSubList("子记录", (rowParent, rowSub) -> { | |||
// rowSub.put("外键id", rowParent.get("id")); | |||
//}); | |||
} | |||
@Override | |||
protected String insertMapID() { | |||
return "${table_name2}Mapper.sync_batch_insert"; | |||
} | |||
@Override | |||
protected String updateMapID() { | |||
return "${table_name2}Mapper.sync_batch_update"; | |||
} | |||
@Override | |||
protected String deleteMapID() { | |||
return "${table_name2}Mapper.sync_batch_delete"; | |||
} | |||
@Override | |||
protected String getTableName() { | |||
return "${table_name}"; | |||
} | |||
@Override | |||
protected String getPrimaryFieldName() { | |||
return "id"; | |||
} | |||
@Override | |||
protected String getSyncUrl() { | |||
throw new ABException("方法未实现"); | |||
} | |||
@Override | |||
protected boolean ispage() { | |||
return true; | |||
} | |||
@Override | |||
protected void insertAddField(Map insertMap) { | |||
insertMap.put("createtime", DateTimeUtil.format(LocalDateTime.now())); | |||
} | |||
/** | |||
* 查询DB数据,用与api数据比对是否增、删、改 | |||
* @return | |||
*/ | |||
@Override | |||
protected List selectDB() { | |||
return SpringContextUtil.getBean(DBHelper.class).selectList("${table_name2}Mapper.sync_batch_select"); | |||
} | |||
/** | |||
* 若需要api数据时(如主表),返回为false,否则true | |||
* @return | |||
*/ | |||
@Override | |||
protected boolean isOrigin() { | |||
return false; | |||
} | |||
/** | |||
* 若不需要api数据时,请先填充 this.originApi | |||
* @return | |||
*/ | |||
@Override | |||
protected JSONArray originApiData() { | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
package com.qmrz.controller.a1; | |||
import com.qmrz.controller.base.BaseController; | |||
import com.qmrz.service.${table_name2}Service; | |||
import com.qmrz.utils.ExportPOIUtils; | |||
import com.qmrz.utils.RD; | |||
import com.qmrz.utils.Web; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.web.bind.annotation.RequestBody; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.web.bind.annotation.RestController; | |||
import java.io.IOException; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* ${table_name},${table_comment} | |||
* Automatic generation | |||
*/ | |||
@Slf4j | |||
@RequestMapping("/a1/${table_name}") | |||
@RestController | |||
public class ${table_name2}Controller extends BaseController { | |||
${table_name2}Service ${table_name}Service; | |||
public ${table_name2}Controller(${table_name2}Service ${table_name}Service){ | |||
super(${table_name}Service); | |||
this.${table_name}Service = ${table_name}Service; | |||
} | |||
@RequestMapping("insert") | |||
@Override | |||
public RD insert(@RequestBody Map insertData) { | |||
return RD.failure("未开启 insert 操作"); | |||
} | |||
@RequestMapping("update") | |||
@Override | |||
public RD update(@RequestBody Map<String,Object> data) { | |||
return RD.failure("未开启 update 操作"); | |||
} | |||
@RequestMapping("delete") | |||
@Override | |||
public RD delete(@RequestBody Map where) { | |||
return RD.failure("未开启 delete 操作"); | |||
} | |||
/** | |||
* 导出excel | |||
* @param map | |||
*/ | |||
@RequestMapping("export") | |||
public void export(@RequestBody Map<String, String> map) { | |||
//db字段名 | |||
String dbColumn[] = {<#list columnList as item>"${item.column_name}"<#if item_has_next>,</#if></#list>}; | |||
//excel列名 | |||
String excelColumn[] = {<#list columnList as item>"${item.column_name_show_name}"<#if item_has_next>,</#if></#list>}; | |||
List<Map> resultList = this.${table_name}Service.selectList(map); | |||
try { | |||
ExportPOIUtils.start_download(Web.getResponse(), "${table_name}", resultList, excelColumn, dbColumn); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
## ${dbname}.${table_name} | |||
### `${table_comment}` | |||
> 表信息 | |||
| 属性 | 内容 | | |||
| --- | --- | | |||
| table_collation | ${table_collation} | | |||
| engine | ${engine} | | |||
> 表结构 | |||
| 说明 | 字段名 | 字段类型 | 主键 | 允许为空 | 默认值 | 字符集 | 排序规则 | | |||
| --- | --- | --- | --- | --- | --- | --- | --- | | |||
<#list columnList as item> | |||
| ${item.column_comment} | ${item.column_name} | ${item.column_type} | ${item.column_key} | ${item.is_nullable} | ${item.column_default} | ${item.character_set_name} | ${item.collation_name} | |||
</#list> | |||
@@ -0,0 +1,10 @@ | |||
## ${dbname} 数据库 | |||
> 表格清单 | |||
| 表名 | 排序规则 | 引擎 | 说明 | | |||
| --- | --- | --- | --- | | |||
<#list tableList as item> | |||
| [${item.table_name}](readme/db_${item.table_name}.md) | ${item.table_collation} | ${item.engine} | ${item.table_comment} | | |||
</#list> | |||
@@ -0,0 +1,44 @@ | |||
**简要描述:** | |||
- ${table_comment} | |||
- [${table_comment}](readme/ ${filename}) | |||
**请求URL:** | |||
- ` /mj/${table_name}/select_page ` | |||
**请求方式:** | |||
- POST | |||
**参数:** | |||
|参数名|类型|说明| | |||
|:---- |:---|:----- |----- | |||
<#list columnList as item> | |||
| ${item.column_name} | ${item.column_type} | ${item.column_comment} | | |||
</#list> | |||
| pageIndex | int | 页数 | | |||
| pageSize | int | 条数 | | |||
**返回示例** | |||
``` | |||
{ | |||
"data": { | |||
"data": [ | |||
{ | |||
<#list columnList as item> | |||
"${item.column_name}":"test"(${item.column_comment}) | |||
</#list> | |||
} | |||
], | |||
"pageCount": 1, | |||
"pageIndex": 1, | |||
"pageSize": 10, | |||
"rowCount": 2(总数) | |||
}, | |||
"msg": "success", | |||
"status": 10200 | |||
} | |||
``` |
@@ -0,0 +1,117 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | |||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
<!-- | |||
${table_name}(${table_comment}) | |||
注意:分隔线以下 不增加业务,有新增自定义业务时加到分隔线上面 | |||
--> | |||
<mapper namespace="com.qmrz.domain.mapper.${table_name2}Mapper"> | |||
<!-- ========================= 分隔线,以下为生成的通用代码 ========================= --> | |||
<!-- 通用查询条件 --> | |||
<sql id="common_where"> | |||
<where> | |||
<#list columnList as item> | |||
<if test="${item.column_name}!=null and ${item.column_name}!=''">and a.${item.column_name} = ${"#"}{${item.column_name}}</if> | |||
</#list> | |||
<#list columnList as item> | |||
<if test="like_${item.column_name}!=null and like_${item.column_name}!=''">and a.${item.column_name} like concat('%',${"#"}{like_${item.column_name}},'%')</if> | |||
</#list> | |||
</where> | |||
</sql> | |||
<!-- 通用查询记录 --> | |||
<select id="selectList" resultType="java.util.LinkedHashMap"> | |||
select <#list columnList as item>a.${item.column_name}<#if item_has_next>,</#if></#list> | |||
from ${table_name} a | |||
<include refid="common_where" /> | |||
<if test="__limit__!=null"> | |||
<#noparse>limit #{__limit__}</#noparse> | |||
</if> | |||
</select> | |||
<!-- 通用查询记录总数 --> | |||
<select id="selectCount" resultType="Integer"> | |||
select count(*) from ${table_name} a | |||
<include refid="common_where" /> | |||
</select> | |||
<!-- 通用插入数据 --> | |||
<insert id="insert"> | |||
insert into ${table_name}( | |||
<trim suffixOverrides=","> | |||
<#list columnList as item> | |||
<if test="${item.column_name}!=null">${item.column_name},</if> | |||
</#list> | |||
</trim>) | |||
values( | |||
<trim suffixOverrides=","> | |||
<#list columnList as item> | |||
<if test="${item.column_name}!=null">${"#"}{${item.column_name}},</if> | |||
</#list> | |||
</trim> | |||
) | |||
</insert> | |||
<!-- 通用更新数据 --> | |||
<update id="update"> | |||
update ${table_name} | |||
<set> | |||
<#list columnList as item> | |||
<#if item.column_key?? && item.column_key!="PRI" || item.column_name?? && item.column_name != "id"> | |||
<if test="${item.column_name}!=null">${item.column_name} = ${"#"}{${item.column_name}},</if> | |||
</#if> | |||
</#list> | |||
</set> | |||
<where> | |||
<#list columnList as item> | |||
<if test="where_${item.column_name}!=null">and ${item.column_name} = ${"#"}{where_${item.column_name}}</if> | |||
</#list> | |||
</where> | |||
</update> | |||
<!-- 通用删除记录 --> | |||
<delete id="delete"> | |||
delete from ${table_name} a | |||
<include refid="common_where"/> | |||
</delete> | |||
<!-- ============================== 以下为api同步使用 ============================== --> | |||
<select id="sync_batch_select" resultType="Map" parameterType="Map"> | |||
select <#list columnList as item>${item.column_name}<#if item_has_next>,</#if></#list> | |||
from ${table_name} | |||
</select> | |||
<insert id="sync_batch_insert" parameterType="Map"> | |||
insert into ${table_name}(<#list columnList as item>${item.column_name}<#if item_has_next>,</#if></#list>) | |||
values | |||
<foreach collection="list" item="item" index="index" separator=","> | |||
(<#list columnList as item>${"#"}{item.${item.column_name}}<#if item_has_next>,</#if></#list>) | |||
</foreach> | |||
</insert> | |||
<update id="sync_batch_update" parameterType="List"> | |||
<foreach collection="list" item="item" index="index" separator=";"> | |||
update ${table_name} | |||
<set> | |||
<#list columnList as item> | |||
<#if item.column_key?? && item.column_key!="PRI" && item.column_name?? && item.column_name != "id" && item.column_name!="createtime"> | |||
${item.column_name}=${"#"}{item.${item.column_name}}, | |||
</#if> | |||
</#list> | |||
</set> | |||
where id=${"#"}{item.id} | |||
</foreach> | |||
</update> | |||
<delete id="sync_batch_delete" parameterType="List"> | |||
delete from ${table_name} where id in ( | |||
<foreach collection="list" item="item" index="index" separator=","> | |||
${"#"}{item} | |||
</foreach> | |||
) | |||
</delete> | |||
</mapper> |
@@ -0,0 +1,140 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | |||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
<!-- | |||
${table_name}(${table_comment}) | |||
注意:分隔线以下 不增加业务,有新增自定义业务时加到分隔线上面 | |||
--> | |||
<mapper namespace="com.qmrz.domain.mapper.${table_name2}Mapper"> | |||
<!-- ========================= 分隔线,以下为生成的通用代码 ========================= --> | |||
<!-- 通用显示代码对应名字 --> | |||
<sql id="common_gldworxzqh"> | |||
,(select name from zonepubinfo zp where 1=1 and zp.pubcode = a.gldw ) as gldwname | |||
,(select name from zoneadmin zd where 1=1 and zd.id = a.xzqh ) as xzqhname | |||
</sql> | |||
<!-- 通用查询条件 --> | |||
<sql id="common_where"> | |||
<where> | |||
<#list columnList as item> | |||
<#assign age='${item.column_name}'> | |||
<#if (age=='gldw')> | |||
<if test="gldwList!=null and gldwList!=''"> | |||
and a.gldw in ( | |||
<foreach item="item" index="index" collection="gldwList" separator="," > | |||
<#noparse> #{item}</#noparse> | |||
</foreach> | |||
) | |||
</if> | |||
<#else> | |||
<if test="${item.column_name}!=null and ${item.column_name}!=''">and a.${item.column_name} = ${"#"}{${item.column_name}}</if> | |||
</#if> | |||
</#list> | |||
<#list columnList as item> | |||
<if test="like_${item.column_name}!=null and like_${item.column_name}!=''">and a.${item.column_name} like concat('%',${"#"}{like_${item.column_name}},'%')</if> | |||
</#list> | |||
</where> | |||
</sql> | |||
<!-- 通用查询记录 --> | |||
<select id="selectList" resultType="java.util.LinkedHashMap"> | |||
select <#list columnList as item>a.${item.column_name}<#if item_has_next>,</#if></#list> | |||
<#list columnList as item> | |||
<#assign age='${item.column_name}'> | |||
<#if (age=='gldw')> | |||
<include refid="common_gldworxzqh" /> | |||
</#if> | |||
</#list> | |||
from ${table_name} a | |||
<include refid="common_where" /> | |||
<if test="__limit__!=null"> | |||
<#noparse>limit #{__limit__}</#noparse> | |||
</if> | |||
</select> | |||
<!-- 通用查询记录总数 --> | |||
<select id="selectCount" resultType="Integer"> | |||
select count(*) from ${table_name} a | |||
<include refid="common_where" /> | |||
</select> | |||
<!-- 通用插入数据 --> | |||
<insert id="insert"> | |||
insert into ${table_name}( | |||
<trim suffixOverrides=","> | |||
<#list columnList as item> | |||
<if test="${item.column_name}!=null">${item.column_name},</if> | |||
</#list> | |||
</trim>) | |||
values( | |||
<trim suffixOverrides=","> | |||
<#list columnList as item> | |||
<if test="${item.column_name}!=null">${"#"}{${item.column_name}},</if> | |||
</#list> | |||
</trim> | |||
) | |||
</insert> | |||
<!-- 通用更新数据 --> | |||
<update id="update"> | |||
update ${table_name} | |||
<set> | |||
<#list columnList as item> | |||
<#if item.column_key?? && item.column_key!="PRI" || item.column_name?? && item.column_name != "id"> | |||
<if test="${item.column_name}!=null">${item.column_name} = ${"#"}{${item.column_name}},</if> | |||
</#if> | |||
</#list> | |||
</set> | |||
<where> | |||
<#list columnList as item> | |||
<if test="where_${item.column_name}!=null">and ${item.column_name} = ${"#"}{where_${item.column_name}}</if> | |||
</#list> | |||
</where> | |||
</update> | |||
<!-- 通用删除记录 --> | |||
<delete id="delete"> | |||
delete from ${table_name} a | |||
<include refid="common_where"/> | |||
</delete> | |||
<!-- ============================== 以下为api同步使用 ============================== --> | |||
<select id="sync_batch_select" resultType="Map" parameterType="Map"> | |||
select <#list columnList as item>${item.column_name}<#if item_has_next>,</#if></#list> | |||
from ${table_name} | |||
</select> | |||
<insert id="sync_batch_insert" parameterType="Map"> | |||
insert into ${table_name}(<#list columnList as item>${item.column_name}<#if item_has_next>,</#if></#list>) | |||
values | |||
<foreach collection="list" item="item" index="index" separator=","> | |||
(<#list columnList as item>${"#"}{item.${item.column_name}}<#if item_has_next>,</#if></#list>) | |||
</foreach> | |||
</insert> | |||
<update id="sync_batch_update" parameterType="List"> | |||
<foreach collection="list" item="item" index="index" separator=";"> | |||
update ${table_name} | |||
<set> | |||
<#list columnList as item> | |||
<#if item.column_key?? && item.column_key!="PRI" && item.column_name?? && item.column_name != "id" && item.column_name!="createtime"> | |||
${item.column_name}=${"#"}{item.${item.column_name}}, | |||
</#if> | |||
</#list> | |||
</set> | |||
where id=${"#"}{item.id} | |||
</foreach> | |||
</update> | |||
<delete id="sync_batch_delete" parameterType="List"> | |||
delete from ${table_name} where id in ( | |||
<foreach collection="list" item="item" index="index" separator=","> | |||
${"#"}{item} | |||
</foreach> | |||
) | |||
</delete> | |||
</mapper> |
@@ -0,0 +1,12 @@ | |||
package com.qmrz.service; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* ${table_name},${table_comment} | |||
* Automatic generation | |||
*/ | |||
public interface ${table_name2}Service extends BaseService { | |||
} |
@@ -0,0 +1,22 @@ | |||
package com.qmrz.service.impl; | |||
import com.qmrz.service.${table_name2}Service; | |||
import com.qmrz.utils.MapUtil; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.stereotype.Service; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* ${table_name},${table_comment} | |||
* Automatic generation | |||
*/ | |||
@Slf4j | |||
@Service | |||
public class ${table_name2}ServiceImpl extends BaseServiceImpl implements ${table_name2}Service { | |||
public ${table_name2}ServiceImpl(){ | |||
super("${table_name}"); | |||
} | |||
} | |||
@@ -0,0 +1,89 @@ | |||
import com.qmrz.CodeGenerator; | |||
import com.qmrz.generator.*; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.junit.Test; | |||
import org.junit.runner.RunWith; | |||
import org.springframework.boot.test.context.SpringBootTest; | |||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | |||
@Slf4j | |||
@RunWith(SpringJUnit4ClassRunner.class) | |||
@SpringBootTest(classes = CodeGenerator.class) | |||
public class TestCodeGenerator { | |||
private String dbname="qmrzga-dev"; | |||
/** | |||
* 生成所有 | |||
*/ | |||
@Test | |||
public void generatorAll() { | |||
readme(); | |||
mapper(); | |||
service(); | |||
serviceImpl(); | |||
controller(); | |||
interface2(); | |||
} | |||
/** | |||
* readme 生成 | |||
*/ | |||
@Test | |||
public void readme() { | |||
DBReadmeGenerator generator = new DBReadmeGenerator(dbname); | |||
generator.generator(); | |||
} | |||
/** | |||
* readme 生成 | |||
*/ | |||
@Test | |||
public void interface2() { | |||
InterfaceReadmeGenerator generator = new InterfaceReadmeGenerator(dbname); | |||
generator.generator(); | |||
} | |||
/** | |||
* mapper 生成 | |||
*/ | |||
@Test | |||
public void mapper() { | |||
MapperGenerator generator = new MapperGenerator(dbname); | |||
generator.generator(); | |||
} | |||
/** | |||
* service 生成 | |||
*/ | |||
@Test | |||
public void service() { | |||
ServiceGenerator generator = new ServiceGenerator(dbname); | |||
generator.generator(); | |||
} | |||
/** | |||
* serviceImpl 生成 | |||
*/ | |||
@Test | |||
public void serviceImpl() { | |||
ServiceImplGenerator generator = new ServiceImplGenerator(dbname); | |||
generator.generator(); | |||
} | |||
/** | |||
* controller 生成 | |||
*/ | |||
@Test | |||
public void controller() { | |||
ControllerGenerator generator = new ControllerGenerator(dbname); | |||
generator.generator(); | |||
} | |||
/** | |||
* api_sync 同步 | |||
*/ | |||
@Test | |||
public void api_sync() { | |||
ApiSyncGenerator generator = new ApiSyncGenerator(dbname); | |||
generator.generator(); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<parent> | |||
<artifactId>codeGenerate</artifactId> | |||
<groupId>com.qmrz</groupId> | |||
<version>1.0</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>common</artifactId> | |||
<packaging>jar</packaging> | |||
<dependencies> | |||
<dependency> | |||
<groupId>org.apache.poi</groupId> | |||
<artifactId>poi</artifactId> | |||
<version>3.9</version> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -0,0 +1,11 @@ | |||
package com.qmrz; | |||
import com.qmrz.config.SysInfo; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
@Slf4j | |||
public class BaseAdminController { | |||
@Autowired | |||
protected SysInfo sysInfo; | |||
} |
@@ -0,0 +1,99 @@ | |||
package com.qmrz.admin; | |||
import com.qmrz.constants.ConstantValue; | |||
import com.qmrz.dto.SecurityAdminDTO; | |||
import com.qmrz.exception.ABException; | |||
import com.qmrz.utils.Session; | |||
import org.apache.shiro.SecurityUtils; | |||
import org.apache.shiro.subject.Subject; | |||
/** | |||
* 管理员登录信息获取 | |||
*/ | |||
public class AdminLogin { | |||
public static final AdminLogin instance = new AdminLogin(); | |||
/** | |||
* 获取管理员登录信息 | |||
* | |||
* @return | |||
*/ | |||
// public AdminLoginInfo getAdminInfo() { | |||
// AdminLoginInfo info = Session.getSession("admininfo"); | |||
// return info; | |||
// } | |||
public SecurityAdminDTO getAdminInfo() { | |||
Subject currentUser = SecurityUtils.getSubject(); | |||
SecurityAdminDTO info = (SecurityAdminDTO) currentUser.getPrincipal(); | |||
return info; | |||
} | |||
public Boolean isSuper() { | |||
return ConstantValue.ONE.equals(getAdminInfo().getIssuper()); | |||
} | |||
/** | |||
* 获取管理员名称 | |||
* | |||
* @return | |||
*/ | |||
// public String getAdminName() { | |||
// AdminLoginInfo info = getAdminInfo(); | |||
// if (info == null) { | |||
// return "未登录"; | |||
// } | |||
// return info.getAdminname(); | |||
// } | |||
public String getAdminName() { | |||
Subject currentUser = SecurityUtils.getSubject(); | |||
if (!currentUser.isAuthenticated()) { | |||
return "未登录"; | |||
} | |||
return ((SecurityAdminDTO) currentUser.getPrincipal()).getUsername(); | |||
} | |||
/** | |||
* 验证用户是否登录 | |||
* | |||
* @return | |||
*/ | |||
// public boolean isLogin() { | |||
// AdminLoginInfo info = getAdminInfo(); | |||
// if (info == null) { | |||
// return false; | |||
// } | |||
// return info.getAdminid() > 0; | |||
// } | |||
public boolean isLogin() { | |||
Subject currentUser = SecurityUtils.getSubject(); | |||
return currentUser.isAuthenticated(); | |||
} | |||
public static final String CustomerInfo_SessionName = "admin_customer_info"; | |||
public static CustomerInfo getCustomerInfo() { | |||
CustomerInfo info = Session.getSession(CustomerInfo_SessionName); | |||
if (info == null) { | |||
throw new ABException("客户标识不存在"); | |||
} | |||
if (info.getCustomerID() == null || info.getCustomerDir() == null) { | |||
throw new ABException("客户id 或 dir为空"); | |||
} | |||
return info; | |||
} | |||
public static Integer getCustomerID() { | |||
return getCustomerInfo().getCustomerID(); | |||
} | |||
public static void setCustomInfo(CustomerInfo customInfo){ | |||
if (customInfo.getCustomerID() == null || customInfo.getCustomerDir() == null) { | |||
throw new ABException("客户id 或 dir为空"); | |||
} | |||
Session.setSession(CustomerInfo_SessionName,customInfo); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.qmrz.admin; | |||
import lombok.Data; | |||
/** | |||
* 管理员登录信息 | |||
*/ | |||
@Data | |||
public class AdminLoginInfo { | |||
private int adminid; | |||
private String adminname; | |||
} |
@@ -0,0 +1,14 @@ | |||
package com.qmrz.admin; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
@Data | |||
@AllArgsConstructor | |||
public class CustomerInfo implements Serializable { | |||
private static final long serialVersionUID = -1959344102914768364L; | |||
private Integer customerID; | |||
private String customerDir; | |||
} |
@@ -0,0 +1,75 @@ | |||
package com.qmrz.config; | |||
import com.github.pagehelper.PageInterceptor; | |||
import com.qmrz.mybatis.MapperScannerConfigurer; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.ibatis.session.SqlSessionFactory; | |||
import org.mybatis.spring.SqlSessionFactoryBean; | |||
import org.mybatis.spring.SqlSessionTemplate; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import javax.sql.DataSource; | |||
/** | |||
* 初始配置 | |||
*/ | |||
@Slf4j | |||
@Configuration | |||
public class Config { | |||
public Config() { | |||
log.info("------------ Config"); | |||
} | |||
/** | |||
* 配置数据源 | |||
* | |||
* @param dbInfo 数据库配置信息 | |||
* @return | |||
*/ | |||
@Bean | |||
public DataSource dataSource(ConfigDBInfo dbInfo) { | |||
log.info("------------ dataSource"); | |||
log.info(dbInfo.toString()); | |||
return ConfigDBUtils.getDruid(dbInfo); | |||
} | |||
/** | |||
* 利用SqlSessionFactoryBean,绑定mapper(xml)位置 | |||
* | |||
* @param dataSource 数据源 | |||
* @return | |||
*/ | |||
@Bean("SqlSessionFactory") | |||
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource,PageInterceptor pageHelper) throws Exception { | |||
log.info("------------ SqlSessionFactoryBean"); | |||
SqlSessionFactoryBean sqlSessionFactoryBean = | |||
ConfigDBUtils.getSqlSessionFactoryBean(dataSource, "classpath*:mapper/*.xml",pageHelper); | |||
return sqlSessionFactoryBean; | |||
} | |||
@Bean("sqlSessionTemplate") | |||
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { | |||
log.info("------------ sqlSessionTemplate"); | |||
SqlSessionTemplate s = new SqlSessionTemplate(sqlSessionFactory); | |||
return s; | |||
} | |||
/** | |||
* mapper配置扫描并绑定 | |||
* | |||
* @return | |||
*/ | |||
@Bean | |||
public MapperScannerConfigurer mapperScannerConfigurer() { | |||
log.info("------------ MapperScannerConfigurer"); | |||
//SqlSessionFactory名称即是SqlSessionFactoryBean的指定bean名 | |||
return ConfigDBUtils.getMapperScannerConfigurer("SqlSessionFactory", "com.qmrz.domain.mapper"); | |||
} | |||
@Bean | |||
public PageInterceptor pageHelper() { | |||
return ConfigDBUtils.pageHelper(); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.qmrz.config; | |||
import lombok.Data; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* 数据库配置信息 | |||
*/ | |||
@Slf4j | |||
@Component | |||
@Data | |||
@ConfigurationProperties(prefix = "db") | |||
public class ConfigDBInfo { | |||
private String driver; | |||
private String url; | |||
private String username; | |||
private String password; | |||
public ConfigDBInfo() { | |||
log.info("------ ConfigDBInfo"); | |||
} | |||
} |
@@ -0,0 +1,149 @@ | |||
package com.qmrz.config; | |||
import com.alibaba.druid.filter.Filter; | |||
import com.alibaba.druid.pool.DruidDataSource; | |||
import com.alibaba.druid.wall.WallConfig; | |||
import com.alibaba.druid.wall.WallFilter; | |||
import com.github.pagehelper.PageInterceptor; | |||
import com.qmrz.mybatis.MapperScannerConfigurer; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.ibatis.plugin.Interceptor; | |||
import org.apache.ibatis.session.Configuration; | |||
import org.mybatis.spring.SqlSessionFactoryBean; | |||
import org.springframework.context.ApplicationContext; | |||
import org.springframework.context.support.FileSystemXmlApplicationContext; | |||
import javax.sql.DataSource; | |||
import java.io.IOException; | |||
import java.sql.SQLException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Properties; | |||
/** | |||
* 数据库配置工具 | |||
*/ | |||
@Slf4j | |||
public class ConfigDBUtils { | |||
/** | |||
* 生成数据源 | |||
* | |||
* @param info | |||
* @return | |||
*/ | |||
public static DataSource getDruid(ConfigDBInfo info) { | |||
log.info("Create DruidDataSource:" + info.getUrl()); | |||
DruidDataSource dds = new DruidDataSource(); | |||
dds.setUrl(info.getUrl()); | |||
dds.setUsername(info.getUsername()); | |||
dds.setPassword(info.getPassword()); | |||
dds.setDriverClassName(info.getDriver()); | |||
dds.setInitialSize(0);//初始化连接大小 | |||
dds.setMaxActive(3000);//连接池最大使用连接数量 | |||
dds.setMinIdle(0);//连接池最小空闲 | |||
dds.setMaxWait(60000);//获取连接最大等待时间 | |||
dds.setValidationQuery("select 1");//验证数据库连接有效性,要求查询语句 | |||
WallConfig wallConfig = new WallConfig(); | |||
wallConfig.setMultiStatementAllow(true); | |||
WallFilter wallFilter = new WallFilter(); | |||
wallFilter.setConfig(wallConfig); | |||
List<Filter> filters = new ArrayList<>(); | |||
filters.add(wallFilter); | |||
dds.setProxyFilters(filters); | |||
//建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 | |||
dds.setTestWhileIdle(true); | |||
//申请连接时执行validationQuery检测连接是否有效,配置true会降低性能。 | |||
dds.setTestOnBorrow(false); | |||
//归还连接时执行validationQuery检测连接是否有效,配置true会降低性能 | |||
dds.setTestOnReturn(false); | |||
//配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 | |||
dds.setTimeBetweenEvictionRunsMillis(60000); | |||
//配置一个连接在池中最小生存的时间,单位是毫秒 | |||
dds.setMinEvictableIdleTimeMillis(25200000); | |||
//对于长时间不使用的连接强制关闭 | |||
dds.setRemoveAbandoned(true); | |||
//关闭超过30分钟的空闲连接,1800秒,也就是30分钟 | |||
dds.setRemoveAbandonedTimeout(1800); | |||
//关闭abanded连接时输出错误日志 | |||
dds.setLogAbandoned(true); | |||
//设置批量更新 | |||
//监控数据库 | |||
//dds.setFilters("mergeStat"); | |||
try { | |||
dds.setFilters("stat,wall"); | |||
} catch (SQLException e) { | |||
log.info("error:" + e.getMessage()); | |||
// TODO Auto-generated catch block | |||
e.printStackTrace(); | |||
} | |||
return dds; | |||
} | |||
/** | |||
* 使用SqlSessionFactoryBean,扫描或绑定mapper(xml)位置 | |||
* | |||
* @param dataSource 数据源 | |||
* @param mapperPath mapper(xml)位置 | |||
*/ | |||
public static SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource, String mapperPath, PageInterceptor pageHelper) { | |||
SqlSessionFactoryBean s = new SqlSessionFactoryBean(); | |||
s.setDataSource(dataSource); | |||
s.setPlugins(new Interceptor[]{pageHelper}); | |||
ApplicationContext ctx = new FileSystemXmlApplicationContext(); | |||
try { | |||
Configuration c = new Configuration(); | |||
c.setCallSettersOnNulls(true); | |||
s.setConfiguration(c); | |||
s.setMapperLocations(ctx.getResources(mapperPath)); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
return s; | |||
} | |||
public static PageInterceptor pageHelper() { | |||
PageInterceptor pageHelper = new PageInterceptor(); | |||
Properties p = new Properties(); | |||
p.setProperty("offsetAsPageNum", "true"); | |||
p.setProperty("rowBoundsWithCount", "true"); | |||
p.setProperty("reasonable", "true"); | |||
// p.setProperty("dialect", "mysql"); | |||
pageHelper.setProperties(p); | |||
return pageHelper; | |||
} | |||
/** | |||
* 使用MapperScannerConfigurer,扫描或绑定 mapper接口位置,并与xml文件映射生产相应实例 | |||
* | |||
* @param sqlSessionFactoryBean | |||
* @param packageName | |||
*/ | |||
public static MapperScannerConfigurer getMapperScannerConfigurer(String sqlSessionFactoryBean, String packageName) { | |||
MapperScannerConfigurer m = new MapperScannerConfigurer(); | |||
//包名:指定mapper接口所在包位置 | |||
m.setBasePackage(packageName); | |||
//SqlSessionFactoryBea的名称,用与mapper的接口和xml的映射 | |||
m.setSqlSessionFactoryBeanName(sqlSessionFactoryBean); | |||
return m; | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.qmrz.config; | |||
import lombok.Data; | |||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* 数据库配置信息 | |||
*/ | |||
@Component | |||
@Data | |||
@ConfigurationProperties(prefix = "uploadfile") | |||
public class ConfigUploadFileInfo { | |||
private Long size;//byte | |||
private String path; | |||
private int picMaxWidth;//px | |||
private int picMaxHeight;//px | |||
} |
@@ -0,0 +1,15 @@ | |||
package com.qmrz.config; | |||
//@Configuration | |||
//@EnableWebSecurity | |||
public class SecurityConfig { | |||
// @Override | |||
// protected void configure(HttpSecurity http) throws Exception { | |||
// http.csrf().disable(); | |||
// http.authorizeRequests().antMatchers("/").permitAll() | |||
// .and() | |||
// .headers().frameOptions().disable(); | |||
// | |||
// | |||
// } | |||
} |
@@ -0,0 +1,79 @@ | |||
package com.qmrz.config; | |||
import lombok.Data; | |||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||
import org.springframework.stereotype.Component; | |||
@Component | |||
@Data | |||
@ConfigurationProperties(prefix = "sys") | |||
public class SysInfo { | |||
/** 站点名称 */ | |||
private String name; | |||
/** | |||
* token密钥 | |||
*/ | |||
private String policeSecret; | |||
/** | |||
* 过期毫秒数 | |||
*/ | |||
private Long policeExpire; | |||
/** | |||
* wxapp表id为wxappid的做为系统公众号 | |||
*/ | |||
private Integer wxappid; | |||
/** | |||
* 微信公众号域名 | |||
*/ | |||
private String wxdomain; | |||
/** | |||
* 阿里短信应用id | |||
*/ | |||
private Integer alismsid; | |||
/** | |||
* 微信支付回调地址 | |||
*/ | |||
private String paynotifyurl; | |||
/** | |||
* 订单生成的机器 IP | |||
*/ | |||
private String payip; | |||
/** | |||
* shiro session超时时间1天 | |||
*/ | |||
private Integer globalSessionTimeout; | |||
/** | |||
* shiro 缓存前缀 | |||
*/ | |||
private String shiroCachePrefix; | |||
/** | |||
* 是否开启api 数据同步 | |||
*/ | |||
private Boolean openSyncApi; | |||
/** | |||
* 是否开启 自动分派 | |||
*/ | |||
private Boolean openBatchAssign; | |||
/** | |||
* 数据库名 | |||
*/ | |||
private String dbname; | |||
/** | |||
* 数据同步地址 | |||
*/ | |||
private String syncapiurl; | |||
} |
@@ -0,0 +1,6 @@ | |||
package com.qmrz.constants; | |||
public class ABMessage { | |||
public static final String test = "注意,是测试数据,接口对接中"; | |||
public static final String test2 = "注意,是测试数据,暂时都返回固定站点信息"; | |||
} |
@@ -0,0 +1,7 @@ | |||
package com.qmrz.constants; | |||
public class ConstantValue { | |||
public static final Integer ZERO = 0; | |||
public static final Integer ONE = 1; | |||
public static final Integer TWO = 2; | |||
} |
@@ -0,0 +1,33 @@ | |||
package com.qmrz.dto; | |||
import com.qmrz.utils.Fn; | |||
import java.util.HashMap; | |||
/** | |||
* 通用参数接收模型(可扩展) | |||
*/ | |||
public class PageMapDTO extends HashMap<String, Object> { | |||
/** | |||
* 页码 默认第1页 | |||
* @return | |||
*/ | |||
public int getPageIndex() { | |||
int pageIdnex = Fn.toInt(this.get("pageIndex")); | |||
if (pageIdnex <= 0) { | |||
pageIdnex = 1; | |||
} | |||
return pageIdnex; | |||
} | |||
/** | |||
* 每页记录数 默认每页20条 | |||
* @return | |||
*/ | |||
public int getPageSize(){ | |||
int pageSize = Fn.toInt(this.get("pageSize")); | |||
if (pageSize <= 0) { | |||
pageSize = 20; | |||
} | |||
return pageSize; | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
package com.qmrz.dto; | |||
import lombok.Data; | |||
@Data | |||
public class ParamCodeDTO { | |||
private String code; | |||
public ParamCodeDTO() { | |||
} | |||
public ParamCodeDTO(String code) { | |||
this.code = code; | |||
} | |||
public static ParamCodeDTO newdto(String code){ | |||
return new ParamCodeDTO(code); | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
package com.qmrz.dto; | |||
import com.qmrz.admin.AdminLogin; | |||
import com.qmrz.exception.ABException; | |||
import lombok.Data; | |||
@Data | |||
public class ParamCustomer { | |||
private Integer customerid = AdminLogin.getCustomerInfo().getCustomerID(); | |||
public ParamCustomer setCustomerid(Integer customerid){ | |||
throw new ABException("customerid不允许set,请使用_set"); | |||
} | |||
public ParamCustomer _setCustomerid(Integer customerid){ | |||
this.customerid = customerid; | |||
return this; | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
package com.qmrz.dto; | |||
import com.qmrz.admin.AdminLogin; | |||
import lombok.Data; | |||
import lombok.extern.slf4j.Slf4j; | |||
@Data | |||
@Slf4j | |||
public class ParamIDDTO { | |||
private Integer id; | |||
private Integer customerid; | |||
public ParamIDDTO setCustomerid(Integer customerid) { | |||
log.warn("customerid不允许set,请使用_set"); | |||
return this; | |||
} | |||
public ParamIDDTO _setCustomerid(Integer customerid) { | |||
this.customerid = customerid; | |||
return this; | |||
} | |||
public ParamIDDTO() { | |||
this.customerid = AdminLogin.getCustomerInfo().getCustomerID(); | |||
} | |||
public ParamIDDTO(Integer id) { | |||
this.id = id; | |||
this.customerid = AdminLogin.getCustomerInfo().getCustomerID(); | |||
} | |||
public ParamIDDTO(Integer id, Integer customerid) { | |||
this.id = id; | |||
this.customerid = customerid; | |||
} | |||
public static ParamIDDTO newdto(Integer id) { | |||
return new ParamIDDTO(id); | |||
} | |||
// @Override | |||
// public String toString() { | |||
// return id.toString(); | |||
// } | |||
} |
@@ -0,0 +1,29 @@ | |||
package com.qmrz.dto; | |||
import lombok.Data; | |||
@Data | |||
public class ParamIDPageDTO extends ParamPageDTO { | |||
private Integer id; | |||
public ParamIDPageDTO() { | |||
} | |||
public ParamIDPageDTO(Integer id) { | |||
this.id = id; | |||
} | |||
public ParamIDPageDTO(Integer id, ParamPageDTO pageDTO) { | |||
this.id = id; | |||
this.setPageIndex(pageDTO.getPageIndex()); | |||
this.setPageSize(pageDTO.getPageSize()); | |||
} | |||
public static ParamIDPageDTO newdto(Integer id) { | |||
return new ParamIDPageDTO(id); | |||
} | |||
public static ParamIDPageDTO newdto(Integer id, ParamPageDTO pageDTO) { | |||
return new ParamIDPageDTO(id, pageDTO); | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
package com.qmrz.dto; | |||
import lombok.Data; | |||
@Data | |||
public class ParamLongIDDTO { | |||
private Long id; | |||
public ParamLongIDDTO() { | |||
} | |||
public ParamLongIDDTO(Long id) { | |||
this.id = id; | |||
} | |||
public static ParamLongIDDTO newdto(Long id){ | |||
return new ParamLongIDDTO(id); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.qmrz.dto; | |||
import lombok.Data; | |||
import java.math.BigDecimal; | |||
/** | |||
* 金额 | |||
*/ | |||
@Data | |||
public class ParamMoneyDTO { | |||
private BigDecimal money; | |||
public ParamMoneyDTO() { | |||
} | |||
public ParamMoneyDTO(BigDecimal money) { | |||
this.money = money; | |||
} | |||
public static ParamMoneyDTO newdto(BigDecimal money){ | |||
return new ParamMoneyDTO(money); | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
package com.qmrz.dto; | |||
import com.qmrz.admin.AdminLogin; | |||
import lombok.Data; | |||
import lombok.extern.slf4j.Slf4j; | |||
@Data | |||
@Slf4j | |||
public class ParamNameDTO { | |||
private String name; | |||
private Integer customerid; | |||
public ParamNameDTO setCustomerid(Integer customerid){ | |||
log.warn("customerid不允许set,请使用_set"); | |||
return this; | |||
} | |||
public ParamNameDTO _setCustomerid(Integer customerid){ | |||
this.customerid = customerid; | |||
return this; | |||
} | |||
public ParamNameDTO() { | |||
this.customerid = AdminLogin.getCustomerInfo().getCustomerID(); | |||
} | |||
public ParamNameDTO(String name) { | |||
this.name = name; | |||
this.customerid = AdminLogin.getCustomerInfo().getCustomerID(); | |||
} | |||
public ParamNameDTO(String name,Integer customerid) { | |||
this.name = name; | |||
this.customerid = customerid; | |||
} | |||
public static ParamNameDTO newdto(String name) { | |||
return new ParamNameDTO(name); | |||
} | |||
} |
@@ -0,0 +1,61 @@ | |||
package com.qmrz.dto; | |||
import com.github.pagehelper.PageHelper; | |||
import com.qmrz.admin.AdminLogin; | |||
import lombok.Data; | |||
import lombok.extern.slf4j.Slf4j; | |||
/** | |||
* 接收参数基础对象:含分页等属性 | |||
*/ | |||
@Data | |||
@Slf4j | |||
public class ParamPageDTO { | |||
/** | |||
* 默认第1页 | |||
*/ | |||
private int pageIndex = 1; | |||
/** | |||
* 默认20条每页 | |||
*/ | |||
private int pageSize = 20; | |||
// private Integer customerid; | |||
public ParamPageDTO() { | |||
// this.customerid = AdminLogin.getCustomerInfo().getCustomerID(); | |||
} | |||
public ParamPageDTO(Integer customerid) { | |||
// this.customerid = customerid; | |||
} | |||
public ParamPageDTO(Integer customerid, Integer pageIndex, Integer pageSize) { | |||
// this.customerid = customerid; | |||
if (pageIndex <= 0) { | |||
pageIndex = 1; | |||
} | |||
this.pageIndex = pageIndex; | |||
if (pageSize <= 0) { | |||
pageSize = 20; | |||
} | |||
this.pageSize = pageSize; | |||
} | |||
public ParamPageDTO setCustomerid(Integer customerid) { | |||
log.warn("customerid不允许set,请使用_set"); | |||
return this; | |||
} | |||
public ParamPageDTO _setCustomerid(Integer customerid) { | |||
// this.customerid = customerid; | |||
return this; | |||
} | |||
/** | |||
* 使用分页mapper时,请调用此方法 | |||
*/ | |||
public void startPage() { | |||
PageHelper.startPage(pageIndex, pageSize); | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
package com.qmrz.dto; | |||
import lombok.Data; | |||
@Data | |||
public class ParamTypeDTO { | |||
private Integer type; | |||
public ParamTypeDTO() { | |||
} | |||
public ParamTypeDTO(Integer type) { | |||
this.type = type; | |||
} | |||
public static ParamTypeDTO newdto(Integer type){ | |||
return new ParamTypeDTO(type); | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
package com.qmrz.dto; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
@Data | |||
public class SecurityAdminDTO implements Serializable { | |||
private static final long serialVersionUID = 1922126787657987938L; | |||
private Integer id; | |||
private String username; | |||
private String password; | |||
/** | |||
* 角色列表 | |||
*/ | |||
private HashMap<String,List<String>> roles; | |||
/** | |||
* 权限列表 | |||
*/ | |||
private List<String> funs; | |||
/** | |||
* 是否超级管理员 | |||
*/ | |||
private Integer issuper; | |||
private Integer islock; | |||
private Long addtime; | |||
private Long updatetime; | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.qmrz.dto; | |||
import lombok.Data; | |||
@Data | |||
public class TParamIDDTO<T> { | |||
private Integer id; | |||
private T model; | |||
public TParamIDDTO() { | |||
} | |||
public TParamIDDTO(Integer id) { | |||
this.id = id; | |||
} | |||
public static TParamIDDTO newdto(Integer id){ | |||
return new TParamIDDTO(id); | |||
} | |||
// @Override | |||
// public String toString() { | |||
// return id.toString(); | |||
// } | |||
} |
@@ -0,0 +1,53 @@ | |||
package com.qmrz.exception; | |||
import com.qmrz.utils.RDCode; | |||
import lombok.extern.slf4j.Slf4j; | |||
@Slf4j | |||
public class ABException extends RuntimeException { | |||
private RDCode code; | |||
public ABException() { | |||
super(RDCode.exception.getMessage()); | |||
this.code = RDCode.exception; | |||
log(); | |||
} | |||
public ABException(String msg, Throwable cause) { | |||
super(msg, cause); | |||
this.code = RDCode.exception; | |||
log(); | |||
} | |||
public ABException(RDCode code, String msg) { | |||
super(msg); | |||
this.code = code; | |||
log(); | |||
} | |||
public ABException(RDCode code, String msg, Throwable cause) { | |||
super(msg, cause); | |||
this.code = code; | |||
log(); | |||
} | |||
public ABException(String msg) { | |||
super(msg); | |||
this.code = RDCode.exception; | |||
log(); | |||
} | |||
public ABException(RDCode code) { | |||
super(code.getMessage()); | |||
this.code = code; | |||
log(); | |||
} | |||
public RDCode getCode() { | |||
return code; | |||
} | |||
private void log() { | |||
log.error(this.getClass().getName() + ":" + this.code.getState() + ":" + this.getMessage()); | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
package com.qmrz.exception; | |||
import com.qmrz.utils.RDCode; | |||
import lombok.extern.slf4j.Slf4j; | |||
/** | |||
* 失败异常 | |||
*/ | |||
@Slf4j | |||
public class FailureException extends ABException { | |||
public FailureException(String msg) { | |||
super(RDCode.failure, msg); | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
package com.qmrz.exception; | |||
import com.qmrz.utils.RD; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.http.HttpHeaders; | |||
import org.springframework.http.HttpStatus; | |||
import org.springframework.http.ResponseEntity; | |||
import org.springframework.validation.BindException; | |||
import org.springframework.validation.FieldError; | |||
import org.springframework.validation.ObjectError; | |||
import org.springframework.web.bind.MethodArgumentNotValidException; | |||
import org.springframework.web.bind.annotation.ControllerAdvice; | |||
import org.springframework.web.context.request.WebRequest; | |||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
@Slf4j | |||
@ControllerAdvice | |||
public class GlobalControllerException extends ResponseEntityExceptionHandler { | |||
private ObjectError error; | |||
@Override | |||
protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { | |||
log.info("------ GlobalControllerException -----"); | |||
//ex.printStackTrace(); | |||
//System.out.println("====== GlobalControllerException ====="); | |||
List<ObjectError> list = ex.getAllErrors(); | |||
if (list.size() > 0) { | |||
return handleExceptionInternal(ex, RD.failure(list.get(0).getDefaultMessage()), headers, status, request); | |||
} | |||
return handleExceptionInternal(ex, RD.failure(ex.getMessage()), headers, status, request); | |||
} | |||
@Override | |||
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { | |||
System.out.println("------ MethodArgumentExceptionHandler -----"); | |||
//ex.printStackTrace(); | |||
//System.out.println("====== MethodArgumentExceptionHandler ====="); | |||
List<ObjectError> list = ex.getBindingResult().getAllErrors(); | |||
if (list.size() > 0) { | |||
// return handleExceptionInternal(ex, RD.failure(list.get(0).getDefaultMessage()), headers, status, request); | |||
Map<String, String> result = new HashMap<>(); | |||
for (ObjectError error : list) { | |||
if (error instanceof FieldError) { | |||
FieldError err = (FieldError) error; | |||
result.put(err.getField(), err.getDefaultMessage()); | |||
} | |||
} | |||
if (result.size() > 0) { | |||
return handleExceptionInternal(ex, RD.failureByForm("操作失败", result), headers, HttpStatus.OK, request); | |||
} | |||
} | |||
return handleExceptionInternal(ex, RD.failure(ex.getMessage()), headers, status, request); | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
package com.qmrz.exception; | |||
import com.qmrz.utils.RD; | |||
import com.qmrz.utils.Web; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.web.servlet.HandlerExceptionResolver; | |||
import org.springframework.web.servlet.ModelAndView; | |||
import javax.servlet.http.HttpServletRequest; | |||
import javax.servlet.http.HttpServletResponse; | |||
/** | |||
* 全局 spring 异常捕获 | |||
*/ | |||
@Slf4j | |||
public class GlobalSpringException implements HandlerExceptionResolver { | |||
@Override | |||
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { | |||
log.info("GlobalSpringException:" + ex.getMessage()); | |||
if (ex instanceof org.apache.shiro.authz.UnauthorizedException) { | |||
Web.printRD(response, RD.notpermission()); | |||
return new ModelAndView(); | |||
} else if (ex instanceof ABException) { | |||
ABException ab = (ABException) ex; | |||
Web.printRD(response, RD.create(ab.getCode(), ab.getMessage(), null)); | |||
return new ModelAndView(); | |||
} else { | |||
Web.printRD(response, RD.exception(ex.getMessage()+ ex.getClass().getName())); | |||
log.error(RD.exception(ex.getMessage() + ex.getClass().getName()).toString()); | |||
ex.printStackTrace(); | |||
return new ModelAndView(); | |||
} | |||
// return null; | |||
} | |||
} |
@@ -0,0 +1,16 @@ | |||
package com.qmrz.exception; | |||
import com.qmrz.utils.RDCode; | |||
/** | |||
* 无权限异常 | |||
*/ | |||
public class NotPermissionException extends ABException { | |||
public NotPermissionException() { | |||
super(RDCode.nopermission); | |||
} | |||
public NotPermissionException(String msg) { | |||
super(RDCode.nopermission,msg); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.qmrz.exception; | |||
import com.qmrz.utils.RDCode; | |||
/** | |||
* 民警未登录或超时 | |||
*/ | |||
public class PoliceNotLoginException extends ABException { | |||
public PoliceNotLoginException() { | |||
super(RDCode.notlogin); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.qmrz.exception; | |||
import com.qmrz.utils.RDCode; | |||
/** | |||
* 用户未登录 | |||
*/ | |||
public class UserNotLoginException extends ABException { | |||
public UserNotLoginException() { | |||
super(RDCode.notlogin); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.qmrz.exception; | |||
import com.qmrz.utils.RDCode; | |||
/** | |||
* 微信用户未授权或超时 | |||
*/ | |||
public class WXUserNotAuthorizationException extends ABException { | |||
public WXUserNotAuthorizationException() { | |||
super(RDCode.notauthorization); | |||
} | |||
} |
@@ -0,0 +1,274 @@ | |||
package com.qmrz.mybatis; | |||
import com.github.pagehelper.Page; | |||
import com.github.pagehelper.PageHelper; | |||
import com.qmrz.dto.ParamPageDTO; | |||
import com.qmrz.exception.ABException; | |||
import com.qmrz.mybatis.service.BaseService; | |||
import com.qmrz.mybatis.sql.BaseWrapper; | |||
import com.qmrz.mybatis.sql.sqlnode.UpdateParam; | |||
import com.qmrz.utils.PageData; | |||
import com.qmrz.utils.SpringContextUtil; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.mybatis.spring.SqlSessionTemplate; | |||
import java.util.LinkedHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.function.Consumer; | |||
@Slf4j | |||
public class BasePO<T> implements BaseService<T> { | |||
SqlSessionTemplate sqlTemp; | |||
POUtil poUtil; | |||
private POProxy poProxy; | |||
public void _setPoProxy(POProxy poProxy) { | |||
this.poProxy = poProxy; | |||
} | |||
public POProxy _getProxy() { | |||
return poProxy; | |||
} | |||
public void _setPoUtil(POUtil poUtil) { | |||
this.poUtil = poUtil; | |||
} | |||
public BasePO() { | |||
this.sqlTemp = SpringContextUtil.getBean(SqlSessionTemplate.class); | |||
} | |||
private String getMSID(String methodName) { | |||
String claName; | |||
if (poProxy != null) { | |||
claName = poProxy.getClassPO().getName(); | |||
} else { | |||
claName = this.getClass().getName(); | |||
} | |||
return claName + "_" + methodName + "_ActiveRecord"; | |||
} | |||
private Map<String, Object> toMap(Object obj) { | |||
return toMap(obj, true); | |||
} | |||
private Map<String, Object> toMap(Object obj, boolean isContainKey) { | |||
if (obj instanceof Map) { | |||
return (Map) obj; | |||
} | |||
if (obj instanceof BasePO) { | |||
BasePO basePO = (BasePO) obj; | |||
if (basePO._getProxy() == null) { | |||
throw new ABException("请使用proxy()创建实体对象:" + this.getClass().getName()); | |||
// return new POUtil(obj.getClass()).getMapNotNull(obj); | |||
} else { | |||
Map result = basePO._getProxy().getSetList(); | |||
if (!isContainKey) { | |||
result.remove(poUtil.getPrimarykey().getFieldNameByDB()); | |||
} | |||
return result; | |||
} | |||
} else { | |||
return poUtil.getParam(obj); | |||
} | |||
// throw new ABException("非法参数"); | |||
} | |||
private BasePO createProxy() { | |||
poProxy = new POProxy(); | |||
poUtil = new POUtil(this.getClass()); | |||
BasePO po = poProxy.getProxy(this.getClass()); | |||
po._setPoProxy(poProxy); | |||
po._setPoUtil(poUtil); | |||
return po; | |||
} | |||
/** | |||
* 创建代理对象 | |||
* | |||
* @return | |||
*/ | |||
public T proxy() { | |||
return (T) this.createProxy(); | |||
} | |||
/** | |||
* 创建代理对象,并初始化填充代理对象 | |||
* | |||
* @param object 将object属性填充到代理对象(即将非代理对象使用代理对象接管) | |||
* @return | |||
*/ | |||
public T proxy(Object object) { | |||
return proxy(object, false); | |||
} | |||
/** | |||
* @param object | |||
* @param isAllowNull 指定object里属性是否允许为空 | |||
* @return | |||
*/ | |||
public T proxy(Object object, boolean isAllowNull) { | |||
BasePO po = this.createProxy(); | |||
POUtil.fillNotNull(po, object, isAllowNull); | |||
return (T) po; | |||
} | |||
/** | |||
* 创建代理对象,并初始化填充代理对象数据 | |||
* | |||
* @param object | |||
* @param only 初始指定字段(初始化数据时,只填充在onlyFieldNameList里包含的字段) | |||
* @return | |||
*/ | |||
public T proxy(Object object, String... only) { | |||
return proxy(object, false, only); | |||
} | |||
public T proxy(Object object, boolean isAllowNull, String... only) { | |||
BasePO po = this.createProxy(); | |||
//将object属性填充到代理对象(即将非代理对象使用代理对象接管) | |||
POUtil.fillNotNull(po, object, only, isAllowNull); | |||
return (T) po; | |||
} | |||
@Override | |||
public List<T> selectWrapper(Consumer<? super BaseWrapper> wrapper) { | |||
return this.sqlTemp.selectList(getMSID("selectWrapper"), wrapper); | |||
} | |||
@Override | |||
public T selectOneWrapper(Consumer<? super BaseWrapper> wrapper) { | |||
List<T> list = this.sqlTemp.selectList(getMSID("selectOneWrapper"), wrapper); | |||
if (list.size() == 0) { | |||
return null; | |||
} | |||
return list.get(0); | |||
} | |||
@Override | |||
public Integer updateWrapper(Object param, Consumer<? super BaseWrapper> wrapper) { | |||
return this.sqlTemp.update(getMSID("updateWrapper") | |||
, new UpdateParam(toMap(param), wrapper)); | |||
} | |||
public Integer update(Consumer<? super BaseWrapper> wrapper) { | |||
return this.sqlTemp.update(getMSID("updateWrapper") | |||
, new UpdateParam(toMap(this), wrapper)); | |||
} | |||
@Override | |||
public Integer deleteWrapper(Consumer<? super BaseWrapper> wrapper) { | |||
return this.sqlTemp.delete(getMSID("deleteWrapper"), wrapper); | |||
} | |||
public PageData<T> selectPage(ParamPageDTO paramPageDTO, Consumer<? super BaseWrapper> wrapper) { | |||
PageHelper.startPage(paramPageDTO.getPageIndex(), paramPageDTO.getPageSize()); | |||
Page<T> result = (Page<T>) this.sqlTemp.selectList(getMSID("selectWrapper"), wrapper); | |||
return PageData.newobj(result); | |||
} | |||
public List<T> select() { | |||
return this.select(this); | |||
} | |||
@Override | |||
public List<T> select(Object whereObject) { | |||
return this.sqlTemp.selectList(getMSID("select"), toMap(whereObject)); | |||
} | |||
public PageData<T> selectPage(ParamPageDTO paramPageDTO) { | |||
PageHelper.startPage(paramPageDTO.getPageIndex(), paramPageDTO.getPageSize()); | |||
return PageData.newobj((Page<T>) (this.select(this))); | |||
} | |||
@Override | |||
public T selectOne(Object whereObject) { | |||
return this.sqlTemp.selectOne(getMSID("selectOne"), toMap(whereObject)); | |||
} | |||
public T selectOne() { | |||
return this.selectOne(this); | |||
} | |||
@Override | |||
public Integer selectCount(Object whereObject) { | |||
List<Integer> result = this.sqlTemp.selectList(getMSID("selectCount"), toMap(whereObject)); | |||
return result.get(0); | |||
} | |||
public Integer selectCount() { | |||
return this.selectCount(this); | |||
} | |||
@Override | |||
public List<T> selectAll() { | |||
return this.sqlTemp.selectList(getMSID("selectAll"), new LinkedHashMap<>()); | |||
} | |||
@Override | |||
public T selectByPrimaryKey(Object paramPrimaryKey) { | |||
return this.selectOne(poUtil.getParamPrimaryKey(paramPrimaryKey)); | |||
} | |||
public T selectByPrimaryKey() { | |||
return this.selectByPrimaryKey(this); | |||
} | |||
@Override | |||
public int delete(Object whereObject) { | |||
return this.sqlTemp.delete(getMSID("delete"), toMap(whereObject)); | |||
} | |||
@Override | |||
public int deleteByPrimaryKey(Object paramPrimaryKey) { | |||
return this.delete(poUtil.getParamPrimaryKey(paramPrimaryKey)); | |||
} | |||
public int deleteByPrimaryKey() { | |||
return this.deleteByPrimaryKey(this); | |||
} | |||
public int delete() { | |||
return this.delete(this); | |||
} | |||
@Override | |||
public int insert(T entity) { | |||
return this.sqlTemp.insert(getMSID("insert"), entity); | |||
} | |||
public int insert() { | |||
return this.insert((T) this); | |||
} | |||
public int update(Object paramSet, Object paramWhere) { | |||
UpdateParam param = new UpdateParam(toMap(paramSet), toMap(paramWhere)); | |||
return this.update(param); | |||
} | |||
@Override | |||
public int updateByPrimaryKey(Object whereValue) { | |||
return this.update(toMap(this, false), poUtil.getParamPrimaryKeyByValue(whereValue)); | |||
//poUtil.getParamWriteNotNull(this) | |||
} | |||
@Override | |||
public int update(UpdateParam updateParam) { | |||
return this.sqlTemp.update(getMSID("update"), updateParam); | |||
} | |||
public int updateByPrimaryKey() { | |||
return this.updateByPrimaryKey(poUtil.getValueByPrimaryKey(this)); | |||
} | |||
public int updateByPrimaryKey(Object paramSet, Object whereValue) { | |||
return this.update(paramSet, poUtil.getParamPrimaryKeyByValue(whereValue)); | |||
} | |||
} |
@@ -0,0 +1,205 @@ | |||
package com.qmrz.mybatis; | |||
import com.qmrz.mybatis.sql.sqlnode.SqlNodeWrapper; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.ibatis.mapping.MappedStatement; | |||
import org.apache.ibatis.scripting.xmltags.SqlNode; | |||
@Slf4j | |||
public class BaseProviderSqlSource { | |||
public SqlNode selectWrapper(MappedStatement ms, Class<?> classPO) { | |||
MapperUtil.setResultType(ms, classPO); | |||
return new SqlNodeWrapper(classPO, "selectWrapper"); | |||
} | |||
public SqlNode selectOneWrapper(MappedStatement ms, Class<?> classPO) { | |||
MapperUtil.setResultType(ms, classPO); | |||
return new SqlNodeWrapper(classPO, "selectOneWrapper"); | |||
} | |||
public SqlNode updateWrapper(MappedStatement ms, Class<?> classPO) { | |||
return new SqlNodeWrapper(classPO, "updateWrapper"); | |||
} | |||
public SqlNode deleteWrapper(MappedStatement ms, Class<?> classPO) { | |||
return new SqlNodeWrapper(classPO, "deleteWrapper"); | |||
} | |||
/** | |||
* 该方法仅仅用来初始化ProviderSqlSource | |||
* | |||
* @param record | |||
* @return | |||
*/ | |||
public String dynamicSQL(Object record) { | |||
log.info("BaseProviderSqlSource dynamicSQL"); | |||
return "dynamicSQL"; | |||
} | |||
public SqlNode select(MappedStatement ms, Class<?> classPO) { | |||
MapperUtil.setResultType(ms, classPO); | |||
return new SqlNodeWrapper(classPO, "select"); | |||
//修改返回值类型为实体类型 | |||
// MapperUtil.setResultType(ms, classPO); | |||
// | |||
// SqlUtil sqlUtil = new SqlUtil(classPO); | |||
// | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(sqlUtil.selectAllColumns()); | |||
// sql.append(sqlUtil.fromTable()); | |||
// sql.append(sqlUtil.whereAllIfFieldXML()); | |||
// sql.append(sqlUtil.orderByDefault()); | |||
// | |||
// return sql.toString(); | |||
} | |||
/** | |||
* 查询全部结果 | |||
*/ | |||
public SqlNode selectAll(MappedStatement ms, Class<?> classPO) { | |||
MapperUtil.setResultType(ms, classPO); | |||
return new SqlNodeWrapper(classPO, "select"); | |||
//修改返回值类型为实体类型 | |||
// MapperUtil.setResultType(ms, classPO); | |||
// | |||
// SqlUtil sqlUtil = new SqlUtil(classPO); | |||
// | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(sqlUtil.selectAllColumns()); | |||
// sql.append(sqlUtil.fromTable()); | |||
// sql.append(sqlUtil.orderByDefault()); | |||
// | |||
// return sql.toString(); | |||
} | |||
public SqlNode selectOne(MappedStatement ms, Class<?> classPO) { | |||
MapperUtil.setResultType(ms, classPO); | |||
return new SqlNodeWrapper(classPO, "selectOne"); | |||
//修改返回值类型为实体类型 | |||
// MapperUtil.setResultType(ms, classPO); | |||
// SqlUtil sqlUtil = new SqlUtil(classPO); | |||
// | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(sqlUtil.selectAllColumns()); | |||
// sql.append(sqlUtil.fromTable()); | |||
// sql.append(sqlUtil.whereXML()); | |||
// sql.append(sqlUtil.limit(1)); | |||
// return sql.toString(); | |||
} | |||
/** | |||
* 根据主键字段进行查询,查询条件使用等号 | |||
*/ | |||
public SqlNode selectByPrimaryKey(MappedStatement ms, Class<?> classPO) { | |||
MapperUtil.setResultType(ms, classPO); | |||
return new SqlNodeWrapper(classPO, "select"); | |||
//修改返回值类型为实体类型 | |||
// MapperUtil.setResultType(ms, classPO); | |||
// | |||
// SqlUtil sqlUtil = new SqlUtil(classPO); | |||
// | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(sqlUtil.selectAllColumns()); | |||
// sql.append(sqlUtil.fromTable()); | |||
// sql.append(sqlUtil.whereByPrimaryKeyXML()); | |||
// | |||
// return sql.toString(); | |||
} | |||
/** | |||
* 根据实体中的属性查询总数,查询条件使用等号 | |||
*/ | |||
public SqlNode selectCount(MappedStatement ms, Class<?> classPO) { | |||
MapperUtil.setResultType2(ms, Integer.class,"_count"); | |||
return new SqlNodeWrapper(classPO, "selectCount"); | |||
//修改返回值类型为实体类型 | |||
// SqlUtil sqlUtil = new SqlUtil(classPO); | |||
// | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(sqlUtil.selectCount()); | |||
// sql.append(sqlUtil.fromTable()); | |||
// sql.append(sqlUtil.whereAllIfFieldXML()); | |||
// | |||
// return sql.toString(); | |||
} | |||
/** | |||
* 根据主键字段进行删除,方法参数必须包含完整的主键属性 | |||
*/ | |||
public SqlNode deleteByPrimaryKey(MappedStatement ms, Class<?> classPO) { | |||
return new SqlNodeWrapper(classPO, "delete"); | |||
// SqlUtil sqlUtil = new SqlUtil(classPO); | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(sqlUtil.deleteFrom()); | |||
// sql.append(sqlUtil.whereByPrimaryKeyXML()); | |||
// return sql.toString(); | |||
} | |||
/** | |||
* 根据实体属性作为条件进行删除,查询条件使用等号 | |||
*/ | |||
public SqlNode delete(MappedStatement ms, Class<?> classPO) { | |||
return new SqlNodeWrapper(classPO, "delete"); | |||
// SqlUtil sqlUtil = new SqlUtil(classPO); | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(sqlUtil.deleteFrom()); | |||
// sql.append(sqlUtil.whereAllIfFieldXML()); | |||
// return sql.toString(); | |||
} | |||
/** | |||
* 保存一个实体,null的属性不会保存,会使用数据库默认值 | |||
*/ | |||
public SqlNode insert(MappedStatement ms, Class<?> classPO) { | |||
return new SqlNodeWrapper(classPO, "insert"); | |||
// SqlUtil sqlUtil = new SqlUtil(classPO); | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(sqlUtil.insertXML()); | |||
// return sql.toString(); | |||
} | |||
// /** | |||
// * 保存一个实体,所有字段都会插入,null的属性也会保存,不会使用数据库默认值 | |||
// */ | |||
// public String insertAllProperty(MappedStatement ms){ | |||
// System.out.println("BaseProviderSqlSource select"); | |||
// return "select id,name from test where 1=#{id}"; | |||
// } | |||
/** | |||
* 根据主键更新实体全部字段,null值不会被更新 | |||
*/ | |||
public SqlNode updateByPrimaryKey(MappedStatement ms, Class<?> classPO) { | |||
return new SqlNodeWrapper(classPO, "update"); | |||
// SqlUtil sqlUtil = new SqlUtil(classPO); | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(sqlUtil.updateSetXML()); | |||
// sql.append(sqlUtil.whereByPrimaryKeyXML()); | |||
// return sql.toString(); | |||
} | |||
public SqlNode update(MappedStatement ms, Class<?> classPO) { | |||
return new SqlNodeWrapper(classPO, "update"); | |||
// SqlUtil sqlUtil = new SqlUtil(classPO); | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(sqlUtil.updateSetXML()); | |||
// sql.append(sqlUtil.whereByPrimaryKeyXML()); | |||
// return sql.toString(); | |||
} | |||
/** | |||
* 根据主键更新实体全部字段,null值也会被更新 | |||
*/ | |||
// public String updateByPrimaryKeyAllProperty(MappedStatement ms){ | |||
// System.out.println("BaseProviderSqlSource select"); | |||
// return "select id,name from test where 1=#{id}"; | |||
// } | |||
} |
@@ -0,0 +1,5 @@ | |||
package com.qmrz.mybatis; | |||
public class DBWrapper { | |||
} |
@@ -0,0 +1,4 @@ | |||
package com.qmrz.mybatis; | |||
public interface INull<T> { | |||
} |
@@ -0,0 +1,131 @@ | |||
package com.qmrz.mybatis; | |||
import com.qmrz.mybatis.sql.BaseWrapper; | |||
import org.apache.ibatis.annotations.*; | |||
import java.util.List; | |||
import java.util.function.Consumer; | |||
public interface Mapper<T> { | |||
// @Options(useGeneratedKeys = true, keyProperty = "id") | |||
@SelectProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
List<T> selectWrapper(Consumer<? super BaseWrapper> wrapper); | |||
@SelectProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
T selectOneWrapper(Consumer<? super BaseWrapper> wrapper); | |||
@UpdateProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
Integer updateWrapper(Object param, Consumer<? super BaseWrapper> wrapper); | |||
@DeleteProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
Integer deleteWrapper(Consumer<? super BaseWrapper> wrapper); | |||
/** | |||
* 根据实体中的属性值进行查询,查询条件使用等号 | |||
* | |||
* @param whereObject map或实体 | |||
* @return | |||
*/ | |||
@SelectProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
List<T> select(Object whereObject); | |||
//@SelectProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
//List<T> selectList(T entity, IWrapper wrapper); | |||
/** | |||
* 根据实体中的属性进行查询,只能有一个返回值,有多个结果取第1个 | |||
* | |||
* @param whereObject map或实体 | |||
* @return | |||
*/ | |||
@SelectProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
T selectOne(Object whereObject); | |||
/** | |||
* 根据实体中的属性查询总数,查询条件使用等号 | |||
* | |||
* @param whereObject map或实体 | |||
* @return | |||
*/ | |||
@SelectProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
Integer selectCount(Object whereObject); | |||
/** | |||
* 查询全部结果 | |||
* | |||
* @return | |||
*/ | |||
@SelectProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
List<T> selectAll(); | |||
/** | |||
* 根据主键字段进行查询,查询条件使用等号 | |||
* | |||
* @param paramPrimaryKey map或实体 | |||
* @return | |||
*/ | |||
@SelectProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
T selectByPrimaryKey(Object paramPrimaryKey); | |||
/** | |||
* 根据主键字段进行删除,方法参数必须包含完整的主键属性 | |||
* | |||
* @param paramPrimaryKey map或实体 | |||
* @return | |||
*/ | |||
@DeleteProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
int deleteByPrimaryKey(Object paramPrimaryKey); | |||
/** | |||
* 根据实体属性作为条件进行删除,查询条件使用等号 | |||
* | |||
* @param whereObject map或实体 | |||
* @return | |||
*/ | |||
@DeleteProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
int delete(Object whereObject); | |||
/** | |||
* 保存一个实体,null的属性不会保存,会使用数据库默认值 | |||
* | |||
* @param entity map或实体 | |||
* @return | |||
*/ | |||
@Options(useGeneratedKeys=true,keyProperty = "id") | |||
@InsertProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
int insert(T entity); | |||
/** | |||
* 保存一个实体,所有字段都会插入,null的属性也会保存,不会使用数据库默认值 | |||
* | |||
* @param entity | |||
* @return | |||
*/ | |||
// @InsertProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
// int insertAllProperty(T entity); | |||
/** | |||
* 根据主键更新实体全部字段,null值不会被更新 | |||
* | |||
* @param paramMap map或实体 | |||
* @return | |||
*/ | |||
@UpdateProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
int updateByPrimaryKey(Object paramMap); | |||
@UpdateProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
int update(Object paramMap); | |||
/** | |||
* 根据主键更新实体全部字段,null值也会被更新 | |||
* | |||
* @param entity | |||
* @return | |||
*/ | |||
// @UpdateProvider(type = BaseProviderSqlSource.class, method = "dynamicSQL") | |||
// int updateByPrimaryKeyAllProperty(T entity); | |||
} |
@@ -0,0 +1,234 @@ | |||
package com.qmrz.mybatis; | |||
import com.qmrz.exception.ABException; | |||
import com.qmrz.mybatis.service.BaseService; | |||
import com.qmrz.utils.SpringContextUtil; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.ibatis.builder.annotation.ProviderSqlSource; | |||
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; | |||
import org.apache.ibatis.executor.keygen.NoKeyGenerator; | |||
import org.apache.ibatis.mapping.*; | |||
import org.apache.ibatis.reflection.MetaObject; | |||
import org.apache.ibatis.reflection.SystemMetaObject; | |||
import org.apache.ibatis.scripting.xmltags.DynamicSqlSource; | |||
import org.apache.ibatis.scripting.xmltags.SqlNode; | |||
import org.apache.ibatis.scripting.xmltags.TextSqlNode; | |||
import org.apache.ibatis.session.Configuration; | |||
import org.apache.ibatis.session.SqlSessionFactory; | |||
import org.springframework.core.io.Resource; | |||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; | |||
import java.io.IOException; | |||
import java.lang.reflect.InvocationTargetException; | |||
import java.lang.reflect.Method; | |||
import java.util.*; | |||
/** | |||
* mybatis功能扩展,实现无xml mapper | |||
*/ | |||
@Slf4j | |||
public class MapperScan { | |||
/** | |||
* 通用方法 | |||
*/ | |||
private Map<String, Method> methods; | |||
private Configuration configuration; | |||
private BaseProviderSqlSource baseProviderSqlSource; | |||
public MapperScan() { | |||
load(SpringContextUtil.getBean(SqlSessionFactory.class)); | |||
} | |||
public MapperScan(SqlSessionFactory sqlSessionFactory) { | |||
load(sqlSessionFactory); | |||
} | |||
public void load(SqlSessionFactory sqlSessionFactory) { | |||
this.methods = new HashMap<>(); | |||
this.baseProviderSqlSource = new BaseProviderSqlSource(); | |||
this.configuration = sqlSessionFactory.getConfiguration(); | |||
for (Method method : BaseProviderSqlSource.class.getDeclaredMethods()) { | |||
methods.put(method.getName(), method); | |||
} | |||
} | |||
/** | |||
* 同时扩展mybatis接口和实体功能 | |||
* @throws IllegalAccessException | |||
* @throws InvocationTargetException | |||
* @throws ClassNotFoundException | |||
*/ | |||
public void register() throws IllegalAccessException, InvocationTargetException, ClassNotFoundException { | |||
log.info("扩展 mybatis 接口、实体"); | |||
registerMapper(); | |||
registerActiveRecord(); | |||
} | |||
/** | |||
* 实现无xml的mapper接口 | |||
* @throws InvocationTargetException | |||
* @throws IllegalAccessException | |||
*/ | |||
public void registerMapper() throws InvocationTargetException, IllegalAccessException { | |||
// log.info("MapperScan registerMapper"); | |||
for (Object object : new ArrayList<Object>(configuration.getMappedStatements())) { | |||
if (!(object instanceof MappedStatement)) { | |||
continue; | |||
} | |||
MappedStatement mappedStatement = (MappedStatement) object; | |||
SqlSource sqlSourceTemp = mappedStatement.getSqlSource(); | |||
if (!(sqlSourceTemp instanceof ProviderSqlSource)) { | |||
continue; | |||
} | |||
log.info("mappedStatement:" + mappedStatement.getId()); | |||
String msId = mappedStatement.getId(); | |||
Method method = methods.get(msId.substring(msId.lastIndexOf(".") + 1)); | |||
if (method == null) { | |||
log.warn("通用mapper:" + msId + " 在BaseProviderSqlSource找不到提供方法"); | |||
continue; | |||
} | |||
Class<?> classPO = MapperUtil.getMapperClass(mappedStatement); | |||
SqlSource sqlSource = createSqlSource(method, mappedStatement, classPO, null); | |||
MetaObject msObject = SystemMetaObject.forObject(object); | |||
msObject.setValue("sqlSource", sqlSource); | |||
} | |||
} | |||
/** | |||
* 创建字符串类型sqlSource | |||
* @param script | |||
* @param parameterType | |||
* @return | |||
*/ | |||
private SqlSource createSqlSource(String script, Class<?> parameterType) { | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append("<script>\n\t"); | |||
sql.append(script); | |||
sql.append("</script>"); | |||
return configuration.getDefaultScriptingLanguageInstance() | |||
.createSqlSource(configuration, sql.toString(), parameterType); | |||
} | |||
/** | |||
* 创建sqlSource对象,自动识别sql类型(String、SqlNode) | |||
* @param method | |||
* @param mappedStatement | |||
* @param classPO | |||
* @param parameterType | |||
* @return | |||
* @throws InvocationTargetException | |||
* @throws IllegalAccessException | |||
*/ | |||
private SqlSource createSqlSource(Method method, MappedStatement mappedStatement, Class<?> classPO, Class<?> parameterType) throws InvocationTargetException, IllegalAccessException { | |||
SqlSource sqlSource; | |||
if (String.class.equals(method.getReturnType())) { | |||
String script = (String) method.invoke(baseProviderSqlSource, mappedStatement, classPO); | |||
sqlSource = createSqlSource(script, parameterType); | |||
} else if (SqlNode.class.isAssignableFrom(method.getReturnType())) { | |||
SqlNode sqlNode = (SqlNode) method.invoke(baseProviderSqlSource, mappedStatement, classPO); | |||
sqlSource = new DynamicSqlSource(configuration, sqlNode); | |||
} else { | |||
throw new ABException("未知sql源"); | |||
} | |||
return sqlSource; | |||
} | |||
/** | |||
* 扩展实体功能 | |||
* @throws ClassNotFoundException | |||
* @throws InvocationTargetException | |||
* @throws IllegalAccessException | |||
*/ | |||
public void registerActiveRecord() throws ClassNotFoundException, InvocationTargetException, IllegalAccessException { | |||
//获取实体资源 | |||
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); | |||
Resource[] r = new Resource[0]; | |||
try { | |||
r = resolver.getResources("classpath*:com/qmrz/domain/**/*.class"); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
//实体资源转字符串 | |||
List<String> classList = new ArrayList<>(); | |||
try { | |||
for (Resource resource : r) { | |||
String path = resource.getURL().getPath(); | |||
path = path.replace("\\", "/"); | |||
classList.add(path.substring(path.indexOf("/com/") + 1 | |||
, path.lastIndexOf(".class")) | |||
.replace("/", ".")); | |||
} | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
//将属于BasePO类的实体进行扩展 | |||
for (String str : classList) { | |||
Class<?> classPO = Class.forName(str); | |||
if (!BasePO.class.isAssignableFrom(classPO)) { | |||
continue; | |||
} | |||
Method[] methods = BaseService.class.getMethods(); | |||
for (Method method : methods) { | |||
registerActiveRecordMethod(method.getName(), classPO); | |||
} | |||
} | |||
} | |||
/** | |||
* 注册实体扩展方法 | |||
* @param methodName | |||
* @param classPO | |||
* @throws InvocationTargetException | |||
* @throws IllegalAccessException | |||
*/ | |||
private void registerActiveRecordMethod(String methodName, Class<?> classPO) throws InvocationTargetException, IllegalAccessException { | |||
String id = classPO.getName() + "_" + methodName; | |||
String newMsId = id + "_ActiveRecord"; | |||
//创建默认动态sql | |||
SqlSource sqlSource = new DynamicSqlSource(configuration, new TextSqlNode("SQL_CommonMapper")); | |||
SqlCommandType sqlCommandType = null; | |||
if (methodName.startsWith("select")) { | |||
sqlCommandType = SqlCommandType.SELECT; | |||
} else if (methodName.startsWith("update")) { | |||
sqlCommandType = SqlCommandType.UPDATE; | |||
} else if (methodName.startsWith("insert")) { | |||
sqlCommandType = SqlCommandType.INSERT; | |||
} else if (methodName.startsWith("delete")) { | |||
sqlCommandType = SqlCommandType.DELETE; | |||
} | |||
//Statement构建配置 | |||
MappedStatement.Builder builder = | |||
new MappedStatement.Builder(configuration | |||
, newMsId, sqlSource, sqlCommandType); | |||
if (methodName.startsWith("insert")) { | |||
builder.keyProperty("id"); | |||
} | |||
//Statement构建 | |||
MappedStatement statement = builder.build(); | |||
//insert后支持主键注入 | |||
builder.keyGenerator(SqlCommandType.INSERT.equals(sqlCommandType) ? new Jdbc3KeyGenerator() : new NoKeyGenerator()); | |||
//获取statement对应方法 | |||
Method method = methods.get(methodName); | |||
//扩展方法与statement绑定并返回SqlSource | |||
sqlSource = createSqlSource(method, statement, classPO, null); | |||
//配置statement方法的sql源 | |||
MetaObject msObject = SystemMetaObject.forObject(statement); | |||
msObject.setValue("sqlSource", sqlSource); | |||
//注入mybatis | |||
configuration.addMappedStatement(statement); | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
package com.qmrz.mybatis; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.beans.factory.support.BeanDefinitionRegistry; | |||
@Slf4j | |||
public class MapperScannerConfigurer extends org.mybatis.spring.mapper.MapperScannerConfigurer { | |||
public void setMarkerInterface(Class<?> superClass) { | |||
log.info("setMarkerInterface"); | |||
log.info(superClass.getName()); | |||
super.setMarkerInterface(superClass); | |||
// this.markerInterface = superClass; | |||
// if (Marker.class.isAssignableFrom(superClass)) { | |||
// mapperHelper.registerMapper(superClass); | |||
// } | |||
} | |||
@Override | |||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { | |||
log.info("postProcessBeanDefinitionRegistry"); | |||
super.postProcessBeanDefinitionRegistry(registry); | |||
} | |||
@Override | |||
public void afterPropertiesSet() throws Exception { | |||
log.info("afterPropertiesSet"); | |||
super.afterPropertiesSet(); | |||
} | |||
} |
@@ -0,0 +1,96 @@ | |||
package com.qmrz.mybatis; | |||
import com.qmrz.exception.ABException; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.ibatis.mapping.MappedStatement; | |||
import org.apache.ibatis.mapping.ResultMap; | |||
import org.apache.ibatis.mapping.ResultMapping; | |||
import org.apache.ibatis.reflection.MetaObject; | |||
import org.apache.ibatis.reflection.SystemMetaObject; | |||
import org.apache.ibatis.session.Configuration; | |||
import java.lang.reflect.Field; | |||
import java.lang.reflect.ParameterizedType; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.List; | |||
@Slf4j | |||
public class MapperUtil { | |||
/** | |||
* 获取Mapper的泛型实体 | |||
* | |||
* @param ms | |||
* @return | |||
*/ | |||
public static Class<?> getMapperClass(MappedStatement ms) { | |||
// log.warn(ms.getResource()); | |||
String poClassName = ms.getResource().replace(".java (best guess)", "") | |||
.replace("/", "."); | |||
//获取实体 | |||
Class<?> classPO; | |||
try { | |||
Class<?> clazz = Class.forName(poClassName); | |||
classPO = (Class<?>) ((ParameterizedType) (clazz.getGenericInterfaces()[0])).getActualTypeArguments()[0]; | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
throw new ABException("通用Mapper:" + e.getMessage()); | |||
} | |||
// log.warn(classPO.getName()); | |||
return classPO; | |||
} | |||
public static void setResultType(MappedStatement ms, Class<?> classPO) { | |||
Configuration configuration = ms.getConfiguration(); | |||
MetaObject msObject = SystemMetaObject.forObject(ms); | |||
// List<ResultMapping> resultMappings = new ArrayList<>(); | |||
// MetaObject msObject = SystemMetaObject.forObject(ms); | |||
// ResultMap.Builder builder = new ResultMap.Builder(ms.getConfiguration() | |||
// , classPO.getName() + "_ResultType", | |||
// classPO, resultMappings, true); | |||
// | |||
// | |||
// | |||
// List<ResultMap> resultMaps = new ArrayList<>(); | |||
// resultMaps.add(builder.build()); | |||
// msObject.setValue("resultMaps", Collections.unmodifiableList(resultMaps)); | |||
List<ResultMapping> resultMappings = new ArrayList<>(); | |||
for (Field field : classPO.getDeclaredFields()) { | |||
ResultMapping.Builder builder = new ResultMapping.Builder(configuration | |||
, field.getName(), field.getName()//, POUtil.getFieldNameByDB(field) | |||
, field.getType()); | |||
resultMappings.add(builder.build()); | |||
} | |||
ResultMap.Builder builder = new ResultMap.Builder(configuration, classPO.getName() + "_CommonMapperResultMap", | |||
classPO, resultMappings, true); | |||
List<ResultMap> resultMaps = new ArrayList<>(); | |||
resultMaps.add(builder.build()); | |||
msObject.setValue("resultMaps", Collections.unmodifiableList(resultMaps)); | |||
} | |||
public static void setResultType2(MappedStatement ms, Class<?> cla, String fieldName) { | |||
Configuration configuration = ms.getConfiguration(); | |||
MetaObject msObject = SystemMetaObject.forObject(ms); | |||
List<ResultMapping> resultMappings = new ArrayList<>(); | |||
ResultMapping.Builder builder2 = new ResultMapping.Builder(configuration | |||
, fieldName, fieldName//, POUtil.getFieldNameByDB(field) | |||
, cla); | |||
resultMappings.add(builder2.build()); | |||
ResultMap.Builder builder = new ResultMap.Builder(configuration, cla.getName() + "_CommonMapperResultMap", | |||
cla, resultMappings, true); | |||
List<ResultMap> resultMaps = new ArrayList<>(); | |||
resultMaps.add(builder.build()); | |||
msObject.setValue("resultMaps", Collections.unmodifiableList(resultMaps)); | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.qmrz.mybatis; | |||
import lombok.Data; | |||
import org.apache.commons.lang.StringUtils; | |||
import java.util.List; | |||
/** | |||
* 实体属性与DB字段 | |||
*/ | |||
@Data | |||
public class PO { | |||
private String tableNameByDB; | |||
private List<POPropertie> fieldList; | |||
private Class<?> entityClass; | |||
private String schemasName; | |||
public String getTableNameByDBAll() { | |||
if (StringUtils.isEmpty(this.schemasName)) { | |||
return this.tableNameByDB; | |||
} else { | |||
return this.schemasName + "." + this.tableNameByDB; | |||
} | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
package com.qmrz.mybatis; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Data; | |||
import java.lang.reflect.Field; | |||
/** | |||
* 实体属性与DB字段 | |||
*/ | |||
@Data | |||
@AllArgsConstructor | |||
public class POPropertie { | |||
private String fieldName; | |||
private String fieldNameByDB; | |||
private Field field; | |||
private Class<?> javaType; | |||
/** | |||
* 默认为null,若不为null,则对应db类型字段串 | |||
*/ | |||
private String dbType; | |||
/** | |||
* 0:无排序 1:asc 2:desc | |||
*/ | |||
private int orderByStatus; | |||
private int orderByIndex; | |||
private boolean isPrimarykey; | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.qmrz.mybatis; | |||
import lombok.Data; | |||
/** | |||
* 实体属性与DB字段 | |||
*/ | |||
@Data | |||
public class POPropertieValue extends POPropertie { | |||
private Object value; | |||
public POPropertieValue(POPropertie p, Object value) { | |||
super(p.getFieldName(), p.getFieldNameByDB(), p.getField(), p.getJavaType(),p.getDbType() | |||
, p.getOrderByStatus(), p.getOrderByIndex(), p.isPrimarykey()); | |||
this.value = value; | |||
} | |||
} |
@@ -0,0 +1,61 @@ | |||
package com.qmrz.mybatis; | |||
import org.springframework.cglib.proxy.Enhancer; | |||
import org.springframework.cglib.proxy.MethodInterceptor; | |||
import org.springframework.cglib.proxy.MethodProxy; | |||
import java.lang.reflect.Method; | |||
import java.lang.reflect.ParameterizedType; | |||
import java.util.*; | |||
/** | |||
* 实体代理类,用于监控实体属性的变化 | |||
*/ | |||
public class POProxy implements MethodInterceptor { | |||
private Enhancer enhancer = new Enhancer(); | |||
private Class<?> classPO; | |||
private Map<String, Object> setList = new LinkedHashMap<>(); | |||
public Class<?> getClassPO() { | |||
return classPO; | |||
} | |||
public Map<String, Object> getSetList() { | |||
return setList; | |||
} | |||
/** | |||
* 创建代理 | |||
* @param classPO | |||
* @param <T> | |||
* @return | |||
*/ | |||
public <T> T getProxy(Class classPO) { | |||
this.classPO = classPO; | |||
//设置创建子类的类 | |||
enhancer.setSuperclass(classPO); | |||
enhancer.setCallback(this); | |||
return (T) enhancer.create(); | |||
} | |||
/** | |||
* 监控set属性 | |||
* @param o | |||
* @param method | |||
* @param objects | |||
* @param methodProxy | |||
* @return | |||
* @throws Throwable | |||
*/ | |||
@Override | |||
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { | |||
String methodName = method.getName().toLowerCase(); | |||
if (methodName.startsWith("set")) { | |||
setList.put(methodName.substring(3, methodName.length()), objects[0]); | |||
} | |||
//代理类调用父类的方法 | |||
return methodProxy.invokeSuper(o, objects); | |||
} | |||
} |
@@ -0,0 +1,463 @@ | |||
package com.qmrz.mybatis; | |||
import com.qmrz.exception.ABException; | |||
import com.qmrz.mybatis.annotation.*; | |||
import org.apache.ibatis.reflection.MetaObject; | |||
import org.apache.ibatis.reflection.SystemMetaObject; | |||
import java.lang.annotation.Annotation; | |||
import java.lang.reflect.Field; | |||
import java.util.*; | |||
public class POUtil { | |||
private static final Class<? extends Annotation> AnnotationID = ID.class; | |||
private static final Class<? extends Annotation> AnnotationDBType = DBType.class; | |||
private static final Class<? extends Annotation> AnnotationFieldName = FieldName.class; | |||
private static final Class<? extends Annotation> AnnotationTableName = TableName.class; | |||
private static final Class<? extends Annotation> AnnotationOrderByDefault = OrderByDefault.class; | |||
private Class<?> classPO; | |||
private String tableNameByDB; | |||
private String schemasNameByDB; | |||
private List<POPropertie> propertieList; | |||
private List<POPropertie> propertieListOrderBy; | |||
private POPropertie primarykey; | |||
public POUtil(Class<?> classPO) { | |||
this.classPO = classPO; | |||
this.loadTableNameByDB(); | |||
this.loadSchemasNameByDB(); | |||
this.loadPropertieList(); | |||
this.loadOrderBy(); | |||
} | |||
public String getTableNameByDB() { | |||
return tableNameByDB; | |||
} | |||
public String getSchemasNameByDB() { | |||
return schemasNameByDB; | |||
} | |||
public List<POPropertie> getPropertieList() { | |||
return propertieList; | |||
} | |||
public List<POPropertie> getPropertieListOrderBy() { | |||
return propertieListOrderBy; | |||
} | |||
public POPropertie getPrimarykey() { | |||
return primarykey; | |||
} | |||
private void loadOrderBy() { | |||
this.propertieListOrderBy = new ArrayList<>(); | |||
this.propertieList.forEach(item -> { | |||
if (item.getOrderByStatus() != 0) { | |||
this.propertieListOrderBy.add(item); | |||
} | |||
}); | |||
Collections.sort(this.propertieListOrderBy, new Comparator<POPropertie>() { | |||
@Override | |||
public int compare(POPropertie o1, POPropertie o2) { | |||
if (o1.getOrderByIndex() < o2.getOrderByIndex()) { | |||
return -1; | |||
} else if (o1.getOrderByIndex() == o2.getOrderByIndex()) { | |||
return 0; | |||
} else { | |||
return 1; | |||
} | |||
} | |||
}); | |||
} | |||
/** | |||
* 写入参数,insert和update时的参数,不包含主键 和 为null | |||
* | |||
* @param po | |||
* @return | |||
*/ | |||
// public Map<String, Object> getParamWriteNotNull(Object po) { | |||
// Map<String, Object> param = new LinkedHashMap<>(); | |||
// getPropertieNotNull(po).forEach(item -> { | |||
// param.put(item.getFieldName(), item.getValue()); | |||
// }); | |||
// return param; | |||
// } | |||
/** | |||
* 实体转map,若实体对象在当前实体结构中不存在,则不加入map | |||
* | |||
* @param po | |||
* @return | |||
*/ | |||
public Map<String, Object> getParam(Object po) { | |||
Map<String, Object> param = new LinkedHashMap<>(); | |||
MetaObject mo = SystemMetaObject.forObject(po); | |||
List<String> names = Arrays.asList(mo.getGetterNames()); | |||
getPropertieList().forEach(item -> { | |||
String dbname = item.getFieldNameByDB(); | |||
if (names.contains(dbname)) { | |||
param.put(dbname, mo.getValue(dbname)); | |||
} | |||
}); | |||
return param; | |||
} | |||
/** | |||
* @param paramPrimaryKey 实体(里面存储key字段) | |||
* @return | |||
*/ | |||
public Map<String, Object> getParamPrimaryKey(Object paramPrimaryKey) { | |||
MetaObject msObject = SystemMetaObject.forObject(paramPrimaryKey); | |||
Map<String, Object> param = new LinkedHashMap<>(); | |||
param.put(this.primarykey.getFieldNameByDB() | |||
, msObject.getValue(this.primarykey.getFieldName())); | |||
return param; | |||
} | |||
public Map<String, Object> getParamPrimaryKeyByValue(Object value) { | |||
Map<String, Object> param = new LinkedHashMap<>(); | |||
param.put(this.primarykey.getFieldNameByDB() | |||
, value); | |||
return param; | |||
} | |||
public Object getValueByPrimaryKey(Object objectPO) { | |||
MetaObject msObject = SystemMetaObject.forObject(objectPO); | |||
return msObject.getValue(this.primarykey.getFieldName()); | |||
} | |||
// /** | |||
// * 写入参数,insert和update时的参数,不包含主键 和 为null | |||
// * | |||
// * @return | |||
// */ | |||
// public Map<String, Object> getParamWriteNotNull(Object po) { | |||
// MetaObject msObject = SystemMetaObject.forObject(po); | |||
// Map<String, Object> param = new LinkedHashMap<>(); | |||
// | |||
// for (POPropertie item : this.getPropertieList()) { | |||
// if (item.isPrimarykey()) { | |||
// continue; | |||
// } | |||
// | |||
// Object val = msObject.getValue(item.getFieldName()); | |||
// if (val == null) { | |||
// continue; | |||
// } | |||
// | |||
// param.put(item.getFieldName(), val); | |||
// } | |||
// return param; | |||
// } | |||
/** | |||
* 获取所有非null属性(不含主键、含属性值) | |||
* | |||
* @param po | |||
* @return | |||
*/ | |||
// public List<POPropertieValue> getPropertieNotNull(Object po) { | |||
// List<POPropertieValue> fieldList = new ArrayList<>(); | |||
// MetaObject msObject = SystemMetaObject.forObject(po); | |||
// | |||
// for (POPropertie propertie : this.propertieList) { | |||
// if (propertie.isPrimarykey()) { | |||
// continue; | |||
// } | |||
// Object fieldValue = msObject.getValue(propertie.getFieldName()); | |||
// if (fieldValue == null) { | |||
// continue; | |||
// } | |||
// fieldList.add(new POPropertieValue(propertie, fieldValue)); | |||
// } | |||
// return fieldList; | |||
// } | |||
/** | |||
* Object转map | |||
* | |||
* @param po | |||
* @return | |||
*/ | |||
public static Map<String, Object> getMap(Object po) { | |||
List<POPropertieValue> fieldList = new ArrayList<>(); | |||
MetaObject msObject = SystemMetaObject.forObject(po); | |||
Field[] fields = po.getClass().getDeclaredFields(); | |||
Map<String, Object> result = new LinkedHashMap<>(); | |||
for (Field field : fields) { | |||
result.put(field.getName(), msObject.getValue(field.getName())); | |||
} | |||
return result; | |||
} | |||
// public Map<String, Object> getMapNotNull(Object po) { | |||
// List<POPropertieValue> fieldList = new ArrayList<>(); | |||
// MetaObject msObject = SystemMetaObject.forObject(po); | |||
// | |||
// Map<String, Object> result = new LinkedHashMap<>(); | |||
// for (POPropertie item : this.propertieList) { | |||
// Object val = msObject.getValue(item.getFieldName()); | |||
// if (val == null) { | |||
// continue; | |||
// } | |||
// if (item.isPrimarykey()) { | |||
// continue; | |||
// } | |||
// result.put(item.getFieldName(), val); | |||
// } | |||
// | |||
// return result; | |||
// } | |||
/** | |||
* 填充实体数据,将object 属性填充到 objectProxy | |||
* | |||
* @param objectProxy | |||
* @param object | |||
*/ | |||
public static void fillNotNull(BasePO objectProxy, Object object, boolean isAllowNull) { | |||
List<POPropertieValue> fieldList = new ArrayList<>(); | |||
MetaObject msObjectProxy = SystemMetaObject.forObject(objectProxy); | |||
MetaObject msObject = SystemMetaObject.forObject(object); | |||
for (Field field : objectProxy._getProxy().getClassPO().getDeclaredFields()) { | |||
if (!msObject.hasGetter(field.getName())) { | |||
continue; | |||
} | |||
Object obj = msObject.getValue(field.getName()); | |||
if (obj == null) { | |||
if (isAllowNull) { | |||
continue; | |||
} else { | |||
//若object有属性,则必须不能为null | |||
throw new ABException(field.getName() + "不允许为空"); | |||
} | |||
} | |||
msObjectProxy.setValue(field.getName(), obj); | |||
} | |||
} | |||
public static void fillNotNull(BasePO objectProxy, Object object, String[] fieldNameList, boolean isAllowNull) { | |||
List<POPropertieValue> fieldList = new ArrayList<>(); | |||
MetaObject msObjectProxy = SystemMetaObject.forObject(objectProxy); | |||
MetaObject msObject = SystemMetaObject.forObject(object); | |||
for (String fieldName : fieldNameList) { | |||
if (!msObject.hasGetter(fieldName)) { | |||
continue; | |||
} | |||
Object obj = msObject.getValue(fieldName); | |||
if (obj == null) { | |||
if (isAllowNull) { | |||
continue; | |||
} else { | |||
//若object有属性,则必须不能为null | |||
throw new ABException(fieldName + "不允许为空"); | |||
} | |||
} | |||
msObjectProxy.setValue(fieldName, obj); | |||
} | |||
} | |||
/** | |||
* 只返回指定参数 | |||
* | |||
* @param po | |||
* @param names | |||
* @return | |||
*/ | |||
public static Map<String, Object> getMapByNames(Object po, String... names) { | |||
Map<String, Object> result = new LinkedHashMap<>(); | |||
if (po == null) { | |||
return result; | |||
} | |||
MetaObject msObject = SystemMetaObject.forObject(po); | |||
for (String name : names) { | |||
result.put(name, msObject.getValue(name)); | |||
} | |||
return result; | |||
} | |||
/** | |||
* 只返回指定参数 | |||
* | |||
* @param list | |||
* @param names | |||
* @return | |||
*/ | |||
public static List<Map<String, Object>> getListMapByNames(List list, String... names) { | |||
List<Map<String, Object>> result = new ArrayList<>(); | |||
for (Object o : list) { | |||
result.add(getMapByNames(o, names)); | |||
} | |||
return result; | |||
} | |||
/** | |||
* 获取所有属性(不含值) | |||
* | |||
* @return | |||
*/ | |||
public void loadPropertieList() { | |||
this.propertieList = new ArrayList<>(); | |||
Field[] fields = classPO.getDeclaredFields(); | |||
// POPropertie propID = null; | |||
POPropertie propIDTmp = null; | |||
boolean hasOrderBy = false;//是否有指定排序注解,若没有默认主键降序排序 | |||
for (Field field : fields) { | |||
String fieldName = field.getName(); | |||
String fieldNameByDB = getFieldNameByDB(field); | |||
//获取order by | |||
int orderByStatus = 0; | |||
int orderByIndex = 0; | |||
if (field.isAnnotationPresent(AnnotationOrderByDefault)) { | |||
OrderByDefault orderByDefault | |||
= ((OrderByDefault) field.getAnnotation(AnnotationOrderByDefault)); | |||
boolean isasc = orderByDefault.isasc(); | |||
if (isasc) { | |||
orderByStatus = 1; | |||
} else { | |||
orderByStatus = 2; | |||
} | |||
orderByIndex = orderByDefault.index(); | |||
hasOrderBy = true; | |||
} | |||
//验证是否主键 | |||
boolean isPrimarykey = false; | |||
if (field.isAnnotationPresent(AnnotationID)) { | |||
if (this.primarykey != null) { | |||
throw new ABException("发现有多个 @ID 注释"); | |||
} | |||
isPrimarykey = true; | |||
} | |||
String dbType = null; | |||
if (field.isAnnotationPresent(AnnotationDBType)) { | |||
dbType = ((DBType) field.getAnnotation(AnnotationDBType)).type(); | |||
} | |||
POPropertie p = new POPropertie(fieldName, fieldNameByDB, field, field.getType(), dbType | |||
, orderByStatus, orderByIndex, isPrimarykey); | |||
if (isPrimarykey) { | |||
this.primarykey = p; | |||
} | |||
if ("id".equals(fieldName)) { | |||
p.setPrimarykey(true); | |||
propIDTmp = p; | |||
} | |||
this.propertieList.add(p); | |||
} | |||
if (this.primarykey == null) { | |||
if (propIDTmp == null) { | |||
if (tableNameByDB.length() >= 4 && "view".equals(tableNameByDB.substring(tableNameByDB.length() - 4))) { | |||
this.primarykey = new POPropertie(null, null, null, null, null, 1, 1, false); | |||
} else { | |||
throw new ABException("必须指定主键:" + this.classPO.getName()); | |||
} | |||
}else{ | |||
this.primarykey = propIDTmp; | |||
} | |||
} | |||
//若没有指定排序,则按主键降序排序 | |||
if (!hasOrderBy) { | |||
this.primarykey.setOrderByStatus(2); | |||
this.primarykey.setOrderByIndex(0); | |||
} | |||
} | |||
public POPropertie getPropertieByName(String name) { | |||
for (POPropertie item : this.propertieList) { | |||
if (name.equals(item.getFieldName())) { | |||
return item; | |||
} | |||
} | |||
throw new ABException("找不到字段:" + this.classPO.getName() + ":" + name); | |||
} | |||
/** | |||
* 获取数据库字段名 | |||
* | |||
* @param field | |||
* @return | |||
*/ | |||
public static String getFieldNameByDB(Field field) { | |||
String fieldNameByDB; | |||
if (field.isAnnotationPresent(AnnotationFieldName)) { | |||
fieldNameByDB = ((FieldName) field.getAnnotation(AnnotationFieldName)).name(); | |||
} else { | |||
fieldNameByDB = field.getName(); | |||
} | |||
return fieldNameByDB; | |||
} | |||
// private static boolean getFieldOrderyByDefault(Field field) { | |||
// if (!field.isAnnotationPresent(AnnotationOrderByDefault)) { | |||
// return false; | |||
// } | |||
// | |||
// boolean isasc = ((OrderByDefault) field.getAnnotation(AnnotationOrderByDefault)).isasc(); | |||
// return getFieldNameByDB(field) + (isasc ? " asc" : " desc"); | |||
// } | |||
/** | |||
* 获取数据库表名 | |||
* | |||
* @return | |||
*/ | |||
private void loadTableNameByDB() { | |||
if (classPO.isAnnotationPresent(AnnotationTableName)) { | |||
this.tableNameByDB = ((TableName) classPO.getAnnotation(AnnotationTableName)).name(); | |||
return; | |||
} | |||
String tableName = classPO.getSimpleName().toLowerCase(); | |||
if (tableName.lastIndexOf("po") > 0) { | |||
tableName = tableName.substring(0, tableName.length() - 2); | |||
} | |||
this.tableNameByDB = tableName; | |||
} | |||
private void loadSchemasNameByDB() { | |||
if (classPO.isAnnotationPresent(AnnotationTableName)) { | |||
this.schemasNameByDB = ((TableName) classPO.getAnnotation(AnnotationTableName)).schemasName(); | |||
return; | |||
} | |||
this.schemasNameByDB = ""; | |||
} | |||
// /** | |||
// * 是否有该注解 | |||
// * | |||
// * @param annotationClass | |||
// * @return | |||
// */ | |||
// public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { | |||
// boolean result = false; | |||
// if (field != null) { | |||
// result = field.isAnnotationPresent(annotationClass); | |||
// } | |||
// if (!result && setter != null) { | |||
// result = setter.isAnnotationPresent(annotationClass); | |||
// } | |||
// if (!result && getter != null) { | |||
// result = getter.isAnnotationPresent(annotationClass); | |||
// } | |||
// return result; | |||
// } | |||
} |
@@ -0,0 +1,344 @@ | |||
package com.qmrz.mybatis; | |||
import com.qmrz.exception.ABException; | |||
import org.apache.commons.lang.StringUtils; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
public class SqlUtil { | |||
private PO po; | |||
private POUtil poUtil; | |||
public SqlUtil(Class<?> entityClass) { | |||
po = new PO(); | |||
poUtil = new POUtil(entityClass); | |||
po.setEntityClass(entityClass); | |||
po.setFieldList(poUtil.getPropertieList()); | |||
po.setTableNameByDB(poUtil.getTableNameByDB()); | |||
po.setSchemasName(poUtil.getSchemasNameByDB()); | |||
if (po.getFieldList().size() == 0) { | |||
throw new ABException("没有字段"); | |||
} | |||
} | |||
public StringBuilder selectAllColumns() { | |||
StringBuilder sql = new StringBuilder(); | |||
List<String> list = new ArrayList<>(); | |||
sql.append("select "); | |||
po.getFieldList().forEach( | |||
item -> list.add(fieldDBSelect(item)) | |||
); | |||
sql.append(StringUtils.join(list.toArray(), ",")); | |||
return sql; | |||
} | |||
public StringBuilder selectCount(String fieldName) { | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append("select count(").append(fieldName).append(") as _count"); | |||
return sql; | |||
} | |||
public StringBuilder selectCount() { | |||
return selectCount(poUtil.getPrimarykey().getFieldNameByDB()); | |||
} | |||
// private String getAllFieldStr() { | |||
// List<POPropertie> properties = po.getFieldList(); | |||
// StringBuilder sql = new StringBuilder(); | |||
// properties.forEach( | |||
// item -> sql.append(item.getFieldNameByDB()).append(",") | |||
// ); | |||
// | |||
// return sql.substring(0, sql.length() - 1); | |||
// } | |||
private String getOrderByStr() { | |||
StringBuilder sql = new StringBuilder(); | |||
poUtil.getPropertieListOrderBy().forEach(item -> { | |||
int orderByStatus = item.getOrderByStatus(); | |||
String str = ""; | |||
if (orderByStatus == 1) { | |||
str = " asc"; | |||
} else if (orderByStatus == 2) { | |||
str = " desc"; | |||
} | |||
if (str.length() > 0) { | |||
sql.append(item.getFieldNameByDB()).append(str).append(","); | |||
} | |||
}); | |||
if (sql.length() > 0) { | |||
return sql.substring(0, sql.length() - 1); | |||
//return " order by " + str; | |||
} | |||
return ""; | |||
} | |||
public StringBuilder fromTable() { | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append(" from "); | |||
sql.append(po.getTableNameByDBAll()); | |||
return sql; | |||
} | |||
public String whereByPrimaryKeyXML() { | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append(" <where>"); | |||
List<POPropertie> properties = po.getFieldList(); | |||
sql.append(poUtil.getPrimarykey().getFieldNameByDB() | |||
+ "=#{" + poUtil.getPrimarykey().getFieldName() + "}"); | |||
sql.append("</where>"); | |||
return sql.toString(); | |||
} | |||
public String whereByPrimaryKey() { | |||
StringBuilder sql = new StringBuilder(); | |||
List<POPropertie> properties = po.getFieldList(); | |||
sql.append(" where "); | |||
sql.append(poUtil.getPrimarykey().getFieldNameByDB() | |||
+ "=#{" + poUtil.getPrimarykey().getFieldName() + "}"); | |||
return sql.toString(); | |||
} | |||
public String whereNotNullXML() { | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append(" <where>"); | |||
List<POPropertie> properties = po.getFieldList(); | |||
for (POPropertie column : properties) { | |||
sql.append(ifNotNullXML(column, column.getFieldNameByDB() + "=#{" + column.getFieldName() + "}")); | |||
} | |||
sql.append("</where>"); | |||
return sql.toString(); | |||
} | |||
public String whereXML() { | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append(" <where>"); | |||
List<POPropertie> properties = po.getFieldList(); | |||
for (POPropertie column : properties) { | |||
sql.append(" and " + column.getFieldNameByDB() + "=#{" + column.getFieldName() + "}"); | |||
} | |||
sql.append("</where>"); | |||
return sql.toString(); | |||
} | |||
// public String where() { | |||
// StringBuilder sql = new StringBuilder(); | |||
// sql.append(" where "); | |||
// List<POPropertie> properties = po.getFieldList(); | |||
// | |||
// List<String> list = new ArrayList<>(); | |||
// for (POPropertie column : properties) { | |||
// list.add(column.getFieldNameByDB() + "=#{" + column.getFieldName() + "}"); | |||
// } | |||
// sql.append(StringUtils.join(list.toArray()," and ")); | |||
// return sql.toString(); | |||
// } | |||
public StringBuilder whereByParam(Collection<String> param) { | |||
StringBuilder sql = new StringBuilder(); | |||
if (param.size() > 0) { | |||
sql.append(" where "); | |||
} | |||
List<String> list = new ArrayList<>(); | |||
for (String column : param) { | |||
POPropertie info = poUtil.getPropertieByName(column); | |||
list.add(info.getFieldNameByDB() + "=#{" + column + "}"); | |||
} | |||
sql.append(StringUtils.join(list.toArray(), " and ")); | |||
return sql; | |||
} | |||
/** | |||
* 不支持查询字符串为空的数据,若要查询,请使用wrapper | |||
* | |||
* @param column | |||
* @param contents | |||
* @return | |||
*/ | |||
private String ifNotNullXML(POPropertie column, String contents) { | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append(" <if test=\""); | |||
sql.append(column.getFieldName()).append(" != null"); | |||
if (column.getJavaType().equals(String.class)) {//若是字符串,则验证是否为"" | |||
sql.append(" and "); | |||
sql.append(column.getFieldName()).append(" != '' "); | |||
} | |||
sql.append("\">"); | |||
sql.append(contents); | |||
sql.append("</if>"); | |||
return sql.toString(); | |||
} | |||
public StringBuilder orderByDefault() { | |||
StringBuilder sql = new StringBuilder(); | |||
String orderBy = getOrderByStr(); | |||
if (orderBy.length() == 0) { | |||
return sql; | |||
} | |||
sql.append(" order by "); | |||
sql.append(orderBy); | |||
return sql; | |||
} | |||
public String updateSetNotNullXML() { | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append("update ").append(po.getTableNameByDB()).append(" <set>"); | |||
poUtil.getPropertieList().forEach(item -> { | |||
if (!item.isPrimarykey()) { | |||
sql.append(ifNotNullXML(item, item.getFieldNameByDB() + "=" + fieldDBWrite(item) + ",")); | |||
} | |||
}); | |||
sql.append("</set>"); | |||
return sql.toString(); | |||
} | |||
public StringBuilder updateSet(Collection<String> paramUpdateSet) { | |||
StringBuilder sql = new StringBuilder(); | |||
List<String> list = new ArrayList<>(); | |||
sql.append("update ").append(po.getTableNameByDB()).append(" set "); | |||
paramUpdateSet.forEach( | |||
item -> { | |||
POPropertie info = poUtil.getPropertieByName(item); | |||
list.add(info.getFieldNameByDB() + "=" + fieldDBWrite(info)); | |||
} | |||
); | |||
sql.append(StringUtils.join(list.toArray(), ",")); | |||
return sql; | |||
} | |||
public StringBuilder insert(Collection<String> paramUpdateSet) { | |||
List<String> fields = new ArrayList<>(); | |||
List<String> values = new ArrayList<>(); | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append("insert into ").append(po.getTableNameByDB()).append("("); | |||
paramUpdateSet.forEach( | |||
item -> { | |||
POPropertie info = poUtil.getPropertieByName(item); | |||
fields.add(info.getFieldNameByDB()); | |||
} | |||
); | |||
sql.append(StringUtils.join(fields.toArray(), ",")); | |||
sql.append(") values( "); | |||
paramUpdateSet.forEach( | |||
item -> { | |||
POPropertie info = poUtil.getPropertieByName(item); | |||
values.add(fieldDBWrite(info)); | |||
} | |||
); | |||
sql.append(StringUtils.join(values.toArray(), ",")); | |||
sql.append(")"); | |||
return sql; | |||
} | |||
public StringBuilder deleteFrom() { | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append("delete from "); | |||
sql.append(po.getTableNameByDBAll()); | |||
return sql; | |||
} | |||
public String insertNotNullXML() { | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append("insert into ").append(po.getTableNameByDB()).append(" ("); | |||
sql.append("<trim suffixOverrides=\",\">"); | |||
poUtil.getPropertieList().forEach(item -> { | |||
if (!item.isPrimarykey()) { | |||
sql.append(ifNotNullXML(item, item.getFieldNameByDB() + ",")); | |||
} | |||
}); | |||
sql.append("</trim>"); | |||
sql.append(") values ("); | |||
sql.append("<trim suffixOverrides=\",\">"); | |||
poUtil.getPropertieList().forEach(item -> { | |||
if (!item.isPrimarykey()) { | |||
sql.append(ifNotNullXML(item, fieldDBWrite(item) + ",")); | |||
} | |||
}); | |||
sql.append("</trim>"); | |||
sql.append(")"); | |||
return sql.toString(); | |||
} | |||
/** | |||
* 写入字段处理 | |||
* | |||
* @param item | |||
* @return | |||
*/ | |||
private String fieldDBWrite(POPropertie item) { | |||
String name = "#{" + item.getFieldName() + "}"; | |||
if (!StringUtils.isEmpty(item.getDbType())) { | |||
if ("datetime".equals(item.getDbType())) { | |||
name = "from_unixtime(#{" + item.getFieldName() + "})"; | |||
} | |||
} | |||
return name; | |||
} | |||
/** | |||
* 读取时字段处理 | |||
* | |||
* @param item | |||
* @return | |||
*/ | |||
private String fieldDBSelect(POPropertie item) { | |||
String name = item.getFieldNameByDB(); | |||
if (!StringUtils.isEmpty(item.getDbType())) { | |||
if ("datetime".equals(item.getDbType())) { | |||
name = "unix_timestamp(" + item.getFieldNameByDB() + ") as " + item.getFieldName(); | |||
} | |||
} else { | |||
if (!item.getFieldName().equals(item.getFieldNameByDB())) { | |||
name = item.getFieldNameByDB() + " as " + item.getFieldName(); | |||
} | |||
} | |||
return name; | |||
} | |||
public String limit(int limit) { | |||
return " limit " + limit; | |||
} | |||
public String limit(int startIndex, int limit) { | |||
return " limit " + startIndex + "," + limit; | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
package com.qmrz.mybatis.annotation; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
@Target(ElementType.FIELD) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
public @interface DBType { | |||
String type(); | |||
} |
@@ -0,0 +1,9 @@ | |||
package com.qmrz.mybatis.annotation; | |||
import java.lang.annotation.*; | |||
@Target(ElementType.FIELD) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
public @interface FieldName { | |||
String name() default ""; | |||
} |
@@ -0,0 +1,12 @@ | |||
package com.qmrz.mybatis.annotation; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
@Target(ElementType.FIELD) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
public @interface ID { | |||
} |
@@ -0,0 +1,13 @@ | |||
package com.qmrz.mybatis.annotation; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
@Target(ElementType.FIELD) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
public @interface OrderByDefault { | |||
boolean isasc() default false; | |||
int index(); | |||
} |
@@ -0,0 +1,13 @@ | |||
package com.qmrz.mybatis.annotation; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
@Target(ElementType.TYPE) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
public @interface TableName { | |||
String name() default ""; | |||
String schemasName() default ""; | |||
} |
@@ -0,0 +1,91 @@ | |||
package com.qmrz.mybatis.service; | |||
import com.qmrz.mybatis.BasePO; | |||
import com.qmrz.mybatis.Mapper; | |||
import com.qmrz.mybatis.sql.BaseWrapper; | |||
import com.qmrz.mybatis.sql.sqlnode.UpdateParam; | |||
import java.util.List; | |||
import java.util.function.Consumer; | |||
public abstract class AbstractService<T extends BasePO> implements BaseService<T> { | |||
private Mapper<T> baseMapper; | |||
public AbstractService(Mapper<T> baseMapper){ | |||
this.baseMapper = baseMapper; | |||
} | |||
public void setBaseMapper(Mapper<T> baseMapper) { | |||
this.baseMapper = baseMapper; | |||
} | |||
@Override | |||
public List<T> selectWrapper(Consumer<? super BaseWrapper> wrapper) { | |||
return baseMapper.selectWrapper(wrapper); | |||
} | |||
@Override | |||
public T selectOneWrapper(Consumer<? super BaseWrapper> wrapper) { | |||
return baseMapper.selectOneWrapper(wrapper); | |||
} | |||
@Override | |||
public Integer updateWrapper(Object param, Consumer<? super BaseWrapper> wrapper) { | |||
return baseMapper.updateWrapper(param, wrapper); | |||
} | |||
@Override | |||
public Integer deleteWrapper(Consumer<? super BaseWrapper> wrapper) { | |||
return baseMapper.deleteWrapper(wrapper); | |||
} | |||
@Override | |||
public List<T> select(Object whereObject) { | |||
return baseMapper.select(whereObject); | |||
} | |||
@Override | |||
public T selectOne(Object whereObject) { | |||
return baseMapper.selectOne(whereObject); | |||
} | |||
@Override | |||
public Integer selectCount(Object whereObject) { | |||
return baseMapper.selectCount(whereObject); | |||
} | |||
@Override | |||
public List<T> selectAll() { | |||
return baseMapper.selectAll(); | |||
} | |||
@Override | |||
public T selectByPrimaryKey(Object paramPrimaryKey) { | |||
return baseMapper.selectByPrimaryKey(paramPrimaryKey); | |||
} | |||
@Override | |||
public int deleteByPrimaryKey(Object paramPrimaryKey) { | |||
return baseMapper.deleteByPrimaryKey(paramPrimaryKey); | |||
} | |||
@Override | |||
public int delete(Object whereObject) { | |||
return baseMapper.delete(whereObject); | |||
} | |||
@Override | |||
public int insert(T entity) { | |||
return baseMapper.insert(entity); | |||
} | |||
@Override | |||
public int updateByPrimaryKey(Object paramMap) { | |||
return baseMapper.updateByPrimaryKey(paramMap); | |||
} | |||
@Override | |||
public int update(UpdateParam updateParam) { | |||
return baseMapper.update(updateParam); | |||
} | |||
} |
@@ -0,0 +1,90 @@ | |||
package com.qmrz.mybatis.service; | |||
import com.qmrz.mybatis.sql.BaseWrapper; | |||
import com.qmrz.mybatis.sql.sqlnode.UpdateParam; | |||
import java.util.List; | |||
import java.util.function.Consumer; | |||
public interface BaseService<T> { | |||
List<T> selectWrapper(Consumer<? super BaseWrapper> wrapper); | |||
T selectOneWrapper(Consumer<? super BaseWrapper> wrapper); | |||
Integer updateWrapper(Object param, Consumer<? super BaseWrapper> wrapper); | |||
Integer deleteWrapper(Consumer<? super BaseWrapper> wrapper); | |||
/** | |||
* 根据实体中的属性值进行查询,查询条件使用等号 | |||
* | |||
* @param whereObject map或实体 | |||
* @return | |||
*/ | |||
List<T> select(Object whereObject); | |||
/** | |||
* 根据实体中的属性进行查询,只能有一个返回值,有多个结果取第1个 | |||
* | |||
* @param whereObject map或实体 | |||
* @return | |||
*/ | |||
T selectOne(Object whereObject); | |||
/** | |||
* 根据实体中的属性查询总数,查询条件使用等号 | |||
* | |||
* @param whereObject map或实体 | |||
* @return | |||
*/ | |||
Integer selectCount(Object whereObject); | |||
/** | |||
* 查询全部结果 | |||
* | |||
* @return | |||
*/ | |||
List<T> selectAll(); | |||
/** | |||
* 根据主键字段进行查询,查询条件使用等号 | |||
* | |||
* @param paramPrimaryKey map或实体 | |||
* @return | |||
*/ | |||
T selectByPrimaryKey(Object paramPrimaryKey); | |||
/** | |||
* 根据主键字段进行删除,方法参数必须包含完整的主键属性 | |||
* | |||
* @param paramPrimaryKey map或实体 | |||
* @return | |||
*/ | |||
int deleteByPrimaryKey(Object paramPrimaryKey); | |||
/** | |||
* 根据实体属性作为条件进行删除,查询条件使用等号 | |||
* | |||
* @param whereObject map或实体 | |||
* @return | |||
*/ | |||
int delete(Object whereObject); | |||
/** | |||
* 保存一个实体,null的属性不会保存,会使用数据库默认值 | |||
* | |||
* @param entity map或实体 | |||
* @return | |||
*/ | |||
int insert(T entity); | |||
/** | |||
* 根据主键更新实体全部字段,null值不会被更新 | |||
* | |||
* @param paramMap map或实体 | |||
* @return | |||
*/ | |||
int updateByPrimaryKey(Object paramMap); | |||
int update(UpdateParam updateParam); | |||
} |
@@ -0,0 +1,131 @@ | |||
package com.qmrz.mybatis.sql; | |||
import com.qmrz.mybatis.SqlUtil; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* 基础条件接口 | |||
*/ | |||
public abstract class AbsWrapperData { | |||
/** | |||
* 0:where 1:select 2:from 3:order 5:group 6:limit | |||
* 20: update set | |||
* 30: insert | |||
* 40: delete | |||
*/ | |||
private int wrapperStatus = 0; | |||
/** | |||
* 当前块里的每个sql片段入栈时的条件组合方式 | |||
* 0:无 1:and块 2:or块 | |||
*/ | |||
private int conditionWhereStatus = 1; | |||
/** | |||
* 当前块的条件组合方式 0:无 1:and块 2:or块 | |||
*/ | |||
private int wrapperWhereStatus = 1; | |||
public int getWrapperStatus() { | |||
return wrapperStatus; | |||
} | |||
public int getConditionWhereStatus() { | |||
return conditionWhereStatus; | |||
} | |||
public int getWrapperWhereStatus() { | |||
return wrapperWhereStatus; | |||
} | |||
public abstract StringBuilder getSQL(); | |||
public StringBuilder getSQLLimit(){ | |||
return new StringBuilder(); | |||
} | |||
public abstract Map<String, Object> getParam(); | |||
private Class<?> classPO; | |||
protected SqlUtil sqlUtil; | |||
/** | |||
* 总序号 | |||
*/ | |||
private int index = 0; | |||
/** | |||
* 当前嵌套块的序号 | |||
*/ | |||
private int currentIndex = 0; | |||
protected void setIndex(int index) { | |||
this.index = index; | |||
renameByParamName(); | |||
} | |||
protected int getIndex() { | |||
return index; | |||
} | |||
protected void setCurrentIndex(int currentIndex) { | |||
this.currentIndex = currentIndex; | |||
} | |||
public AbsWrapperData(int wrapperStatus, int wrapperWhereStatus, int conditionWhereStatus, Class<?> classPO) { | |||
this.wrapperStatus = wrapperStatus; | |||
this.wrapperWhereStatus = wrapperWhereStatus; | |||
this.conditionWhereStatus = conditionWhereStatus; | |||
this.classPO = classPO; | |||
this.sqlUtil = new SqlUtil(classPO); | |||
} | |||
protected Class<?> getClassPO() { | |||
return classPO; | |||
} | |||
protected abstract void renameByParamName(); | |||
/** | |||
* 防止参数重复,重命名增加序号 | |||
* | |||
* @param fieldValue | |||
*/ | |||
protected void renameByParamName(ConditionGeneralValue fieldValue) { | |||
fieldValue.setName(fieldValue.getName() + "_" + index); | |||
} | |||
protected void renameByParamName(List<ConditionGeneralValue> fieldValue) { | |||
fieldValue.forEach(item -> item.setName(item.getName() + "_" + index)); | |||
} | |||
/** | |||
* 获取连接符 | |||
*/ | |||
public String getLinkStr() { | |||
String linkStr = " ";//每段sql的连接符,默认使用空格连接 | |||
if (0 == currentIndex) { | |||
return linkStr; | |||
} | |||
if (0 == this.getWrapperStatus()) {//若where操作 | |||
Integer whereStatus; | |||
//是否是块包装器 | |||
if (this instanceof BaseWrapper) { | |||
whereStatus = this.getWrapperWhereStatus(); | |||
} else { | |||
whereStatus = this.getConditionWhereStatus(); | |||
} | |||
if (1 == whereStatus) {//若and | |||
linkStr = " and "; | |||
} else if (2 == whereStatus) {//若or | |||
linkStr = " or "; | |||
} | |||
} | |||
return linkStr; | |||
} | |||
} |
@@ -0,0 +1,292 @@ | |||
package com.qmrz.mybatis.sql; | |||
import com.qmrz.mybatis.sql.statement.*; | |||
import java.util.*; | |||
import java.util.function.Consumer; | |||
public abstract class BaseWrapper extends AbsWrapperData implements IWrapper { | |||
/** | |||
* where 连接状态 | |||
* 1: and块 | |||
* 2: or块 | |||
*/ | |||
//protected int whereStatus = 1; | |||
private ConditionCount conditionsCount = new ConditionCount(0); | |||
private int conditionsCurrentCount = 0; | |||
private List<AbsWrapperData> conditions = new ArrayList<>(); | |||
protected void setConditionsCount(ConditionCount conditionsCount) { | |||
this.conditionsCount = conditionsCount; | |||
} | |||
public void addStatement(AbsWrapperData absWrapperData) { | |||
absWrapperData.setIndex(conditionsCount.getCount()); | |||
absWrapperData.setCurrentIndex(conditionsCurrentCount); | |||
conditions.add(absWrapperData); | |||
conditionsCount.increment(); | |||
conditionsCurrentCount++; | |||
} | |||
public List<AbsWrapperData> getConditions() { | |||
return conditions; | |||
} | |||
public BaseWrapper(int wrapperStatus, int wrapperWhereStatus, int conditionWhereStatus, Class<?> classPO) { | |||
super(wrapperStatus, wrapperWhereStatus, conditionWhereStatus, classPO); | |||
// Class<?> classPO = (Class<?>) ((ParameterizedType) (this.getClass().getGenericInterfaces()[0])).getActualTypeArguments()[0]; | |||
// POUtil.getPropertie(classPO); | |||
} | |||
/** | |||
* 此块的完整sql | |||
* | |||
* @return | |||
*/ | |||
@Override | |||
public StringBuilder getSQL() { | |||
StringBuilder sql = new StringBuilder(); | |||
if (conditions.size() == 0) { | |||
return sql; | |||
} | |||
boolean kuohao = 0 == this.getWrapperStatus() && 0 != this.getWrapperWhereStatus(); | |||
if (kuohao) {//where的条件时 | |||
sql.append(this.getLinkStr()).append("("); | |||
} | |||
conditions.forEach(item -> { | |||
if (6 != item.getWrapperStatus()) {//6 limit | |||
sql.append(item.getSQL()); | |||
} | |||
}); | |||
if (kuohao) {//where时 | |||
sql.append(")"); | |||
} | |||
return sql; | |||
} | |||
@Override | |||
public StringBuilder getSQLLimit() { | |||
StringBuilder sql = new StringBuilder(); | |||
if (conditions.size() == 0) { | |||
return sql; | |||
} | |||
conditions.forEach(item -> { | |||
// System.out.println("getSQLLimit"); | |||
sql.append(item.getSQLLimit()); | |||
}); | |||
return sql; | |||
} | |||
/** | |||
* 此块的所有参数 | |||
* | |||
* @return | |||
*/ | |||
public Map<String, Object> getParam() { | |||
Map<String, Object> param = new LinkedHashMap<>(); | |||
conditions.forEach(item -> { | |||
if (item.getParam() != null) { | |||
for (Map.Entry<String, Object> entry : item.getParam().entrySet()) { | |||
param.put(entry.getKey(), entry.getValue()); | |||
} | |||
} | |||
}); | |||
return param; | |||
} | |||
@Override | |||
protected void renameByParamName() { | |||
//块包装器只是块,无参数,无逻辑 | |||
} | |||
public BaseWrapper selectAllField() { | |||
addStatement(new SelectAllField(getClassPO())); | |||
return this; | |||
} | |||
public BaseWrapper update(Map<String, Object> setParam) { | |||
addStatement(new UpdateSet(getClassPO(), setParam)); | |||
return this; | |||
} | |||
public BaseWrapper delete() { | |||
addStatement(new DeleteFrom(getClassPO())); | |||
return this; | |||
} | |||
public BaseWrapper from() { | |||
addStatement(new FromTable(getClassPO())); | |||
return this; | |||
} | |||
public BaseWrapper limit(int limit) { | |||
addStatement(new Limit(getClassPO(), limit, null)); | |||
return this; | |||
} | |||
public BaseWrapper limit(int limit1, int limit2) { | |||
addStatement(new Limit(getClassPO(), limit1, limit2)); | |||
return this; | |||
} | |||
public BaseWrapper between(String fieldName, Object fieldValue1, Object fieldValue2) { | |||
List<ConditionGeneralValue> param = new ArrayList<>(); | |||
param.add(new ConditionGeneralValue(fieldName + "_between1", fieldValue1)); | |||
param.add(new ConditionGeneralValue(fieldName + "_between2", fieldValue2)); | |||
ConditionBetween c = new ConditionBetween(getWrapperWhereStatus() | |||
, getConditionWhereStatus(), getClassPO()); | |||
c.setFiedName(fieldName); | |||
c.setFieldValue(param); | |||
return addWhere(c); | |||
} | |||
public BaseWrapper in(String fieldName, List value) { | |||
return in(fieldName, value.toArray()); | |||
} | |||
public BaseWrapper in(String fieldName, Object ...value) { | |||
if (value == null || value.length==0) { | |||
return this; | |||
} | |||
List<ConditionGeneralValue> param = new ArrayList<>(); | |||
for (int i=0;i<value.length;i++) { | |||
String name=fieldName+"_in_"+String.valueOf(i); | |||
ConditionGeneralValue val=new ConditionGeneralValue(name,value[i]); | |||
param.add(val); | |||
} | |||
ConditionIn c = new ConditionIn(getWrapperWhereStatus() | |||
, getConditionWhereStatus(), getClassPO()); | |||
c.setFiedName(fieldName); | |||
c.setFieldValue(param); | |||
return addWhere(c); | |||
} | |||
/** | |||
* @param f 字段名称 | |||
* @param value | |||
* @return | |||
*/ | |||
public BaseWrapper eq(String f, Object value) { | |||
return addWhere(f, "_eq", value, "="); | |||
} | |||
public BaseWrapper neq(String fieldName, Object value) { | |||
return addWhere(fieldName, "_neq", value, "<>"); | |||
} | |||
public BaseWrapper gt(String fieldName, Object value) { | |||
return addWhere(fieldName, "_gt", value, ">"); | |||
} | |||
public BaseWrapper ge(String fieldName, Object value) { | |||
return addWhere(fieldName, "_ge", value, ">="); | |||
} | |||
public BaseWrapper lt(String fieldName, Object value) { | |||
return addWhere(fieldName, "_lt", value, "<"); | |||
} | |||
public BaseWrapper le(String fieldName, Object value) { | |||
return addWhere(fieldName, "_le", value, "<="); | |||
} | |||
public BaseWrapper or(Consumer<? super BaseWrapper> action) { | |||
return or(true, action); | |||
} | |||
public BaseWrapper orderByDefault() { | |||
addStatement(new OrderByDefault(getClassPO())); | |||
return this; | |||
} | |||
public BaseWrapper like(String fieldName, String fieldValue) { | |||
if (fieldValue == null) { | |||
return this; | |||
} | |||
ConditionLike c = new ConditionLike(this.getWrapperWhereStatus() | |||
, this.getConditionWhereStatus(), getClassPO()); | |||
c.setFiedName(fieldName); | |||
c.setFieldValue(new ConditionGeneralValue(fieldName + "_like", fieldValue)); | |||
return addWhere(c); | |||
} | |||
public BaseWrapper or(boolean isConditionAnd, Consumer<? super BaseWrapper> action) { | |||
OrBlock w = new OrBlock(isConditionAnd, this.conditionsCount, this.getClassPO()); | |||
this.addStatement(w); | |||
action.accept(w);//执行嵌套的链式调用 | |||
return this; | |||
} | |||
public BaseWrapper where() { | |||
this.addStatement( | |||
new StrWhere(this.getWrapperWhereStatus(), | |||
this.getConditionWhereStatus() | |||
, getClassPO()) | |||
); | |||
return this; | |||
} | |||
public BaseWrapper and(Consumer<? super BaseWrapper> action) { | |||
return and(true, action); | |||
} | |||
public BaseWrapper and(boolean isConditionAnd, Consumer<? super BaseWrapper> action) { | |||
AndBlock w = new AndBlock(isConditionAnd, this.conditionsCount, this.getClassPO()); | |||
this.addStatement(w); | |||
action.accept(w);//执行嵌套的链式调用 | |||
return this; | |||
} | |||
/** | |||
* 添加where语句 | |||
* | |||
* @param fieldName 参数名 | |||
* @param paramSuffix 参数后缀 | |||
* @param fieldValue 参数值 | |||
* @param condition 操作符 = > < | |||
* @return | |||
*/ | |||
private BaseWrapper addWhere(String fieldName, String paramSuffix, Object fieldValue, String condition) { | |||
ConditionGeneral c = new ConditionGeneral(this.getWrapperWhereStatus() | |||
, this.getConditionWhereStatus(), getClassPO()); | |||
c.setFiedName(fieldName); | |||
c.setFieldValue(new ConditionGeneralValue(fieldName + paramSuffix, fieldValue)); | |||
c.setCondition(condition); | |||
return addWhere(c); | |||
} | |||
/** | |||
* 添加where 条件语句 | |||
* | |||
* @param c | |||
* @return | |||
*/ | |||
private BaseWrapper addWhere(AbsWrapperData c) { | |||
int conditionWhere = this.getConditionWhereStatus(); | |||
//若只第一次where,则增加一个where包装,使状态conditionWhere进入and/or状态 | |||
if (conditionWhere != 1 && conditionWhere != 2) {//默认为and | |||
WhereBlock ab = new WhereBlock(true, conditionsCount, getClassPO()); | |||
ab.where().addStatement(c); | |||
this.addStatement(ab); | |||
return ab; | |||
} | |||
this.addStatement(c); | |||
return this; | |||
} | |||
public BaseWrapper notoption() { | |||
return this; | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.qmrz.mybatis.sql; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Data; | |||
/** | |||
* 在整个链式(包含 入嵌套和出嵌套 的条件及块的增量统计) | |||
*/ | |||
@Data | |||
@AllArgsConstructor | |||
public class ConditionCount { | |||
private Integer count; | |||
public int increment(){ | |||
this.count++; | |||
return this.count; | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
package com.qmrz.mybatis.sql; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Data; | |||
@Data | |||
@AllArgsConstructor | |||
public class ConditionGeneralValue { | |||
/** | |||
* sql参数名称 | |||
*/ | |||
private String name; | |||
/** | |||
* sql参数值 | |||
*/ | |||
private Object value; | |||
} |
@@ -0,0 +1,4 @@ | |||
package com.qmrz.mybatis.sql; | |||
public interface IWrapper { | |||
} |
@@ -0,0 +1,7 @@ | |||
package com.qmrz.mybatis.sql; | |||
public class Wrapper extends BaseWrapper { | |||
public Wrapper(Class<?> classPO) { | |||
super(-1, 0, 0,classPO); | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.qmrz.mybatis.sql; | |||
import com.qmrz.mybatis.sql.statement.AndBlock; | |||
import com.qmrz.mybatis.sql.statement.ConditionGeneral; | |||
import java.util.*; | |||
public class WrapperResolve { | |||
private BaseWrapper wrapper; | |||
private StringBuffer sql = new StringBuffer(); | |||
// private List<String> fieldList = new ArrayList<>(); | |||
private Map<String,Object> paramList = new LinkedHashMap<>(); | |||
public WrapperResolve(BaseWrapper wrapper) { | |||
this.wrapper = wrapper; | |||
} | |||
public void getSQL() { | |||
getSQL(wrapper.getConditions()); | |||
} | |||
private void getSQL(List<AbsWrapperData> list) { | |||
if (list.size() == 0) { | |||
return; | |||
} | |||
sql.append("("); | |||
list.forEach(item -> { | |||
getSQL(item); | |||
}); | |||
sql.append(")"); | |||
} | |||
private void getSQL(AbsWrapperData item) { | |||
if (item instanceof ConditionGeneral) { | |||
ConditionGeneral c = (ConditionGeneral) item; | |||
sql.append(item.getSQL()); | |||
paramList.put(c.getFieldValue().getName(), c.getFieldValue().getValue()); | |||
} else if (item instanceof BaseWrapper) { | |||
getSQL(((AndBlock) item).getConditions()); | |||
} | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
package com.qmrz.mybatis.sql; | |||
import java.util.List; | |||
import java.util.function.Consumer; | |||
public class WrapperUtil { | |||
public static boolean hasWhere(BaseWrapper w) { | |||
List<AbsWrapperData> list = w.getConditions(); | |||
boolean result = false; | |||
for (AbsWrapperData absWrapperData : list) { | |||
if (absWrapperData.getWrapperStatus() == 0) { | |||
result = true; | |||
break; | |||
} | |||
} | |||
return result; | |||
} | |||
public static Consumer<? super BaseWrapper> consumer(Consumer<? super BaseWrapper> w) { | |||
return w; | |||
} | |||
} |
@@ -0,0 +1,304 @@ | |||
package com.qmrz.mybatis.sql.sqlnode; | |||
import com.qmrz.exception.ABException; | |||
import com.qmrz.mybatis.BasePO; | |||
import com.qmrz.mybatis.SqlUtil; | |||
import com.qmrz.mybatis.sql.BaseWrapper; | |||
import com.qmrz.mybatis.sql.Wrapper; | |||
import com.qmrz.mybatis.sql.WrapperUtil; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.ibatis.binding.MapperMethod; | |||
import org.apache.ibatis.scripting.xmltags.DynamicContext; | |||
import org.apache.ibatis.scripting.xmltags.SqlNode; | |||
import java.util.Map; | |||
import java.util.function.Consumer; | |||
@Slf4j | |||
@SuppressWarnings("unchecked") | |||
public class SqlNodeWrapper implements SqlNode { | |||
/** | |||
* select、update、delete | |||
*/ | |||
private String option; | |||
private Class<?> classPO; | |||
private SqlUtil sqlUtil; | |||
public SqlNodeWrapper(Class<?> classPO, String option) { | |||
this.option = option; | |||
this.classPO = classPO; | |||
this.sqlUtil = new SqlUtil(classPO); | |||
} | |||
private void applySQL(DynamicContext context, StringBuilder sql, Map<String, Object>... param) { | |||
context.appendSql(sql.toString()); | |||
for (Map<String, Object> stringObjectMap : param) { | |||
stringObjectMap.forEach((k, v) -> | |||
context.bind(k, v) | |||
); | |||
} | |||
} | |||
@Override | |||
public boolean apply(DynamicContext context) { | |||
if (option.endsWith("Wrapper")) { | |||
return applyWrapper(context);//包装器模式解析 | |||
} else { | |||
return applyGeneral(context);//普通模式解析 | |||
} | |||
} | |||
/** | |||
* 普通模式解析 | |||
* | |||
* @param context | |||
* @return | |||
*/ | |||
public boolean applyGeneral(DynamicContext context) { | |||
Object param = context.getBindings().get("_parameter"); | |||
switch (option) { | |||
case "select": | |||
select(context); | |||
break; | |||
case "selectOne": | |||
selectOne(context); | |||
break; | |||
case "selectCount": | |||
selectCountResolve(context); | |||
break; | |||
case "update": | |||
updateResolve(context); | |||
break; | |||
case "delete": | |||
deleteResolve(context); | |||
break; | |||
case "insert": | |||
insertResolve(context); | |||
break; | |||
} | |||
return true; | |||
} | |||
private void select(DynamicContext context) { | |||
selectResolve(context, false); | |||
} | |||
private void selectOne(DynamicContext context) { | |||
selectResolve(context, true); | |||
} | |||
private void selectResolve(DynamicContext context, boolean isone) { | |||
Map<String, Object> param = (Map) context.getBindings().get("_parameter"); | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append(sqlUtil.selectAllColumns()); | |||
sql.append(sqlUtil.fromTable()); | |||
sql.append(sqlUtil.whereByParam(param.keySet())); | |||
sql.append(sqlUtil.orderByDefault()); | |||
if (isone) { | |||
sql.append(" limit 1"); | |||
} | |||
applySQL(context, sql, param); | |||
} | |||
private void selectCountResolve(DynamicContext context) { | |||
Map<String, Object> param = (Map) context.getBindings().get("_parameter"); | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append(sqlUtil.selectCount()); | |||
sql.append(sqlUtil.fromTable()); | |||
sql.append(sqlUtil.whereByParam(param.keySet())); | |||
applySQL(context, sql, param); | |||
} | |||
private void updateResolve(DynamicContext context) { | |||
UpdateParam updateParam = (UpdateParam) context.getBindings().get("_parameter"); | |||
Map<String, Object> set = updateParam.getSetData(); | |||
Map<String, Object> param = (Map<String, Object>) updateParam.getWhereData(); | |||
if (param.size() == 0) { | |||
throw new ABException("至少有一个查询条件"); | |||
} | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append(sqlUtil.updateSet(set.keySet())); | |||
sql.append(sqlUtil.whereByParam(param.keySet())); | |||
applySQL(context, sql, set, param); | |||
} | |||
private void deleteResolve(DynamicContext context) { | |||
Map<String, Object> param = (Map) context.getBindings().get("_parameter"); | |||
if (param.size() == 0) { | |||
throw new ABException("至少有一个查询条件"); | |||
} | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append(sqlUtil.deleteFrom()); | |||
sql.append(sqlUtil.whereByParam(param.keySet())); | |||
applySQL(context, sql, param); | |||
} | |||
private void insertResolve(DynamicContext context) { | |||
Object _parameter = context.getBindings().get("_parameter"); | |||
Map<String, Object> param; | |||
if (_parameter instanceof BasePO) { | |||
// param = new POUtil(classPO).getParamWriteNotNull(_parameter); | |||
param = ((BasePO)_parameter)._getProxy().getSetList(); | |||
} else { | |||
param = (Map) _parameter; | |||
} | |||
// Map<String, Object> param = (Map) paramObj; | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append(sqlUtil.insert(param.keySet())); | |||
applySQL(context, sql, param); | |||
} | |||
/** | |||
* 包装器模式解析 | |||
* | |||
* @param context | |||
* @return | |||
*/ | |||
public boolean applyWrapper(DynamicContext context) { | |||
log.info("SqlNodeWrapper apply"); | |||
BaseWrapper w = null; | |||
switch (option) { | |||
case "selectWrapper": | |||
w = selectWrapper(context, false); | |||
break; | |||
case "selectOneWrapper": | |||
w = selectWrapper(context, true); | |||
break; | |||
case "updateWrapper": | |||
w = updateWrapper(context); | |||
checkWhereWrapper(w); | |||
break; | |||
case "deleteWrapper": | |||
w = deleteWrapper(context); | |||
checkWhereWrapper(w); | |||
break; | |||
case "select": | |||
// w = deleteWrapper(context); | |||
//checkWhereWrapper(w); | |||
break; | |||
default: | |||
throw new ABException("功能 " + option + " 未实现"); | |||
} | |||
log.info(w.getSQL().toString()); | |||
log.info(w.getSQLLimit().toString()); | |||
log.info(String.valueOf(w.getParam())); | |||
//配置当前查询语句 | |||
context.appendSql(w.getSQL().toString()); | |||
context.appendSql(w.getSQLLimit().toString()); | |||
//配置当前查询参数 | |||
w.getParam().forEach((k, v) -> context.bind(k, v)); | |||
return true; | |||
} | |||
private void checkWhereWrapper(BaseWrapper w) { | |||
if (!WrapperUtil.hasWhere(w)) { | |||
throw new ABException("必须有where条件"); | |||
} | |||
} | |||
/** | |||
* 查询解析器 | |||
* | |||
* @param context | |||
* @return | |||
*/ | |||
private BaseWrapper selectWrapper(DynamicContext context, boolean isone) { | |||
Object fn = context.getBindings().get("_parameter"); | |||
BaseWrapper w = new Wrapper(classPO); | |||
BaseWrapper result = w.selectAllField().from(); | |||
//执行表达式 | |||
if (fn != null) { | |||
((Consumer<? super BaseWrapper>) fn).accept(result); | |||
} | |||
result.orderByDefault(); | |||
if (isone) { | |||
result.limit(1); | |||
} | |||
return w; | |||
} | |||
/** | |||
* 更新解析器 | |||
* | |||
* @param context | |||
* @return | |||
*/ | |||
private BaseWrapper updateWrapper(DynamicContext context) { | |||
Object _parameter = context.getBindings().get("_parameter"); | |||
Object fn; | |||
Map<String, Object> paramUpdateSet; | |||
if (_parameter instanceof UpdateParam) { | |||
UpdateParam up = (UpdateParam) _parameter; | |||
fn = up.getWhereData(); | |||
paramUpdateSet = up.getSetData(); | |||
} else { | |||
//获取update的set参数,支持BasePO实体和map | |||
MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) _parameter; | |||
Object obj = paramMap.get("param1"); | |||
if (obj instanceof Map) { | |||
paramUpdateSet = (Map<String, Object>) obj; | |||
} else if (obj instanceof BasePO) { | |||
paramUpdateSet = ((BasePO) obj)._getProxy().getSetList(); | |||
// new POUtil(obj.getClass()).getParamWriteNotNull(obj); | |||
} else { | |||
throw new ABException("参数不合法"); | |||
} | |||
fn = paramMap.get("param2"); | |||
} | |||
BaseWrapper w = new Wrapper(classPO); | |||
BaseWrapper result = w.update(paramUpdateSet); | |||
log.info(String.valueOf(paramUpdateSet)); | |||
//执行表达式 | |||
if (fn != null) { | |||
((Consumer<? super BaseWrapper>) fn).accept(result); | |||
} | |||
return w; | |||
} | |||
/** | |||
* 删除解析器 | |||
* | |||
* @param context | |||
* @return | |||
*/ | |||
private BaseWrapper deleteWrapper(DynamicContext context) { | |||
Object fn = context.getBindings().get("_parameter"); | |||
BaseWrapper w = new Wrapper(classPO); | |||
BaseWrapper result = w.delete(); | |||
//执行表达式 | |||
if (fn != null) { | |||
((Consumer<? super BaseWrapper>) fn).accept(result); | |||
} | |||
return w; | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
package com.qmrz.mybatis.sql.sqlnode; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Data; | |||
import java.util.Map; | |||
@Data | |||
@AllArgsConstructor | |||
public class UpdateParam { | |||
private Map<String,Object> setData; | |||
private Object whereData; | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.qmrz.mybatis.sql.statement; | |||
import com.qmrz.mybatis.sql.BaseWrapper; | |||
import com.qmrz.mybatis.sql.ConditionCount; | |||
/** | |||
* sql: 无,只包装作用 | |||
*/ | |||
public class AndBlock extends BaseWrapper { | |||
/** | |||
* @param isConditionAnd | |||
* @param index 嵌套时,序号继承到新块 | |||
*/ | |||
public AndBlock(boolean isConditionAnd, ConditionCount index, Class<?> classPO) { | |||
super(0, 1, isConditionAnd ? 1 : 2, classPO); | |||
this.setConditionsCount(index); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
package com.qmrz.mybatis.sql.statement; | |||
import com.qmrz.exception.ABException; | |||
import com.qmrz.mybatis.sql.AbsWrapperData; | |||
import com.qmrz.mybatis.sql.ConditionGeneralValue; | |||
import lombok.Data; | |||
import java.util.LinkedHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* sql: linkStr a between #{a1} and #{a2} | |||
*/ | |||
@Data | |||
public class ConditionBetween extends AbsWrapperData { | |||
/** | |||
* 条件左则字段名 | |||
*/ | |||
private String fiedName; | |||
private List<ConditionGeneralValue> fieldValue; | |||
public ConditionBetween(int wrapperWhereStatus, int conditionWhereStatus, Class<?> classPO) { | |||
super(0, wrapperWhereStatus,conditionWhereStatus,classPO); | |||
} | |||
@Override | |||
public StringBuilder getSQL() { | |||
if (fieldValue.size() != 2) { | |||
throw new ABException("参数个数应该为2,目前是:" + fieldValue.size()); | |||
} | |||
return new StringBuilder() | |||
.append(this.getLinkStr()) | |||
.append(fiedName).append(" between ") | |||
.append("#{").append(fieldValue.get(0).getName()).append("}") | |||
.append(" and ") | |||
.append("#{").append(fieldValue.get(1).getName()).append("}"); | |||
} | |||
@Override | |||
public Map<String, Object> getParam() { | |||
Map<String, Object> param = new LinkedHashMap<>(); | |||
fieldValue.forEach(item->{ | |||
param.put(item.getName(), item.getValue()); | |||
}); | |||
return param; | |||
} | |||
@Override | |||
protected void renameByParamName() { | |||
this.renameByParamName(fieldValue); | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
package com.qmrz.mybatis.sql.statement; | |||
import com.qmrz.mybatis.sql.AbsWrapperData; | |||
import com.qmrz.mybatis.sql.ConditionGeneralValue; | |||
import lombok.Data; | |||
import java.util.LinkedHashMap; | |||
import java.util.Map; | |||
/** | |||
* sql: linkStr a=#{a} | |||
*/ | |||
@Data | |||
public class ConditionGeneral extends AbsWrapperData { | |||
/** | |||
* 条件左则字段名 | |||
*/ | |||
private String fiedName; | |||
/** | |||
* 条件右侧参数名,及参数值 | |||
*/ | |||
private ConditionGeneralValue fieldValue; | |||
private String condition; | |||
public ConditionGeneral(int wrapperWhereStatus, int conditionWhereStatus, Class<?> classPO) { | |||
super(0, wrapperWhereStatus, conditionWhereStatus, classPO); | |||
} | |||
/** | |||
* 格式 " and/or fieldname=#{paramname}" | |||
* | |||
* @return | |||
*/ | |||
@Override | |||
public StringBuilder getSQL() { | |||
return new StringBuilder() | |||
.append(this.getLinkStr()) | |||
.append(fiedName).append(condition) | |||
.append("#{").append(fieldValue.getName()).append("}"); | |||
} | |||
@Override | |||
public Map<String, Object> getParam() { | |||
Map<String, Object> param = new LinkedHashMap<>(); | |||
// if (fieldValue == null) { | |||
// return param; | |||
// } | |||
param.put(fieldValue.getName(), fieldValue.getValue()); | |||
return param; | |||
} | |||
@Override | |||
protected void renameByParamName() { | |||
this.renameByParamName(fieldValue); | |||
} | |||
} |
@@ -0,0 +1,56 @@ | |||
package com.qmrz.mybatis.sql.statement; | |||
import com.qmrz.mybatis.sql.AbsWrapperData; | |||
import com.qmrz.mybatis.sql.ConditionGeneralValue; | |||
import lombok.Data; | |||
import org.apache.commons.lang.StringUtils; | |||
import java.util.ArrayList; | |||
import java.util.LinkedHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* sql: linkStr a in(#{a}) | |||
*/ | |||
@Data | |||
public class ConditionIn extends AbsWrapperData { | |||
/** | |||
* 条件左则字段名 | |||
*/ | |||
private String fiedName; | |||
private List<ConditionGeneralValue> fieldValue; | |||
public ConditionIn(int wrapperWhereStatus, int conditionWhereStatus, Class<?> classPO) { | |||
super(0, wrapperWhereStatus,conditionWhereStatus,classPO); | |||
} | |||
@Override | |||
public StringBuilder getSQL() { | |||
List<String> list = new ArrayList<>(); | |||
fieldValue.forEach(item->list.add("#{"+item.getName()+"}")); | |||
StringBuilder sb= new StringBuilder() | |||
.append(this.getLinkStr()) | |||
.append(fiedName).append(" in (") | |||
.append(StringUtils.join(list.toArray(),",")) | |||
.append(")"); | |||
return sb; | |||
} | |||
@Override | |||
public Map<String, Object> getParam() { | |||
Map<String, Object> param = new LinkedHashMap<>(); | |||
fieldValue.forEach(item->{ | |||
param.put(item.getName(), item.getValue()); | |||
}); | |||
return param; | |||
} | |||
@Override | |||
protected void renameByParamName() { | |||
this.renameByParamName(fieldValue); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
package com.qmrz.mybatis.sql.statement; | |||
import com.qmrz.mybatis.sql.AbsWrapperData; | |||
import com.qmrz.mybatis.sql.ConditionGeneralValue; | |||
import lombok.Data; | |||
import java.util.LinkedHashMap; | |||
import java.util.Map; | |||
/** | |||
* sql: name like concat('%',#{name},'%') | |||
*/ | |||
@Data | |||
public class ConditionLike extends AbsWrapperData { | |||
/** | |||
* 条件左则字段名 | |||
*/ | |||
private String fiedName; | |||
/** | |||
* 条件右侧参数名,及参数值 | |||
*/ | |||
private ConditionGeneralValue fieldValue; | |||
public ConditionLike(int wrapperWhereStatus, int conditionWhereStatus, Class<?> classPO) { | |||
super(0, wrapperWhereStatus, conditionWhereStatus, classPO); | |||
} | |||
/** | |||
* 格式 " and/or fieldname=#{paramname}" | |||
* | |||
* @return | |||
*/ | |||
@Override | |||
public StringBuilder getSQL() { | |||
return new StringBuilder() | |||
.append(this.getLinkStr()) | |||
.append(fiedName).append(" like") | |||
.append(" concat('%',#{").append(fieldValue.getName()).append("},'%')"); | |||
} | |||
@Override | |||
public Map<String, Object> getParam() { | |||
Map<String, Object> param = new LinkedHashMap<>(); | |||
if (fieldValue == null) { | |||
return param; | |||
} | |||
param.put(fieldValue.getName(), fieldValue.getValue()); | |||
return param; | |||
} | |||
@Override | |||
protected void renameByParamName() { | |||
this.renameByParamName(fieldValue); | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
package com.qmrz.mybatis.sql.statement; | |||
import com.qmrz.mybatis.sql.AbsWrapperData; | |||
import lombok.Data; | |||
import java.util.Map; | |||
/** | |||
* sql: detele from tableName | |||
*/ | |||
@Data | |||
public class DeleteFrom extends AbsWrapperData { | |||
private StringBuilder sql; | |||
public DeleteFrom(Class<?> classPO) { | |||
super(40, 0, 0, classPO); | |||
load(); | |||
} | |||
private void load(){ | |||
this.sql = sqlUtil.deleteFrom(); | |||
} | |||
@Override | |||
public StringBuilder getSQL() { | |||
return new StringBuilder().append(this.sql); | |||
} | |||
@Override | |||
public Map<String, Object> getParam() { | |||
return null; | |||
} | |||
@Override | |||
protected void renameByParamName() { | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
package com.qmrz.mybatis.sql.statement; | |||
import com.qmrz.mybatis.sql.AbsWrapperData; | |||
import lombok.Data; | |||
import java.util.Map; | |||
/** | |||
* sql: from tableName | |||
*/ | |||
@Data | |||
public class FromTable extends AbsWrapperData { | |||
private StringBuilder sql; | |||
public FromTable( Class<?> classPO) { | |||
super(2, 0, 0, classPO); | |||
load(); | |||
} | |||
private void load(){ | |||
this.sql = sqlUtil.fromTable(); | |||
} | |||
@Override | |||
public StringBuilder getSQL() { | |||
return new StringBuilder().append(this.sql); | |||
} | |||
@Override | |||
public Map<String, Object> getParam() { | |||
return null; | |||
} | |||
@Override | |||
protected void renameByParamName() { | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
package com.qmrz.mybatis.sql.statement; | |||
import com.qmrz.mybatis.sql.AbsWrapperData; | |||
import lombok.Data; | |||
import java.util.Map; | |||
/** | |||
* sql: from tableName | |||
*/ | |||
@Data | |||
public class Limit extends AbsWrapperData { | |||
private Integer limit1; | |||
private Integer limit2; | |||
public Limit(Class<?> classPO, Integer limit1, Integer limit2) { | |||
super(6, 0, 0, classPO); | |||
this.limit1 = limit1; | |||
this.limit2 = limit2; | |||
load(); | |||
} | |||
private void load() { | |||
} | |||
@Override | |||
public StringBuilder getSQL() { | |||
StringBuilder sql = new StringBuilder(); | |||
if (limit1 != null && limit2 != null) { | |||
sql.append(" limit " + limit1 + "," + limit2); | |||
}else if (limit1 != null) { | |||
sql.append(" limit " + limit1); | |||
} | |||
return sql; | |||
} | |||
@Override | |||
public StringBuilder getSQLLimit() { | |||
StringBuilder sql = new StringBuilder(); | |||
if (limit1 != null && limit2 != null) { | |||
sql.append(" limit " + limit1 + "," + limit2); | |||
}else if (limit1 != null) { | |||
sql.append(" limit " + limit1); | |||
} | |||
return sql; | |||
} | |||
@Override | |||
public Map<String, Object> getParam() { | |||
return null; | |||
} | |||
@Override | |||
protected void renameByParamName() { | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.qmrz.mybatis.sql.statement; | |||
import com.qmrz.mybatis.sql.BaseWrapper; | |||
import com.qmrz.mybatis.sql.ConditionCount; | |||
/** | |||
* sql: 无,只包装作用 | |||
*/ | |||
public class OrBlock extends BaseWrapper { | |||
/** | |||
* @param isConditionAnd | |||
* @param index 嵌套时,序号继承到新块 | |||
*/ | |||
public OrBlock(boolean isConditionAnd, ConditionCount index, Class<?> classPO) { | |||
super(0, 2, isConditionAnd ? 1 : 2, classPO); | |||
this.setConditionsCount(index); | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
package com.qmrz.mybatis.sql.statement; | |||
import com.qmrz.mybatis.sql.AbsWrapperData; | |||
import lombok.Data; | |||
import java.util.Map; | |||
/** | |||
* sql: order by ... | |||
*/ | |||
@Data | |||
public class OrderByDefault extends AbsWrapperData { | |||
public OrderByDefault(Class<?> classPO) { | |||
super(3, 0, 0, classPO); | |||
load(); | |||
} | |||
private void load(){ | |||
} | |||
@Override | |||
public StringBuilder getSQL() { | |||
return new StringBuilder().append(sqlUtil.orderByDefault()); | |||
} | |||
@Override | |||
public Map<String, Object> getParam() { | |||
return null; | |||
} | |||
@Override | |||
protected void renameByParamName() { | |||
} | |||
} |