tk.mybatis通用工具pom

 <!--mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency> <!--通用mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.1.5</version>
</dependency>
  • 我使用springboot搭建,所以引用的都是springboot封装的组件

采坑点

批量插入数据,默认主键只支持id

  1. 继承此工具MySqlMapper方法后
/**
* 通用Mapper接口,MySql独有的通用方法
*
* @param <T> 不能为空
* @author liuzh
*/
public interface MySqlMapper<T> extends
InsertListMapper<T>,
InsertUseGeneratedKeysMapper<T> { }
  • 可以看到存在可以批量插入类到数据库的方法
  • 如果项目中途加入了此工具,那么恭喜,估计要踩很多坑~
  • 数据库表主键不为id时,可以继续看源码
public interface InsertListMapper<T> {

    /**
* 批量插入,支持批量插入的数据库可以使用,例如MySQL,H2等,另外该接口限制实体包含`id`属性并且必须为自增列
*
* @param recordList
* @return
*/
@Options(useGeneratedKeys = true, keyProperty = "id")
@InsertProvider(type = SpecialProvider.class, method = "dynamicSQL")
int insertList(List<T> recordList); /**
* ======如果主键不是id怎么用?==========
* 假设主键的属性名是uid,那么新建一个Mapper接口如下
* <pre>
public interface InsertUidListMapper<T> {
@Options(useGeneratedKeys = true, keyProperty = "uid")
@InsertProvider(type = SpecialProvider.class, method = "dynamicSQL")
int insertList(List<T> recordList);
}
* 只要修改keyProperty = "uid"就可以
*
* 然后让你自己的Mapper继承InsertUidListMapper<T>即可
*
* </pre>
*/
}
  • 他留着坑还是很负责的把解决办法留下了~~
  • 我是按网上通用的搭建方式搭建的目录结构,也就是如下结构
/**
* 继承自己的MyMapper
*
*/
public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {
//FIXME 特别注意,该接口不能被扫描到,否则会出错
//FIXME 最后在启动类中通过MapperScan注解指定扫描的mapper路径:
}
  • 因为InsertUidListMapper这种特殊写的mapper和MyMapper是同一类,如果不同样配置下会报如下错误
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (tk.mybatis.mapper.provider.SpecialProvider.dynamicSQL).  Cause: java.lang.InstantiationException: tk.mybatis.mapper.provider.SpecialProvider
  • 这时候你要,在application.properties中,把InsertUidListMapper路径配上去
mapper.mappers=com.tzxylao.manager.utils.MyMapper,com.tzxylao.manager.mapper_ext.InsertUidListMapper
  • 还有一点,光这样匹配后还不够,自己写的类DpageConfigMapper,继承InsertUidListMapper这个类后,把DpageConfigMapper类放在Mapper目录下,那么又会很纠结。系统启动会扫描不到DpageConfigMapper这个类。。我竟然找不到默认扫描Mapper包的地方。。但是经验告诉我,继承了MyMapper的类都能被扫描到~~
  • 可是自己的类继承的是InsertUidListMapper,想要它被扫描,启动类就要加上扫描包的地方。。我扫描了整个Mapper包
@EnableTransactionManagement  // 启注解事务管理,等同于xml配置方式的
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableAutoConfiguration
@MapperScan("com.tzxylao.manager.mapper")
public class Application extends SpringBootServletInitializer { public static void main(String[] args) {
SpringApplication.run(Application.class, args);
} @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
  • 但这样要注意,继承类InsertUidListMapper,不能再这个包里,否则会报该类不能被扫描错误~~
  • 就算把这个类移到了其他包,系统也可以正常运行了。。其实还是有点问题。。启动的时候会出现类似的警告
Skipping MapperFactoryBean with name 'sysMenuMapper' and 'com.telchina.framework.sys.mapper.SysMenuMapper' mapperInterface. Bean already defined with the same name!

虽然不影响使用,但还是看着烦,他的意思就是这个类被扫了两遍我就说哪里MyMapper类继承的类都被莫名其妙扫了一遍。。自己再配置扫一遍就重复了

  • 解决办法就是再建个子包,不继承MyMapper的自定义Mapper都放子包,再单独配置子包扫描
@EnableTransactionManagement  // 启注解事务管理,等同于xml配置方式的
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableAutoConfiguration
@MapperScan("com.tzxylao.manager.mapper.ext")
public class Application extends SpringBootServletInitializer { public static void main(String[] args) {
SpringApplication.run(Application.class, args);
} @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}

把DpageConfigMapper类放ext子包里就行了。。

  • 上面步骤都解决了,插入还是不成功的,插入语句没有主键,自己生成的主键插不进去?
  • 看源码
 /**
* 批量插入
*
* @param ms
*/
public String insertList(MappedStatement ms) {
final Class<?> entityClass = getEntityClass(ms);
//开始拼sql
StringBuilder sql = new StringBuilder();
sql.append(SqlHelper.insertIntoTable(entityClass, tableName(entityClass)));
sql.append(SqlHelper.insertColumns(entityClass, true, false, false));
sql.append(" VALUES ");
sql.append("<foreach collection=\"list\" item=\"record\" separator=\",\" >");
sql.append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">");
//获取全部列
Set<EntityColumn> columnList = EntityHelper.getColumns(entityClass);
//当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值
for (EntityColumn column : columnList) {
if (!column.isId() && column.isInsertable()) {
sql.append(column.getColumnHolder("record") + ",");
}
}
sql.append("</trim>");
sql.append("</foreach>");
return sql.toString();
}
  • 可以看到,主键插入的地方,他有这样的判断!column.isId() && column.isInsertable(),所以,Bean类主键属性上@Id去掉,就可以自己添加主键值了

