codeGenerator
- 框架研发的程序员们往往提供业务快速开发的脚手架,内置各种工具、技术配置集成,公司自主研发底层框架、以便其他业务部门实现快速开发,无需项目的搭建。其中代码生成器也是因需求自然而生。
- 提到代码生成器,鼎鼎大名的mybatis-generator也是最早接触的,但仅仅生成pojo、业务、持久层还是mapper文件
varCode_1.0
varCode:自己java代码实现的生成pojo、service、serviceImpl、dao、daoImpl、controller、js、html(js、html模板还未开发完)的前后端一套代码构建工具,无需修改、即刻运行的简单web项目,具体集成的功能下文描述。
设计思路
底层数据库操作——>元数据DatabaseMetaData获取相关表信息(转换为需要生成模板的对象数据)——>模板引擎构建代码生成
从配置项说起
<?xml version="1.0" encoding="UTF-8"?>
<config>
<!--“/”表示存放于当前项目结构中-->
<baseDir>/</baseDir>
<!--生成的包名结构-->
<basePackage>com.lin.bdp</basePackage>
<dbName>test</dbName>
<dbUserName>root</dbUserName>
<dbPassword></dbPassword>
<!--“*”代表所有,多个表名用逗号,分割-->
<tableName>f_user</tableName>
<dbDriver>com.mysql.jdbc.Driver</dbDriver>
<bdUrl>jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC</bdUrl>
</config>
配置项的信息往往取决于功能展示的方式和获取信息的途径:
baseDir:配置物理地址生成代码的路径 ,“/”友善的实现直接存放当前项目
basePackage:项目包名的结构
数据库信息一套
tableName:生成的代码表名,多个“,“分割,”*”友善的实现所有表
提供xml解析工具类(自己用的digester,准备改成properties文件由spring env加载)
需要获取的数据库信息对象
只列举实体类和字段
public class TableInfo {
private String tableName;
private String originTableName;//数据库带_命名方式的表名
private List<ColumnInfo> columnInfoList;
private ColumnInfo primaryKeyColumn;//主键字段
private Boolean autoIncrement;/主键增长方式
}
public class ColumnInfo {
private String columnName;
private String originColumnName;
private String columnType;
private String remarks;
}
字符串工具类实现:
1、驼峰式命名与数据库命名转换
2、实体类、字段、get方法需要用到的首字母大小写转换
3、数据库字段类型和java属性类型转换
package com.lin.util;
public class StringDBUtil {
/**
* 数据库_命名转化为驼峰式命名
* @param tableOrColumnName
* @return
*/
public static String dbNameHandle(String tableOrColumnName){
if (!tableOrColumnName.contains("_")){
return tableOrColumnName;
}
tableOrColumnName = tableOrColumnName.replaceAll("^\\w_","");
String old = String.valueOf(tableOrColumnName.charAt(tableOrColumnName.indexOf("_")+1));
tableOrColumnName = tableOrColumnName.replace("_"+old,old.toUpperCase());
return dbNameHandle(tableOrColumnName);
}
/**
* 数据库_命名转化为驼峰式命名,首字母大写
* @param name
* @return
*/
public static String initialCaps(String name){
String temp = dbNameHandle(name);
return String.valueOf(temp.charAt(0)).toUpperCase()+temp.substring(1,temp.length());
}
/**
* 数据库字段类型转换
* @return
*/
public static String type2Property(String type){
if(type.matches("VARCHAR|CHAR|TEXT")){
return "String";
}
if(type.indexOf("BLOB")!=-1){
return "byte[]";
}
if(type.matches("DATE|TIME|DATETIME|TIMESTAMP|YEAR")){
return "Date";
}
if(type.matches("INT|TINYINT|SMALLINT|BIGINT|DECIMAL")){
return "Integer";
}
return type;
}
}
元数据构建需要的数据库信息对象
由于方便调用做成工具类,直接使用的原生jdbc获取元数据信息:
1、获取所有表名:
rs = metaData.getTables(null, null, "%", new String[]{"TABLE"});
2、获取字段信息:
rs = metaData.getColumns(null, "%", tableName, "%");
3、获取主键字段名:
pks = metaData.getPrimaryKeys(config.getDbName(), "%", tableName);
package com.lin.util;
import java.sql.*;
import java.util.*;
public class DBUtil {
/**
* 获取所有表名
*
* @param config
*/
public static List<String> getTableNames(Config config) {
Connection cnn = getConn(config);
ResultSet rs = null;
List<String> tableNames = new ArrayList<>();
try {
DatabaseMetaData metaData = cnn.getMetaData();
rs = metaData.getTables(null, null, "%", new String[]{"TABLE"});
while (rs.next()) {
String tableName = rs.getString("TABLE_NAME");
if (tableName.equals("schema_version")) {
continue;
}
tableNames.add(tableName);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(cnn, null, rs);
}
return tableNames;
}
/**
* 获取数据库连接
*
* @param config
* @return
*/
public static Connection getConn(Config config) {
Connection conn = null;
try {
Class.forName(config.getDbDriver());
conn = DriverManager.getConnection(config.getBdUrl(), config.getDbUserName(), config.getDbPassword());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 获取table元信息
*/
public static List<TableInfo> getTableInfos(Config config) {
List<String> tableNamesList = new ArrayList<>();
if ("*".equals(config.getTableName())) {
tableNamesList = getTableNames(config);
} else {
tableNamesList.addAll(Arrays.asList(config.getTableName().split(",")));
}
List<TableInfo> tableInfoList = new ArrayList<>();
Connection cnn = getConn(config);
ResultSet rs = null;
DatabaseMetaData metaData;
try {
for (String tableName : tableNamesList) {
TableInfo tableInfo = new TableInfo();
List<ColumnInfo> columnInfoList = new ArrayList<>();
tableInfo.setTableName(StringDBUtil.initialCaps(tableName));
tableInfo.setOriginTableName(tableName);
metaData = cnn.getMetaData();
//获取主键字段名
ResultSet pks = metaData.getPrimaryKeys(config.getDbName(), "%", tableName);
String pkName = null;
while (pks.next()) {
pkName = pks.getString("COLUMN_NAME");
}
//获取字段信息
rs = metaData.getColumns(null, "%", tableName, "%");
while (rs.next()) {
ColumnInfo column = new ColumnInfo();
String columnName = rs.getString("COLUMN_NAME");
column.setColumnName(StringDBUtil.dbNameHandle(columnName));
column.setOriginColumnName(columnName);
column.setColumnType(StringDBUtil.type2Property(rs.getString("TYPE_NAME")));
column.setRemarks(rs.getString("REMARKS"));
columnInfoList.add(column);
if(columnName.equals(pkName)){
tableInfo.setPrimaryKeyColumn(column);
if(rs.getString("IS_AUTOINCREMENT").equals("YES")){
tableInfo.setAutoIncrement(true);
}else{
tableInfo.setAutoIncrement(false);}
}
}
tableInfo.setColumnInfoList(columnInfoList);
tableInfoList.add(tableInfo);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
close(cnn, null, rs);
}
return tableInfoList;
}
/**
* 关闭资源
*/
public static void close(Connection conn, PreparedStatement ps, ResultSet rs) {
if (rs != conn) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != ps) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
System.out.println("数据库连接关闭失败!");
}
}
}
}
}
}
}
}
构建生成代码的工具类
直接上代码
package com.lin.util;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
public class GenerateUtil {
public static final String FTL_TEMPLATE_PATH = "/webapp/WEB-INF/ftl";
public static final String ROOT_PATH = System.getProperty("user.dir") + "/src/main";
public static final List<String> FTL_TYPES = new ArrayList<>();
public static final List<String> PACKAGE_TO__POJO = new ArrayList<>();
static {
PACKAGE_TO__POJO.addAll(Arrays.asList(new String[]{"pageDesc","response"}));
FTL_TYPES.addAll(Arrays.asList(new String[]{"pojo","pageDesc","service","controller","response",
"serviceImpl","dao","daoImpl","js","jsp"}));
}
/**
* 生成单表的单个模板代码
*/
public static void generateBase(TableInfo tableInfo,String ftlType){
Config config = (Config) Xml2ConfigBean.getBean("config.xml");
Map<String,Object> dataMap = new HashMap<>();
dataMap.put("config",config);
dataMap.put("tableInfo",tableInfo);
Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
try {
cfg.setDirectoryForTemplateLoading(new File(ROOT_PATH + FTL_TEMPLATE_PATH));
cfg.setObjectWrapper(new DefaultObjectWrapper(Configuration.VERSION_2_3_23));
Template temp = cfg.getTemplate(ftlType + ".ftl");
String sufixName = ".java";
String filePath = ROOT_PATH + "/java/" + (config.getBasePackage()).replace(".",File.separator) + File.separator + (PACKAGE_TO__POJO.contains(ftlType)?"pojo":ftlType);
if(ftlType.equals("js")){
sufixName = ".js";
filePath = ROOT_PATH + "/webapp/assets/" + tableInfo.getTableName() + StringDBUtil.initialCaps(ftlType);
}
if(ftlType.equals("jsp")){
sufixName = ".jsp";
filePath = ROOT_PATH + "/webapp/WEB-INF/jsp/" + tableInfo.getTableName() + StringDBUtil.initialCaps(ftlType);
}
if(!"/".equals(config.getBaseDir())){
filePath = config.getBaseDir() + File.separator + ftlType;
}
String fileName = tableInfo.getTableName()+ StringDBUtil.initialCaps(ftlType) +sufixName;
if(ftlType.equals("pojo")){
fileName = tableInfo.getTableName()+ sufixName;
}
if(PACKAGE_TO__POJO.contains(ftlType)){
fileName = StringDBUtil.initialCaps(ftlType) + sufixName;
}
File file = new File(filePath);
if(!file.exists()){
file.mkdirs();
}
File generateFile = new File(filePath + File.separator + fileName);
FileWriter fw = new FileWriter(generateFile);
BufferedWriter bw = new BufferedWriter(fw);
temp.process(dataMap, bw);
bw.flush();
fw.close();
System.out.println("生成 " + fileName +" --> " + generateFile.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
}
/**
* 生成配置项表名的一套代码
*/
public static void generate(Config config){
if (null == config){
config = (Config) Xml2ConfigBean.getBean("config.xml");
}
List<TableInfo> tableInfoList = DBUtil.getTableInfos(config);
for (TableInfo tableInfo:tableInfoList) {
for (String ftlType:FTL_TYPES){
generateBase(tableInfo,ftlType);
}
}
}
}
好了准备工作已经完成,生成的工类也写完了,那么如何定制需要的代码模板,譬如mybatis的持久层mapper文件,当我需要集成其他持久层框架,也能随时替换,再者加上上文说生成controller访问层、js、静态页面html,varCode实现的json格式响应类、pageDesc分页类、持久层动态sql、自己定义的业务通用方法,等等生成的代码自动放入项目路径(类文件存放于java包路径、js、jsp存放于webapp路径)、编译、执行,直接就能使用的。
从代码可以看出
(截图亦为freemarker模板的使用——>构建map存放对象信息——>获取模板——>渲染、流输出文件)
上篇http服务端、客户端的简单实现文章也说了,用freemarker模板引擎,个性化实现你的ftl模板文件,有多少需求、生成多少代码,模板编写的通用,那就是一次编写、处处收益!(哈哈,差点携程java的跨平台口号:一次编译,处处运行!)
freemarker简介
语法:类似el表达式
标签以“#”开头,“@”为自定义标签语法
结合模板中使用的列举以下常用标签:
1、${}
取模型中的值,就当el取值表达式一样,“.”和“[]”获取对象属性和集合元素
2、<#if></#if>
<#if columnInfo.remarks??>
/**
*columnInfo.remarks
*/
</#if>
pojo.ftl模板中获取数据库字段comment就当作属性的注释,columnInfo.remarks??为true注释显示(??后面解释),支持<#else if><#else>
3、<#list></#list>
<#list tableInfo.columnInfoList as columnInfo>
public ${columnInfo.columnType} get${columnInfo.columnName?cap_first}() {
return ${columnInfo.columnName};
}
</#list>
pojo.ftl模板中定义get方法(定义属性、set方法也是),循环表的所有列
相当于java代码for(Object obj:list)
el表达式<c:forEach items="${list}" var="obj">
list循环中提供<#break>结束循环,未提供continue,可结合<#if>实现,获取下标值 as 后的对象+_index
4、<#assign>
声名变量,类似var
来看个包含上面三个标签的综合体
<#assign field_count = "">
<#list tableInfo.columnInfoList as columnInfo>
<#if tableInfo.autoIncrement && (columnInfo.columnName!=tableInfo.primaryKeyColumn.columnName)>
<#assign field_count = field_count + columnInfo?is_last?string("?","?, ")>
</#if>
</#list>
daoimpl.ftl代码中声明空字符串拼接新增sql语句,循环遍历所有字段、如果主键自增长,则插入的主键值和占位符?,就少拼接一个(代码中也实现了,非自增长,生成可供使用的序列值)使用中声明两次递归拼接需要的变量值
5、??以及?、!
以上标签已经够用了,功能更强的自定义标签可以实现TemplateDirectiveModel接口,类似于jstl库自定义标签继承的SimpleTagSupport
下面来介绍常用的函数以及上文??以及?、!含义:
1、??是否为null判断,freemarker取值本身无法识别null(报错)
2、?引用函数
比如:<#assign db_fields = db_fields + columnInfo.originColumnName + columnInfo?is_last?string("",", ")>集合下表是否最后一个
${tableInfo.tableName?uncap_first}首字母大写
${tableInfo.primaryKeyColumn.columnName?cap_first}首字母小写
?后面即是引用的函数名,columnInfo?is_last?string("",", ")第二个?是三目运算符标志,后面不支持:来表示是否的取值,而是用string函数分别取括号前后两个参数
3、!后面接如果为空的默认值 相当于Oracle的decode、nvl
6、运算符
+的字符串连接,数学运算符(求余、取模等)、逻辑运算符、比较运算符(><相当于gt lt,==相当于e)和其他语法大体适用
构建ftl模板文件
有了freemarker模板引擎的简单了解,生成我们需要的模板文件就不是难事了,
存放于WEB-INF下的模板(路径可配)
dao、service大体没啥难度,
持久层我实现的是jdbc,支持日常curd方法、按字段联合查询、模糊查询、分页查询、动态sql;
controller层自定义response响应对象、继承swagger2 在线api文档(方便调试接口)、字段唯一性校验
代码较多,贴下controller模板:
@Controller
@Api(value = "${tableInfo.tableName} Controller",tags={"${tableInfo.tableName}操作接口Api"})
@RequestMapping("/${tableInfo.tableName?uncap_first}")
public class ${tableInfo.tableName}Controller {
@Autowired
private ${tableInfo.tableName}Service ${tableInfo.tableName}Service;
public static final List<String> UNIQUE_FIELDS = new ArrayList<>();
static{
UNIQUE_FIELDS.addAll(Arrays.asList(new String[]{}));//数组内添加需要唯一校验的字段
}
@RequestMapping(value="/listPage",method = RequestMethod.GET)
@ResponseBody
@ApiOperation(value="获取${tableInfo.tableName?uncap_first}列表",notes="响应成功:0,失败:-1")
@ApiImplicitParam(name = "pageDesc", value = "分页对象", required = true, dataType = "PageDesc")
public Response listAll(PageDesc pageDesc){
List<${tableInfo.tableName}> ${tableInfo.tableName?uncap_first}List = ${tableInfo.tableName}Service.listAll(pageDesc);
return Response.ok(${tableInfo.tableName?uncap_first}List);
}
@RequestMapping(value="/update",method = RequestMethod.POST)
@ResponseBody
@ApiOperation(value="新增、更新对象",notes="响应成功:0,失败:-1")
@ApiImplicitParam(name = "${tableInfo.tableName?uncap_first}", value = "${tableInfo.tableName?uncap_first}对象", required = true, dataType = "${tableInfo.tableName}")
public Response update${tableInfo.tableName}(${tableInfo.tableName} ${tableInfo.tableName?uncap_first}){
${tableInfo.primaryKeyColumn.columnType} ${tableInfo.primaryKeyColumn.columnName} = ${tableInfo.tableName?uncap_first}.get${tableInfo.primaryKeyColumn.columnName?cap_first}();
//更新
if(null != ${tableInfo.primaryKeyColumn.columnName}){
if(!UNIQUE_FIELDS.isEmpty()){
for(String field:UNIQUE_FIELDS){
Map<String,Object> map = new HashMap<>();
map.put(field,${tableInfo.tableName?uncap_first}.get(field));
List<${tableInfo.tableName}> ${tableInfo.tableName?uncap_first}List = ${tableInfo.tableName}Service.get${tableInfo.tableName}List(map);
if(null == ${tableInfo.tableName?uncap_first}List||${tableInfo.tableName?uncap_first}List.get(0).get${tableInfo.primaryKeyColumn.columnName?cap_first}().equals(${tableInfo.primaryKeyColumn.columnName})){
${tableInfo.tableName}Service.update${tableInfo.tableName}(${tableInfo.tableName?uncap_first},"UPDATE");
return Response.ok();
}else{
return Response.error(field+":"+${tableInfo.tableName?uncap_first}.get(field)+"已存在!");
}
}
}
${tableInfo.tableName}Service.update${tableInfo.tableName}(${tableInfo.tableName?uncap_first},"UPDATE");
return Response.ok();
//新增
}else{
if(!UNIQUE_FIELDS.isEmpty()){
for(String field:UNIQUE_FIELDS){
Map<String,Object> map = new HashMap<>();
map.put(field,${tableInfo.tableName?uncap_first}.get(field));
List<${tableInfo.tableName}> ${tableInfo.tableName?uncap_first}List = ${tableInfo.tableName}Service.get${tableInfo.tableName}List(map);
if(null == ${tableInfo.tableName?uncap_first}List){
${tableInfo.tableName}Service.update${tableInfo.tableName}(${tableInfo.tableName?uncap_first},"ADD");
return Response.ok();
}else{
return Response.error(field+":"+${tableInfo.tableName?uncap_first}.get(field)+"已存在!");
}
}
}
${tableInfo.tableName}Service.update${tableInfo.tableName}(${tableInfo.tableName?uncap_first},"ADD");
return Response.ok();
}
}
@RequestMapping(value="/{${tableInfo.primaryKeyColumn.columnName}}",method = RequestMethod.GET)
@ResponseBody
@ApiOperation(value="按主键${tableInfo.primaryKeyColumn.columnName}查询${tableInfo.tableName?uncap_first}",notes="响应成功:0,失败:-1")
@ApiImplicitParam(name = "${tableInfo.primaryKeyColumn.columnName}", value = "${tableInfo.primaryKeyColumn.columnName}", required = true, dataType = "${tableInfo.primaryKeyColumn.columnType}")
public Response get${tableInfo.tableName}By${tableInfo.primaryKeyColumn.columnName?cap_first}(@PathVariable ${tableInfo.primaryKeyColumn.columnType} ${tableInfo.primaryKeyColumn.columnName}){
${tableInfo.tableName} ${tableInfo.tableName?uncap_first} = ${tableInfo.tableName}Service.get${tableInfo.tableName}By${tableInfo.primaryKeyColumn.columnName?cap_first}(${tableInfo.primaryKeyColumn.columnName});
return Response.ok(${tableInfo.tableName?uncap_first});
}
@RequestMapping(value="/delete/{${tableInfo.primaryKeyColumn.columnName}}",method = RequestMethod.GET)
@ResponseBody
@ApiOperation(value="根据${tableInfo.primaryKeyColumn.columnName}删除${tableInfo.tableName?uncap_first}",notes="响应成功:0,失败:-1")
@ApiImplicitParam(name = "${tableInfo.primaryKeyColumn.columnName}", value = "${tableInfo.primaryKeyColumn.columnName}", required = true, dataType = "${tableInfo.primaryKeyColumn.columnType}")
public Response delete${tableInfo.tableName}By${tableInfo.primaryKeyColumn.columnName?cap_first}(@PathVariable ${tableInfo.primaryKeyColumn.columnType} ${tableInfo.primaryKeyColumn.columnName}){
${tableInfo.tableName} ${tableInfo.tableName?uncap_first} = ${tableInfo.tableName}Service.delete${tableInfo.tableName}By${tableInfo.primaryKeyColumn.columnName?cap_first}(${tableInfo.primaryKeyColumn.columnName});
return Response.ok(${tableInfo.tableName?uncap_first});
}
@RequestMapping(value="/list",method = RequestMethod.POST)
@ResponseBody
@ApiOperation(value="按条件查询${tableInfo.tableName?uncap_first}集合",notes="响应成功:0,失败:-1")
@ApiImplicitParams({
@ApiImplicitParam(name = "map", value = "key值${tableInfo.tableName?uncap_first}属性", required = true, dataType = "Map<String,Object>"),
@ApiImplicitParam(name = "pageDesc", value = "pageDesc", required = false, dataType = "PageDesc")
})
public Response get${tableInfo.tableName}List(Map<String,Object> map,PageDesc pageDesc){
List<${tableInfo.tableName}> ${tableInfo.tableName?uncap_first}List = ${tableInfo.tableName}Service.get${tableInfo.tableName}List(map,pageDesc);
return Response.ok(${tableInfo.tableName?uncap_first}List);
}
@RequestMapping(value="/like",method = RequestMethod.POST)
@ResponseBody
@ApiOperation(value="按条件模糊查询${tableInfo.tableName?uncap_first}集合",notes="响应成功:0,失败:-1")
@ApiImplicitParams({
@ApiImplicitParam(name = "map", value = "key值${tableInfo.tableName?uncap_first}属性", required = true, dataType = "Map<String,Object>"),
@ApiImplicitParam(name = "pageDesc", value = "pageDesc", required = false, dataType = "PageDesc")
})
public Response getListLike(Map<String,Object> map,PageDesc pageDesc){
List<${tableInfo.tableName}> ${tableInfo.tableName?uncap_first}List = ${tableInfo.tableName}Service.getListLike(map,pageDesc);
return Response.ok(${tableInfo.tableName?uncap_first}List);
}
}
看下测试效果:
配置如下
主程序入口:(config传null,表示解析本地的xml文件,后面改为页面表单配置,提交传入config配置参数)
package com.lin;
import com.lin.util.GenerateUtil;
import org.springframework.beans.factory.annotation.Autowired;
public class TestMain {
@Autowired
public static void main(String[] args) {
GenerateUtil.generate(null);
}
}
打开一个controller和daoImpl看看效果吧:
UserController
@Controller
@Api(value = "User Controller",tags={"User操作接口Api"})
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService UserService;
public static final List<String> UNIQUE_FIELDS = new ArrayList<>();
static{
UNIQUE_FIELDS.addAll(Arrays.asList(new String[]{}));//数组内添加需要唯一校验的字段
}
@RequestMapping(value="/listPage",method = RequestMethod.GET)
@ResponseBody
@ApiOperation(value="获取user列表",notes="响应成功:0,失败:-1")
@ApiImplicitParam(name = "pageDesc", value = "分页对象", required = true, dataType = "PageDesc")
public Response listAll(PageDesc pageDesc){
List<User> userList = UserService.listAll(pageDesc);
return Response.ok(userList);
}
@RequestMapping(value="/update",method = RequestMethod.POST)
@ResponseBody
@ApiOperation(value="新增、更新对象",notes="响应成功:0,失败:-1")
@ApiImplicitParam(name = "user", value = "user对象", required = true, dataType = "User")
public Response updateUser(User user){
Integer id = user.getId();
//更新
if(null != id){
if(!UNIQUE_FIELDS.isEmpty()){
for(String field:UNIQUE_FIELDS){
Map<String,Object> map = new HashMap<>();
map.put(field,user.get(field));
List<User> userList = UserService.getUserList(map);
if(null == userList||userList.get(0).getId().equals(id)){
UserService.updateUser(user,"UPDATE");
return Response.ok();
}else{
return Response.error(field+":"+user.get(field)+"已存在!");
}
}
}
UserService.updateUser(user,"UPDATE");
return Response.ok();
//新增
}else{
if(!UNIQUE_FIELDS.isEmpty()){
for(String field:UNIQUE_FIELDS){
Map<String,Object> map = new HashMap<>();
map.put(field,user.get(field));
List<User> userList = UserService.getUserList(map);
if(null == userList){
UserService.updateUser(user,"ADD");
return Response.ok();
}else{
return Response.error(field+":"+user.get(field)+"已存在!");
}
}
}
UserService.updateUser(user,"ADD");
return Response.ok();
}
}
@RequestMapping(value="/{id}",method = RequestMethod.GET)
@ResponseBody
@ApiOperation(value="按主键id查询user",notes="响应成功:0,失败:-1")
@ApiImplicitParam(name = "id", value = "id", required = true, dataType = "Integer")
public Response getUserById(@PathVariable Integer id){
User user = UserService.getUserById(id);
return Response.ok(user);
}
@RequestMapping(value="/delete/{id}",method = RequestMethod.GET)
@ResponseBody
@ApiOperation(value="根据id删除user",notes="响应成功:0,失败:-1")
@ApiImplicitParam(name = "id", value = "id", required = true, dataType = "Integer")
public Response deleteUserById(@PathVariable Integer id){
User user = UserService.deleteUserById(id);
return Response.ok(user);
}
@RequestMapping(value="/list",method = RequestMethod.POST)
@ResponseBody
@ApiOperation(value="按条件查询user集合",notes="响应成功:0,失败:-1")
@ApiImplicitParams({
@ApiImplicitParam(name = "map", value = "key值user属性", required = true, dataType = "Map<String,Object>"),
@ApiImplicitParam(name = "pageDesc", value = "pageDesc", required = false, dataType = "PageDesc")
})
public Response getUserList(Map<String,Object> map,PageDesc pageDesc){
List<User> userList = UserService.getUserList(map,pageDesc);
return Response.ok(userList);
}
@RequestMapping(value="/like",method = RequestMethod.POST)
@ResponseBody
@ApiOperation(value="按条件模糊查询user集合",notes="响应成功:0,失败:-1")
@ApiImplicitParams({
@ApiImplicitParam(name = "map", value = "key值user属性", required = true, dataType = "Map<String,Object>"),
@ApiImplicitParam(name = "pageDesc", value = "pageDesc", required = false, dataType = "PageDesc")
})
public Response getListLike(Map<String,Object> map,PageDesc pageDesc){
List<User> userList = UserService.getListLike(map,pageDesc);
return Response.ok(userList);
}
}
UserDaoImpl
@Repository
public class UserDaoImpl implements UserDao {
private static final Map<String,Object> FIELD_MAP = new HashMap<>();
static{
FIELD_MAP.put("id","id");
FIELD_MAP.put("userName","userName");
FIELD_MAP.put("password","password");
FIELD_MAP.put("sex","sex");
}
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* @param pageDesc 分页对象
* @return 获取user列表
*/
@Override
public List<User> listAll(PageDesc pageDesc){
return getUserList(null,pageDesc);
}
/**
* @param user 新增(支持auto_increment插值)、更新对象
* @param type 操作类型
*/
@Override
public void updateUser(User user,String type){
Integer id = user.getId();
String sql = "INSERT INTO f_user(userName, password, sex) values(?, ?, ?)";
//更新
if(type.equals("UPDATE")){
deleteUserById(id);
jdbcTemplate.update(sql, new Object[]{user.getUserName(), user.getPassword(), user.getSex()});
//新增
}else{
jdbcTemplate.update(sql, new Object[]{user.getUserName(), user.getPassword(), user.getSex()});
}
}
/**
* @param id
* @return 按主键id查询user
*/
@Override
public User getUserById(Integer id){
String sql = "SELECT id, userName, password, sex FROM f_user WHERE id = ?";
RowMapper<User> rowMapper = new BeanPropertyRowMapper(User.class);
return jdbcTemplate.queryForObject(sql, rowMapper, id);
}
/**
* @param id
* @return 删除的user对象
*/
@Override
public User deleteUserById(Integer id){
User user = getUserById(id);
String sql = "DELETE FROM f_user WHERE id = ?";
jdbcTemplate.update(sql, id);
return user;
}
/**
* @param map key只能是FIELD_MAP中的值,即pojo属性名
* @param pageDesc 分页对象
* @return 按条件查询的user集合
*/
@Override
public List<User> getUserList(Map<String,Object> map,PageDesc pageDesc){
StringBuilder sql = new StringBuilder("SELECT id, userName, password, sex FROM f_user WHERE 1=1 ");
if(null != map){
for (String param:map.keySet()){
sql.append(" and " + FIELD_MAP.get(param) + " = ? ");
}
}
if(null != pageDesc){
sql.append(" LIMIT " + pageDesc.getRowStart() + "," + pageDesc.getRowEnd());
}
RowMapper<User> rowMapper = new BeanPropertyRowMapper(User.class);
return jdbcTemplate.query(sql.toString(), map.values().toArray(),rowMapper);
}
/**
* @param map key只能是FIELD_MAP中的值,即pojo属性名
* @return 按条件查询的user集合
*/
@Override
public List<User> getUserList(Map<String,Object> map){
return getUserList(map,null);
}
/**
* @param map key只能是FIELD_MAP中的值,即pojo属性名
* @param pageDesc 分页对象
* @return 模糊查询user集合
*/
@Override
public List<User> getListLike(Map<String,Object> map,PageDesc pageDesc){
StringBuilder sql = new StringBuilder("SELECT id, userName, password, sex FROM f_user WHERE 1=1 ");
if(null != map){
for (String param:map.keySet()){
sql.append(" and " + FIELD_MAP.get(param) + " LIKE CONCAT('%',?,'%') ");
}
}
if(null != pageDesc){
sql.append(" LIMIT " + pageDesc.getRowStart() + "," + pageDesc.getRowEnd());
}
RowMapper<User> rowMapper = new BeanPropertyRowMapper(User.class);
return jdbcTemplate.query(sql.toString(), map.values().toArray(),rowMapper);
}
/**
* @param map key只能是FIELD_MAP中的key值,即pojo属性名
* @return 模糊查询user集合
*/
@Override
public List<User> getListLike(Map<String,Object> map){
return getListLike(map,null);
}
}
启动项目(本身就是web项目),swagger2界面api:
测试直接可用
后期更新完善好(页面配置、mybatis、herbinate多元持久层)提供源码地址,谢谢!。