SpringBoot+MyBatis中自动根据@Table注解和@Column注解生成增删改查逻辑
习惯使用jpa操作对象的方式,现在用mybatis有点不习惯。
其实是懒得写SQL,增删改查那么简单的事情你帮我做了呗,mybatis:NO。
没办法,自己搞喽!
这里主要是实现了通过代码自动生成mybatis的增删改查语句,并注册到SqlSessionFactory中,并没有生成xml文件,不生成mapper文件。只是在项目启动的时候自动生成,配置到SqlSessionFactory中,下一次启动后自动根据model自动生成相关逻辑。所以不必担心表结构修改需要改一大堆文件。使用了此方法只需要改model文件就可以了。
注意:model必须添加@Table注解,对应的列也必须添加@Column注解(javax)。
思路:
在项目启动时mybatis默认配置运行结束后添加自定义配置
@Configuration
@AutoConfigureAfter(MybatisAutoConfiguration.class)
public class MyBatisTypeMapScannerConfig { private Logger log = Logger.getLogger(MyBatisTypeMapScannerConfig.class); public MyBatisTypeMapScannerConfig(ApplicationContext applicationContext, SqlSessionFactory sqlSessionFactory) {
在配置中可以获取SqlSessionFactory,看到这里,已经结束了。剩下的都是不重要细节。
1.读取项目下的model(包含@table注解的类)
List<Class<?>> list = ClassUtil.getClassesWithAnnotation(Table.class);
2.读取model下的字段(根据@Column注解)
Map<String, Map<String, Object>> cols = ClassUtil.getColumnRelation(clas);
3.根据table和column信息配置resultmap,mapper
End;
代码: MyBatisTypeMapScannerConfig
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set; import javax.persistence.Table; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.tomcat.util.buf.StringUtils;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration; import com.esri.rest.util.ClassUtil; /**
* 自动根据@Table注解和@Column注解添加mybatis中的resultmap配置,
* 此配置生效后不需要在mapper.xml中手动添加resultmap,自动添加的resultmap的ID为类的全路径名
* <p>
* Title: MyBatisTypeMapScannerConfig.java
* </p>
* <p>
* Description:
* </p>
*
* @author lichao1
* @date 2018年12月4日
* @version 1.0
*/
@Configuration
@AutoConfigureAfter(MybatisAutoConfiguration.class)
public class MyBatisTypeMapScannerConfig { protected final Log log = LogFactory.getLog(getClass()); public MyBatisTypeMapScannerConfig(ApplicationContext applicationContext, SqlSessionFactory sqlSessionFactory) {
log.debug("自动添加resultMap");
org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration(); // ResultMap rm = new ResultMap.Builder(configuration, id, type,
// null).build();
// configuration.addResultMap(rm);
// 获取默认包下的所有包含@Table注解的类
List<Class<?>> list = ClassUtil.getClassesWithAnnotation(Table.class); for (Class<?> clas : list) {
System.out.println(clas);
Map<String, Map<String, Object>> cols = ClassUtil.getColumnRelation(clas);
ResultMap rm = new ResultMap.Builder(configuration, clas.getName(), clas,
getResultMapping(configuration, cols)).build();
configuration.addResultMap(rm);
List<ResultMap> resultMaps = new ArrayList<ResultMap>();
resultMaps.add(rm); Table table = clas.getAnnotation(Table.class);
String tableName = table.name();
String allColum = getColumListString(cols); // select
// String sql = " select " + allColum + " from " + tableName;
// SqlSource sqlSource = new RawSqlSource(configuration, sql, clas);
// Builder builder = new MappedStatement.Builder(configuration,
// clas.getName() + ".select", sqlSource,
// SqlCommandType.SELECT);
// builder.resultMaps(resultMaps);
// MappedStatement ms = builder.build();
// configuration.addMappedStatement(ms); InputStream inputStream = createXml(clas, cols);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, clas.getName() + ".auto",
configuration.getSqlFragments());
mapperParser.parse(); } log.debug("自动添加resultMap");
} private InputStream createXml(Class<?> clas, Map<String, Map<String, Object>> cols) {
StringBuilder builder = new StringBuilder();
String name = clas.getName();
Table table = clas.getAnnotation(Table.class);
String tableName = table.name();
String allColum = getColumListString(cols); builder.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
builder.append(
"<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >");
builder.append("<mapper namespace=\"" + name + "\" >"); Set<String> keys = cols.keySet();
String[] keyArr = new String[keys.size()];
keys.toArray(keyArr); /****************** 查询 start ***************/
builder.append("<select id=\"" + name + ".select\" resultMap=\"" + name + "\" >");
builder.append("SELECT " + allColum + " FROM " + tableName + " WHERE 1=1 ");
// builder.append(" <if test=\"id != null\"> and id like #{id} </if>");
// 查询条件
builder.append(createLikelySql(keyArr, clas, cols)); // 排序
builder.append(" <if test=\"ORDERBY != null\"> order by ${ORDERBY} </if>"); // 分页
builder.append(" <if test=\"pagestart != null\"> limit #{pagesize} OFFSET #{pagestart} </if>"); builder.append("</select>");
/****************** 查询 end ***************/ /****************** 计数 start ***************/
builder.append("<select id=\"" + name + ".count\" resultType=\"long\" >");
builder.append("SELECT count(*) count FROM " + tableName + " WHERE 1=1 ");
builder.append(createLikelySql(keyArr, clas, cols));
builder.append("</select>"); /****************** 计数 end ***************/ /****************** 精确查询 start ***************/
builder.append("<select id=\"" + name + ".selectexactly\" resultMap=\"" + name + "\" >");
builder.append("SELECT " + allColum + " FROM " + tableName + " WHERE 1=1 ");
// builder.append(" <if test=\"id != null\"> and id like #{id} </if>");
// 查询条件
builder.append(createExactlySql(keyArr, clas, cols)); // 排序
builder.append(" <if test=\"ORDERBY != null\"> order by ${ORDERBY} </if>"); // 分页
builder.append(" <if test=\"pagestart != null\"> limit #{pagesize} OFFSET #{pagestart} </if>"); builder.append("</select>");
/****************** 精确查询 end ***************/ /****************** 精确计数 start ***************/
builder.append("<select id=\"" + name + ".countexactly\" resultType=\"long\" >");
builder.append("SELECT count(*) count FROM " + tableName + " WHERE 1=1 ");
builder.append(createExactlySql(keyArr, clas, cols));
builder.append("</select>");
/****************** 精确计数 end ***************/ /****************** 自定义条件语句查询 start ***************/
builder.append("<select id=\"" + name + ".selectwhere\" resultMap=\"" + name + "\" >");
builder.append("SELECT " + allColum + " FROM " + tableName + " ");
// 查询条件
builder.append(" <if test=\"WHERESTR != null\"> WHERE ${WHERESTR} </if>"); // 排序
builder.append(" <if test=\"ORDERBY != null\"> order by ${ORDERBY} </if>"); // 分页
builder.append(" <if test=\"pagestart != null\"> limit #{pagesize} OFFSET #{pagestart} </if>"); builder.append("</select>");
/****************** 自定义条件语句查询 end ***************/ /****************** 自定义条件语句计数 start ***************/
builder.append("<select id=\"" + name + ".countwhere\" resultType=\"long\" >");
builder.append("SELECT count(*) count FROM " + tableName + " ");
// 查询条件
builder.append(" <if test=\"WHERESTR != null\"> WHERE ${WHERESTR} </if>");
builder.append("</select>");
/****************** 自定义条件语句计数 end ***************/ /****************** 删除 start ***************/
builder.append("<delete id=\"" + name + ".delete\" parameterType=\"java.lang.String\" >");
builder.append(" DELETE FROM " + tableName + " WHERE id =#{id} ");
builder.append("</delete>");
/****************** 删除 end ***************/ /****************** 批量删除 start ***************/
builder.append("<delete id=\"" + name + ".deletebatch\" >");
builder.append(" DELETE FROM " + tableName + " WHERE 1=1 ");
builder.append(createExactlySql(keyArr, clas, cols));
builder.append("</delete>");
/****************** 批量删除 end ***************/ /****************** 更新 start ***************/
builder.append("<update id=\"" + name + ".update\" parameterType=\"" + name + "\" >");
builder.append("UPDATE " + tableName + " SET ");
for (int i = 0; i < keyArr.length; i++) {
String key = keyArr[i];
Map<String, Object> obj = cols.get(key);
builder.append(" " + (String) obj.get("dbname") + " = #{" + key + "}");
if (i < (keyArr.length - 1)) {
builder.append(",");
}
}
builder.append(" WHERE id =#{id} ");
builder.append("</update>");
/****************** 更新 end ***************/ /****************** 按需更新 start ***************/
builder.append("<update id=\"" + name + ".updatesection\" parameterType=\"" + name + "\" >");
builder.append("UPDATE " + tableName + " SET ");
for (int i = 0; i < keyArr.length; i++) {
String key = keyArr[i];
Map<String, Object> obj = cols.get(key);
// builder.append(" " + (String) obj.get("dbname") + " = #{" + key +
// "}");
if (!"id".equals(key)) {
builder.append(" <if test=\"_parameter.containsKey('" + key + "')\">" + (String) obj.get("dbname") + " = #{" + key
+ "} , </if>");
// builder.append(" " + (String) obj.get("dbname") + " = #{" + key + "} , ");
}
}
builder.append(" id = #{id} ");
builder.append(" WHERE id =#{id} ");
builder.append("</update>");
/****************** 按需更新 end ***************/ /****************** 插入 start ***************/
builder.append("<insert id=\"" + name + ".insert\" parameterType=\"" + name + "\" >");
builder.append("insert INTO " + tableName + " (" + allColum + ") VALUES");
builder.append("(" + getColumListString2(cols, "#{", "}") + ") ");
builder.append("</insert>");
/****************** 插入 end ***************/ builder.append("</mapper>");
InputStream is = new ByteArrayInputStream(builder.toString().getBytes());
return is;
} private String createListXml() {
StringBuilder builder = new StringBuilder(); return builder.toString();
} /**
* 生成查询条件语句
*
* @param keyArr
* @param clas
* @param cols
* @return
*/
private String createLikelySql(String[] keyArr, Class<?> clas, Map<String, Map<String, Object>> cols) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < keyArr.length; i++) {
String key = keyArr[i];
Map<String, Object> obj = cols.get(key);
try {
Class t = (Class) obj.get("type");
if (t == String.class) {
// String 类型自动支持like '%' || #name# || '%'
builder.append(" <if test=\"" + key + " != null\"> and " + (String) obj.get("dbname")
+ " like '%'||#{" + key + "}|| '%' </if>");
} else {
builder.append(" <if test=\"" + key + " != null\"> and " + (String) obj.get("dbname") + " = #{"
+ key + "} </if>");
} } catch (Exception e) {
log.info(obj);
log.info(key);
log.info(clas.getName());
}
}
return builder.toString();
} private String createExactlySql(String[] keyArr, Class<?> clas, Map<String, Map<String, Object>> cols) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < keyArr.length; i++) {
String key = keyArr[i];
Map<String, Object> obj = cols.get(key);
builder.append(
" <if test=\"" + key + " != null\"> and " + (String) obj.get("dbname") + " = #{" + key + "} </if>");
}
return builder.toString();
} /**
* 获取表内字段
*
* @param cols
* @return
*/
private String getColumListString(Map<String, Map<String, Object>> cols) {
return getColumListString(cols, "", "");
} private String getColumListString(Map<String, Map<String, Object>> cols, String pre, String end) {
pre = pre == null ? "" : pre;
end = end == null ? "" : end;
Set<String> keys = cols.keySet();
String[] keyArr = new String[keys.size()];
String[] nameArr = new String[keys.size()];
keys.toArray(keyArr);
for (int i = 0; i < keyArr.length; i++) {
String key = keyArr[i];
Map<String, Object> obj = cols.get(key);
if (((String) obj.get("dbname")).equals("update_date")) {
log.info("key");
}
nameArr[i] = pre + (String) obj.get("dbname") + end;
}
return StringUtils.join(nameArr);
} private String getColumListString2(Map<String, Map<String, Object>> cols) {
return getColumListString2(cols, "", "");
} private String getColumListString2(Map<String, Map<String, Object>> cols, String pre, String end) {
pre = pre == null ? "" : pre;
end = end == null ? "" : end;
Set<String> keys = cols.keySet();
String[] keyArr = new String[keys.size()];
String[] nameArr = new String[keys.size()];
keys.toArray(keyArr);
for (int i = 0; i < keyArr.length; i++) {
String key = keyArr[i];
nameArr[i] = pre + key + end;
}
return StringUtils.join(nameArr);
} /**
* 根据@Column注解生成字段映射关系
*
* @param configuration
* @param Map<String,
* Map<String, Object>> cols
* @return
*/
private List<ResultMapping> getResultMapping(org.apache.ibatis.session.Configuration configuration,
Map<String, Map<String, Object>> cols) {
List<ResultMapping> resultMappings = new ArrayList<ResultMapping>(); System.out.println(cols);
Set<String> keys = cols.keySet();
String[] keyArr = new String[keys.size()];
keys.toArray(keyArr); for (String key : keyArr) {
String property;
String column;
Object javaType;
Map<String, Object> map = cols.get(key);
property = key;
column = (String) map.get("dbname");
javaType = map.get("type");
ResultMapping mapping = new ResultMapping.Builder(configuration, property, column, (Class<?>) javaType)
.build();
resultMappings.add(mapping);
} return resultMappings;
} }
应用
CommonDaoimpl
/**
* CommonDaoimpl
* <p>
* Title: CommonDaoimpl.java
* </p>
* <p>
* Description:
* </p>
*
* @author lichao1
* @date 2018年11月19日
* @version 1.0
* @param <T>
* @param <ID>
*/
@Repository
public class CommonDaoimpl<T, ID extends Serializable> implements ICommonDao<T, ID> { @PersistenceContext
private EntityManager entityManager; @Autowired
public SqlSessionFactory sqlSessionFactory; protected <T> String getStatement(Class<T> clazz, String prefix) {
String entityName = clazz.getSimpleName();
if (entityName.endsWith("Model")) {
entityName = entityName.substring(0, entityName.length() - 5);
}
if (entityName.endsWith("Entity")) {
entityName = entityName.substring(0, entityName.length() - 6);
}
entityName = prefix + entityName;
return entityName;
} // Mybatis 查询方法, 只需要输入mapper的命名空间名称和方法名就可以实现数据库操作 /**
* 执行删除语句
* @param statement
* @param parameter
* @return
*/
public int deleteByMyBatis(String statement, Object parameter) {
return this.sqlSessionFactory.openSession().delete(statement, parameter);
} /**
* 执行删除语句
* @param t
* @param funName
* @param parameter
* @return
*/
public int deleteByMyBatis(Class<T> t, String funName, Object parameter) {
String statement = t.getName() + "." + funName;
return deleteByMyBatis(statement, parameter);
}
public int deleteByMyBatis(Class<T> t, Object parameter) {
String statement = t.getName() + "." + "delete";
return deleteByMyBatis(statement, parameter);
} /**
* 执行查询列表
* @param statement
* @param parameter
* @return
*/
public List<T> listByMyBatis(String statement, Object parameter) {
return this.sqlSessionFactory.openSession().selectList(statement, parameter);
} /**
* 执行查询列表语句
* @param t
* @param funName
* @param parameter
* @return
*/
public List<T> listByMyBatis(Class<T> t, String funName, Object parameter) {
String statement = t.getName() + "." + funName;
return listByMyBatis(statement, parameter);
} public List<T> ListByMyBatis(Class<T> t, Object parameter){
String statement = t.getName() + "." + "select";
return listByMyBatis(statement, parameter);
} /**
* 执行插入语句
* @param statement
* @param parameter
* @return
*/
public int insertByMyBatis(String statement, Object parameter) {
return this.sqlSessionFactory.openSession().insert(statement, parameter);
} /**
* 执行插入语句
* @param t
* @param funName
* @param parameter
* @return
*/
public int insertByMyBatis(Class<T> t, String funName, Object parameter) {
String statement = t.getName() + "." + funName;
return insertByMyBatis(statement, parameter);
} /**
* 执行选择一条记录语句
* @param statement
* @param parameter
* @return
*/
public T selectOneByMyBatis(String statement, Object parameter) {
return this.sqlSessionFactory.openSession().selectOne(statement, parameter);
} /**
* 执行选择一条记录语句
* @param t
* @param funName
* @param parameter
* @return
*/
public T selectOneByMyBatis(Class<T> t, String funName, Object parameter) {
String statement = t.getName() + "." + funName;
return selectOneByMyBatis(statement, parameter);
} /**
* 计数
* @param t
* @param parameter
* @return
*/ public long countByMyBatis(String statement, Object parameter) {
return (long)this.sqlSessionFactory.openSession().selectOne(statement, parameter);
} public long countByMyBatis(Class<?> t, Object parameter){
String statement = t.getName() + ".count";
return countByMyBatis(statement, parameter);
} /**
* 更新数据
* @param statement
* @param parameter
* @return
*/
public int updateByMyBatis(String statement, Object parameter) {
return this.sqlSessionFactory.openSession().update(statement, parameter);
} /**
* 更新数据
* @param t
* @param funName
* @param parameter
* @return
*/
public int updateByMyBatis(Class<T> t, String funName, Object parameter) {
String statement = t.getName() + "." + funName;
return updateByMyBatis(statement, parameter);
} public int updateByMyBatis(Class<T> t, Object parameter) {
String statement = t.getName() + ".update";
return updateByMyBatis(statement, parameter);
} /**
* 插入数据
* @param statement
* @param parameter
* @return
*/
public int insertByMayBatis(String statement, Object parameter) {
return this.sqlSessionFactory.openSession().insert(statement, parameter);
} public int insertByMayBatis(Class<T> t, String funName, Object parameter) {
String statement = t.getName() + "." + funName;
return this.sqlSessionFactory.openSession().insert(statement, parameter);
} public int insertByMayBatis(Class<T> t, Object parameter) {
return insertByMayBatis(t,"insert", parameter);
}
SpringBoot+MyBatis中自动根据@Table注解和@Column注解生成增删改查逻辑的更多相关文章
- SpringBoot+MyBatis中自动根据@Table注解和@Column注解生成ResultMap
其实我一点都不想用mybatis,好多地方得自己写,比如这里. 使用mybatis要写大量的xml,烦的一批.最烦人的莫过于写各种resultmap,就是数据库字段和实体属性做映射.我认为这里应该是m ...
- Springboot+Mybatis+Clickhouse+jsp 搭建单体应用项目(三)(添加增删改查)
一.添加增加接口 @ApiResponses(value = { @ApiResponse(code = 200, message = "接口返回成功状态"), @ApiRespo ...
- MyBatis学习 之 二、SQL语句映射文件(2)增删改查、参数、缓存
目录(?)[-] 二SQL语句映射文件2增删改查参数缓存 select insert updatedelete sql parameters 基本类型参数 Java实体类型参数 Map参数 多参数的实 ...
- 微软Connect教程系列--自动生成增删改查页面工具介绍(二)
本章课程描述了vs2015的三个特点,其中主要将描述在vs2015下面,使用命令自动生成增删改查界面,具体如下: 1.web.config文件不在存在,用config.json替代,以适应支撑vs的插 ...
- NetCore2.0 RozarPage自动生成增删改查
原文链接:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/web-api-help-pages-using-swagger 上面的只是原文 ...
- magento中Model创建以及该Model对于数据库的增删改查
本文是按照magento英文文档照做与翻译的. Model层的实现是mvc框架的一个巨大的部分.它代表了你的应用的数据,或者说大多数应用没有数据是无用的.Magento的Model扮演着一个重要的角色 ...
- Mybatis学习笔记(二) 之实现数据库的增删改查
开发环境搭建 mybatis 的开发环境搭建,选择: eclipse j2ee 版本,mysql 5.1 ,jdk 1.7,mybatis3.2.0.jar包.这些软件工具均可以到各自的官方网站上下载 ...
- Java代码自动生成,生成前端vue+后端controller、service、dao代码,根据表名自动生成增删改查功能
本项目地址:https://github.com/OceanBBBBbb/ocean-code-generator 项目简介 ocean-code-generator采用(适用): ,并使用m ...
- 用Java中的File类模拟实现对系统文件的增删改查效果
码字不易,三连支持一波吧 IO操作向来是各大语言的热区,而对文件的操作也是重中之重. 那么在Java中也给我们提供了很多关于文件操作的类.今天我就用一个比较基本的File类来模拟实现对文件的增删改查效 ...
随机推荐
- Django(二):url和views
网络通讯的本质是socket,从socket封装到MVC模式,参见另外几篇博客.本节笔记整理自Django2.0官方文档. 一.url调度器 - django.urls.path django2.0中 ...
- K:单例模式中存在的问题
对于单例模式的实现,无论其是否具有懒加载的功能,我们的目标是有且仅生成一个对象.但是,实际上,对于单例模式的一般实现,都会存在着以下的两个问题: 序列化攻击: 对于枚举方式实现的单例模式,并不存在 ...
- python,tensorflow,CNN实现mnist数据集的训练与验证正确率
1.工程目录 2.导入data和input_data.py 链接:https://pan.baidu.com/s/1EBNyNurBXWeJVyhNeVnmnA 提取码:4nnl 3.CNN.py i ...
- 第二天-while循环 格式化输出 运算符 编码
一.while循环 while 条件: 语句块(循环体) #判断条件是否成立,若成立执行循环体,然后再次判断条件...直到不满足跳出循环 else: 当条件不成立的时候执行这里,和break没 ...
- gulp 打包报错:Error: `libsass` bindings not found. Try reinstalling `node-sass`
看了网上很多帖子 有说切换node版本的 有说卸载重新装gulp-sass的 有说删除node_modules重新install的 但是我测试了下在我们的电脑环境下都不行,后来找到一个可以打包不报错的 ...
- java截取字符串
public class Temp { public static void main(String[] args) { String a="dsadgafa34"; System ...
- 收藏的几个关于php面向对象教程
面向对象的分析方法是利用面向对象的信息建模概念,如实体.关系.属性等,同时运用封装.继承.多态等机制来构造模拟现实系统的方法,学会了面向对象思想,能够大大提高php编程开发效率!本篇文章php中文网将 ...
- WinForm实现Rabbitmq官网6个案例-Routing
代码: namespace RabbitMQDemo { public partial class Routing : Form { private string exchangeName = &qu ...
- c# 序列化接口(转载贴)
http://www.cnblogs.com/TianFang/p/3724449.html
- Android学习笔记(2)----LocationManager的使用
今天使用Android的LocationManager制作了一款获取当前经纬坐标位置的软件. LocationManager获取的只是经纬坐标点,为了解析出当前经纬坐标点的实际位置,可以使用Googl ...