博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[瞎折腾]使用freemarker编写MyBatis的Mapper.xml自动生成工具
阅读量:7095 次
发布时间:2019-06-28

本文共 8366 字,大约阅读时间需要 27 分钟。

  hot3.png

MyBatis是 iBatis的新项目名,是一个java的持久化框架,和目前一家独大的Hibernate相比MyBatis显得比较的被冷漠。两个都是好框架,大家习惯用哪个而已。因为之前一直是用iBatis,现在看到新版的MyBatis想来学习一下。
MyBatis的官网有很详细的user guides,而且还有中文,看一两天就可以上手:
新版的一个重点特性是新增动态SQL(dynamic SQL),简单来说就是能够使用while、if、elseif、loop,就是在Mapper.xml中加入条件控制,基于这个不算新的功能,我妄想写一个生成工具对每个表生成一份可以完全实现80%数据库操作的mapper.xml,最终工具是产生了,但是达不到理想的效果,原因有几方面:
1、不能满足所有的需求
2、不能生成级联的mapper
3、生成的mapper很大,解析起来非常耗时,即效率不好
4、实际应用意义不大
基于上面的几点,我放弃了对其的改进,不过在这个过程中有不少有用的知识点需要记录下来。另外补充的是,官方有一个自动生成的插件: 一样的不好用,还是自己写sql比较好。
一、MyBatis和Spring结合
MyBatis和Spring结合非常简单,配置也不复杂,除了Spring和Mybatis的jar包外还需要插件包mybatis-spring-1.0.1.jar ,上面的jar都可以在 下载到。
现在有一个项目如图:
关注java/org.mybatis.jpetstore.persistence和resource/org.mybatis.jpetstore.persistence两个包,java下的是dao的接口,resource下的是数据表的Mapper。
里面有一个表如下:
create table category (    catid varchar(10) not null,    name varchar(80) null,    descn varchar(255) null,    constraint pk_category primary key (catid));
现在你需要对这个表根据id进行select操作,首先需要定义一个接口CategoryMapper.java:
public interface CategoryMapper {  Category getCategory(String categoryId);}
然后需要新建一个Mapper,CategoryMapper.xml:
最后就是在spring的配置文件中配置就可以了:
直接用Spring的scans扫描整个包,我感觉这种方式即简单又方便,感觉很清爽,而且扩展性也很好。
二、利用freemarker生成动态SQL
下面的内容需要对freemarker有一定的认识,至于什么是freemarker,看官方的文档:
这份文档非常详细,只有你想不到,没有没提到的。
velocity跟freemarker两个是类似的java模板工具,前者没有宏定义,后者有,在没有什么特别复杂需求的时候建议用前者(纯属我个人观点)
Mapper生成工具具体流程:
通过jdbc读取数据库——》返回表名(table.sqlName)、所有字段的list(table.columns)、每个字段的名字(column.sqlName)、每个字段的类型(column.javaType) ——》对信息进行处理生成一些变量类名(className)、首字母小写的变量名(column.columnNameFirstLower)、大写的变量名(column.constantName)——》编写flt模板文件——》生成Mapper.xml。
需要说明的几点:
(1)、在Mybatis的Mapper.xml中是用#{value}和${value}显示变量的值,对于#{value},MyBatis会把value里面的双引号、单引号去掉,${value}则会把变量中的值原封不动的替换。
(2)、在freemarker中也是用${value}这种形式来显示变量的,因此用freemarker生成Mapper.xml需要达到的效果是${value}解析后得到${XXX}或者#{XXX}
为了解决上面的第二点,有必要定义两个宏:
<#macro mapperEl value>${r"#{"}${value}}</#macro>用来生成#{value}
<#macro jspEl value>${r"${"}${value}}</#macro> 用来生成${value}
SQL语句分析:
sql太复杂了,下面只讲where的部分,在sql语句中有很大一部分是condition部分,where部分组成大概有下面几点:
(1)、当column是string时,column = #{value}
(2)、当column是date时, trunc(column, 'MI') = trunc(#{value}, 'MI')
(3)、条件之间有 AND OR 两种关系
(4)、like 的条件连接,需要再根据(1)、(2)两点来分类
(5)、除去上面的外加一个extraConditions,允许用户写一些好复杂的条件
大概就5点吧,直接上代码:
<#list table.columns as column>
<#if column.javaType == "java.util.Date" > ,'MI') ]]> <#else> AND tb.${column.sqlName} = <@mapperEl column.columnNameFirstLower/>
<#list table.columns as column> <#if column.javaType == "java.lang.String">
AND tb.${column.sqlName} LIKE <@mapperLike column.columnNameFirstLower/>
<#elseif column.javaType == "java.util.Date" >
AND trunc(tb.${column.sqlName},'MI') >= trunc(<@mapperBegin column.columnNameFirstLower/>,'MI')
AND trunc(tb.${column.sqlName},'MI') <= trunc(<@mapperEnd column.columnNameFirstLower/>,'MI')
<#else>
<#list table.columns as column>
OR tb.${column.sqlName} = <@mapperEl column.columnNameFirstLower/>
<#list table.columns as column> <#if column.javaType == "java.lang.String">
OR tb.${column.sqlName} LIKE <@mapperLike column.columnNameFirstLower/>
<#elseif column.javaType == "java.util.Date" >
OR trunc(tb.${column.sqlName},'MI') >= trunc(<@mapperBegin column.columnNameFirstLower/>,'MI')
OR trunc(tb.${column.sqlName},'MI') <= trunc(<@mapperEnd column.columnNameFirstLower/>,'MI')
<#else>
<@jspEl 'extraConditions'/>
<@jspEl 'sortColumns'/>
<@jspEl 'groupColumns'/>
生成的结果:
AND category.catid = #{catid}
AND category.name = #{name}
AND category.descn = #{descn}
AND category.catid LIKE #{catid}
AND category.name LIKE #{name}
AND category.descn LIKE #{descn}
OR category.catid = #{catid}
OR category.name = #{name}
OR category.descn = #{descn}
OR category.catid LIKE #{catid}
OR category.name LIKE #{name}
OR category.descn LIKE #{descn}
${extraConditions}
${orderBy}
${groupBy}
然后是对于javaBean的生成模板:${className}Bean.java
<#assign className = table.className>   <#assign classNameLower = className?uncap_first> package ${basepackage}.model;import java.io.Serializable;import ${basepackage}.model.BaseEntitySupportpublic class ${className}Bean extends BaseEntitySupport implements java.io.Serializable{    private static final long serialVersionUID = 8751282105532159742L;    <#list table.columns as column>    private ${column.javaType} ${column.columnNameLower};    
<#list table.columns as column> public ${className} set${column.columnName}(${column.javaType} ${column.columnName}) { this.${column.columnNameLower} = ${column.columnName}; return this; } public ${column.javaType} get${column.columnName}() { return this.${column.columnNameLower}; }
}
生成结果CategoryBean .java:
import java.io.Serializable;import org.mybatis.jpetstore.persistence.model.BaseEntitySupportpublic class CategoryBean extends BaseEntitySupport implements java.io.Serializable{    private static final long serialVersionUID = 8751282105532159742L;    private java.lang.String catid;    private java.lang.String name;    private java.lang.String descn;    public Category setCatid(java.lang.String Catid) {        this.catid = Catid;        return this;    }    public java.lang.String getCatid() {        return this.catid;    }    public Category setName(java.lang.String Name) {        this.name = Name;        return this;    }    public java.lang.String getName() {        return this.name;    }    public Category setDescn(java.lang.String Descn) {        this.descn = Descn;        return this;    }    public java.lang.String getDescn() {        return this.descn;    }}
工具生成的代码大概就是这个样子,只要加上insert、update、select、delete基本就成型。
可是,就如上面说的,这个生成工具没有什么实际的意义,所以还是作为瞎折腾的产物吧。

转载于:https://my.oschina.net/541996928/blog/128912

你可能感兴趣的文章
项目整体管理
查看>>
打算搭建一个***视频下载网站
查看>>
Skype for Business Server 2015-04-前端服务器-7-部署
查看>>
我的友情链接
查看>>
django使用rest_framework API认证
查看>>
背景图片百分之百大小css设置方法
查看>>
SQL 语句中的With(index())
查看>>
我的友情链接
查看>>
修改计算机名后arcgis设置
查看>>
揭密HTML5带来的攻击手法
查看>>
php脚本超时时间设置
查看>>
DPM2012学习(十一),裸机还原域控制器
查看>>
SQL2005学习(二十五),插入单行数据
查看>>
bootstrap-fileinput提交多张图片时只获取到一张
查看>>
RedHat 正在决定 eth0 的 IP 信息...失败;无链接。检查电缆吗?
查看>>
我眼中的德国攻城师
查看>>
Linux Mail基本服务器构建之postfix源码安装(下)
查看>>
Centos6.2下puppet客户端安装
查看>>
Nginx实现高效负载均衡器
查看>>
ElastAlert对ELK日志进行邮箱报警
查看>>