总结

  • 总觉的我的解决方法很low,限制也太大~有熟悉tk.mybatis的大神讲下别的思路吗?

tk.mybatis通用工具采坑记的更多相关文章

  1. 分布式改造剧集之Redis缓存采坑记

    Redis缓存采坑记 ​ 前言 ​ 这个其实应该属于分布式改造剧集中的一集(第一集见前面博客:http://www.cnblogs.com/Kidezyq/p/8748961.html),本来按照顺序 ...

  2. Spring Cloud Config采坑记

    1. Spring Cloud Config采坑记 1.1. 问题 在本地运行没问题,本地客户端服务能连上本地服务端服务,可一旦上线,发现本地连不上线上的服务 服务端添加security登录加密,客户 ...

  3. k8s采坑记 - 解决二进制安装环境下证书过期问题

    前言 上一篇k8s采坑记 - 证书过期之kubeadm重新生成证书阐述了如何使用kubeadm解决k8s证书过期问题. 本篇阐述使用二进制安装的kubernetes环境,如何升级过期证书? k8s配置 ...

  4. Redis适配采坑记

    Redis适配采坑记 相对于其他的适配,Redis可以说是非常简单的其中只发现一个坑 问题一: 问题描述: redis认证失败 问题详解: redis连接配置时,本地需要采用password属性,远程 ...

  5. 微信小程序后台springboot+mybatis+mysql“采坑”集锦

    "采坑"错误集锦 1.service层 错误描述:2019-04-14 22:09:52.027 ERROR 8416 --- [nio-8082-exec-5] o.a.c.c. ...

  6. dubbo初学采坑记

    写在前面的话 dubbo 现在是apache组织旗下的项目,相信国内也有很多人使用.最近一个同事离职,我就接手了他的项目.远程通讯就是用的dubbo框架来实现的.使用Intelij idea 写了一个 ...

  7. Service worker (@nuxtjs/workbox) 采坑记

    PWA(Progressive Web App)是前端的大趋势,它能极大的加快前端页面的加载速度,得到近乎原生 app 的展示效果(其实难说).PWA 其实是多种前端技术的组合,其中最重要的一个技术就 ...

  8. aidl使用采坑记

    什么是AIDL? AIDL是 Android Interface definition language的缩写,它是一种Android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口 A ...

  9. css选择器:first-child和nth-child 采坑记

    今天想用nth-child来给一个类似于树的目录(bootstrap-nav-tree  一个angularjs插件)设置不同的颜色,结构大致类似于 <ul> <li class=& ...

随机推荐

  1. (转)Detect it Easy(壳侦测工具)使用方法介绍

    http://www.ucbug.com/jiaocheng/129805.html Detect it Easy是一个多功能的PE-DIY工具,主要用于壳侦测.功能正日益完善,是不可多得的破解利器! ...

  2. react mobx 装饰器语法配置

    1.弹出项目配置 npm run eject 此处注意,若弹出项目配置失败,请先执行以下两行代码(我的项目执行上一句都会报错,所以都会执行) 1.git add . 2.git commit -m & ...

  3. java学习笔记(四):import语法

    Import 语法是给编译器寻找特定类的适当位置的一种方法. 创建一个Employee 类,包括四个实体变量姓名(name),年龄(age),职位(designation)和薪水(salary). p ...

  4. vue项目如何通过前端实现自动识别并配置服务器环境地址

    前言: 一般来说,一个web项目的生产环境和测试环境的服务器地址一旦确定下来,很少会频繁变动的.那么就可以单独写一个脚本文件,通过当前访问的域名来判断当前的访问环境,然后再通过一定的规则获取对应的服务 ...

  5. Swift 反射机制,命名空间

    1. 知道 Swift 中有命名空间        - 在同一命名空间下,全局共享!        - 第三方框架使用 Swift 如果直接拖拽到项目中,从属同一个命名空间,很有可能冲突!       ...

  6. Swift 模型属性

    1 .  // 定义模型属性时,一般定义为可选的,可以简化代码,不需要写 init 方法    // 如果是基本数据类型,不能设置为可选的,而且要设置初始值 var name: String? pri ...

  7. jsp相关笔记(一)

    1.在html中调整两个<p>标签之间的间距,可以用margin属性: p { margin: 0.2em 0;} 2.在jsp中要对页面分成上.左.右三栏时,可以用<framese ...

  8. The best way to use Xtool X100 PAD2 for FEM programming

    Look here: XTOOL X100 PAD2 is new FEM programming. Possible to use Xtool X100 PAD2 for FEM programmi ...

  9. HBase Configuration过程

    (2012-10-22 15:56:10) 转载▼      HBase客户端API中,我们看到对HBase的任何操作都需要首先创建HBaseConfiguration类的实 例.为HBaseConf ...

  10. Alpha项目冲刺

    一.团队成员 学号 姓名 211606361 何承华(队长) 211606356 陈宇 211606360 丁培辉 211606333 温志铭 211606343 杨宇潇 211606391 张主强 ...