介绍
TgDao是一款基于Mybatis的编译期SQL生成器,利用注解来表达SQL,能根据你的方法签名生成对应的Mapper.xml文件。
它能减少你日常开发中大量简单SQL的编写,由于它只是生成Mapper.xml文件,因此对于复杂的查询场景,
你同样可以自己编写来完成一些工具所无法生成的SQL。
1 | 复制代码@Table(name = "T_User") |
上面的model定义了模型和数据库表的关系,看到下面这些方法的签名,聪明的你肯定能猜出每个方法的sql吧,这就是这个库要做的工作。
1 | 复制代码@DaoGen(model = User.class) |
文档
引入如下依赖:
1 | 复制代码<dependency> |
Table与Model关联
@Table
记录数据表的名字@Id
记录主键信息@Column
映射了表字段和属性的关系,如果表字段和类属性同名,那么可以省略这个注解@Ingore
忽略这个类属性,没有哪个表字段与它关联
1 | 复制代码@Table(name = "T_User") |
查询
1 | 复制代码@Select |
@Select
columns
:默认select *
可以配置columns("username,age")
选择部分字段;SqlMode
:有两个选择,SqlMode.SELECTIVE 和 SqlMode.COMMON,区别是selective会检查查询条件的字段是否为null来实现动态的查询,
即<if test="name != null">username = #{name}</if>
@Condition
criterion
:查询条件,=
,<
,>
,in
等,具体见Criterions
column
:与表字段的对应,若与字段名相同可不配置attach
:连接and
,or
, 默认是and
test
:selective下的判断表达式,即<if test="username != null">
里的test属性
@Limit
,@OffSet
为分页字段。
方法的参数不加任何注解一样会被当做查询条件,如下面两个函数效果是一样的:
1 | 复制代码@Select() |
查询Model
上面的例子在查询条件比较多时方法参数会比较多,我们可以把查询条件封装到一个类里,使用@ModelConditions
来注解查询条件,注意被@ModelConditions
只能有一个参数。
1 | 复制代码@Select |
@ModelCondition
field
:必填,查询条件中类对应的属性column
:对应的表字段paramType
:in 查询下才需要配置,数组为array
,List为collection
类型test
:selective下的判断表达式,即<if test="username != null">
里的test属性
@Page
只能用在ModelConditions下的查询,并且方法参数的那个类应该有offset
,limit
这两个属性。
注:
1 | 复制代码@Select(columns = "username,age") |
两个函数生成的sql如上,@Select
的属性SqlMode
默认是Selective
,所以两个都有条件判断,但是这里第一个函数的sql,
Mybatis不支持,执行会报错,类似no age getter in java.lang.Interger
,Mybatis会把这唯一的一个参数当做对象来取里面的值。
解决方法:函数签名里强加@Param()
注解,或者@Select
里使用sqlMode = SqlMode.COMMON
去掉生成sql里的if判断。
这个问题只会在方法只有一个参数的情况下发生,第二个函数生成的sql是ok的。
分页
查询参数里@Limit
,@OffSet
或查询model里@Page
的分页功能都比较原始,TgDao只是一款SQL生成器而已,因此你可以使用各种插件,
或者与其他框架集成。对于分页,可以无缝与PageHelper整合。
1 | 复制代码@Select |
插入
1 | 复制代码@Insert(useGeneratedKeys = true, keyProperty = "id")//获取自增id |
BatchInsert
强烈建议写columns,因为生成的语句并不会过滤null字段,数据库中插入null易报错。
更新
1 | 复制代码@Update(columns = "username,age")//选择更新某几个列 |
删除
1 | 复制代码@Delete |
selective
@Select
,@Count
,@Update
,@Delete
都有selective
这个属性,这个属性有两个值,分别是SqlMode.COMMON
和SqlMode.SELECTIVE
。
它们的区别在下面这段生成的xml里显示的很清楚,SqlMode.SELECTIVE
引入了Mybatis的动态SQL能力。
1 | 复制代码 <!-- SELECTIVE --> |
@Select
,@Count
默认的selective属性是SqlMode.SELECTIVE
,这样查询语句可以充分利用Mybatis的动态SQL能力。
而@Update
,@Delete
默认是SqlMode.COMMON
,这样做的原因是:selective模式下如果参数全是null
会使得where语句里没有任何条件,
最终变成全表的更新和删除,这是一个极其危险的动作。所以@Update
,@Delete
慎用SqlMode.SELECTIVE
模式。
@Params
在介绍这个注解时要先介绍一下Mybatis自己的@Param
注解,@Param
注解在方法的参数上,给参数定义了一个名字,
这样可以在xml的sql里使用这个名字来取得参数所对应的值。如下:
1 | 复制代码 List<User> queryUser(@Param("name") String name); |
明明参数就叫name,为什么还要@Param
注解一个名字name呢?这是因为Java编译完,会丢掉参数名,以至于运行期mybatis不知道这个参数叫什么,所以需要注解一个名字。
在运行时看到mybatis报错如:Parameter 'XXX' not found. Available parameters are...
这就是没有这个注解导致的问题。
但是在Java8里我们已经可以通过给javac 添加-parameters
参数来保留参数名字信息,这样mybatis会利用这个信息,这样就不需要加@Param
注解了。
maven可以通过如下方式设置:
1 | 复制代码 <plugin> |
然而有一种情况-parameters
也无能为力,List<User> queryUser4(List ids);
当参数是collection或者数组类型时,mybatis依旧无法认出ids
这个参数,只认collection
和array
。
而@Params
注解是Mybatis自身注解@Param
和-parameters
外的另外一种解决方案。@Params
可以注解在类和方法上,
被它注解的类和方法会在编译期自动给所有方法参数加上@Param
注解,它借鉴了lombok的方式在编译期修改抽象语法树从而改变编译生成的字节码文件。
1 | 复制代码 @Select(columns = "username,age") |
更多请看example
说明
- 编译生成的XML文件与Mapper接口在同一个包下
- 只支持Java8和MySql
- 修改了源代码中方法的定义或者model里和数据表的映射关系,发现编译出来的xml却没有改变,这是增量编译的原因。生成一个xml同时需要model和mapper interface两个部分,
如果你只修改了其中一个的代码,那么另一个未修改的代码编译器就不做处理,这样这一次编译就无法得到全部的信息,所以TgDao无法生成最新版本的xml。
解决方法是每次mvn clean compile
先清除一下编译目录,更好的方案正在寻找…
本文转载自: 掘金