- 四、代码生成器
- 生成的代码
Country">一、实体类CountryCountryMapper">二、Mapper接口CountryMapperCountryMapper.xml">三、Mapper.xml文件CountryMapper.xml- 4.2 代码生成器文档
- 五、扩展通用接口
四、代码生成器
4.1 通用 Mapper 专用代码生成器
使用该插件可以很方便的生成实体类、Mapper接口以及对应的XML文件。
本篇文档就是讲述如何在 MBG 中使用该插件。
首先对MBG不太了解的可以先阅读下面的文档
Mybatis Geneator 详解 http://blog.csdn.net/isea533/article/details/42102297
4.1.1 简单介绍
通用 Mapper 专用代码生成器生成的 Model 会在原有基础上增加 @Table,@Id,@Column 等注解,方便自动会数据库字段进行映射。
运行MBG有多种方法,这里只介绍两种比较常见的方法。并且有关的内容会针对这样的运行方式进行配置。
4.1.2 使用Java编码方式运行MBG
在 generatr 项目测试代码中包含这个例子。
使用这种方式,需要引入 MBG 的依赖,同时项目中应该已经有通用 Mapper 的依赖了。
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.6</version></dependency><!-- 通用 Mapper --><!-- https://mvnrepository.com/artifact/tk.mybatis/mapper --><dependency><groupId>tk.mybatis</groupId><artifactId>mapper</artifactId><version>4.0.0</version></dependency><!-- 如果你只需要用到通用 Mapper 中的插件,可以只引入 mapper-generator --><!-- 注意,这个包不需要和上面的 mapper 同时引入,mapper 中包含 generator --><!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-generator --><dependency><groupId>tk.mybatis</groupId><artifactId>mapper-generator</artifactId><version>1.0.0</version></dependency>
Java代码很容易,和测试中的一样:
public static void main(String[] args) throws Exception {List<String> warnings = new ArrayList<String>();boolean overwrite = true;ConfigurationParser cp = new ConfigurationParser(warnings);Configuration config =cp.parseConfiguration(getResourceAsStream("generatorConfig.xml"));DefaultShellCallback callback = new DefaultShellCallback(overwrite);MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);myBatisGenerator.generate(null);for (String warning : warnings) {System.out.println(warning);}}
注意,测试中还有
startDB等方法,这是因为测试中使用的 hsqldb 内存数据库。
这段代码容易,最主要的一个内容是"generatorConfig.xml",我们应该如何配置该类。
下面是一个generatorConfig.xml的例子:
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><!--suppress MybatisGenerateCustomPluginInspection --><generatorConfiguration><context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat"><property name="javaFileEncoding" value="UTF-8"/><property name="useMapperCommentGenerator" value="false"/><plugin type="tk.mybatis.mapper.generator.MapperPlugin"><property name="mappers" value="tk.mybatis.mapper.common.Mapper"/><property name="caseSensitive" value="true"/><property name="forceAnnotation" value="true"/><property name="beginningDelimiter" value="`"/><property name="endingDelimiter" value="`"/></plugin><jdbcConnection driverClass="org.hsqldb.jdbcDriver"connectionURL="jdbc:hsqldb:mem:generator"userId="sa"password=""></jdbcConnection><!--MyBatis 生成器只需要生成 Model--><javaModelGenerator targetPackage="test.model"targetProject="generator/src/test/java"/><table tableName="user_info"><generatedKey column="id" sqlStatement="JDBC"/></table><table tableName="country"><generatedKey column="id" sqlStatement="JDBC"/></table></context></generatorConfiguration>
和一般的配置相比,这里只是多了一个插件的配置:
<plugin type="tk.mybatis.mapper.generator.MapperPlugin"><property name="mappers" value="tk.mybatis.mapper.common.Mapper"/><property name="caseSensitive" value="true"/><property name="forceAnnotation" value="true"/><property name="beginningDelimiter" value="`"/><property name="endingDelimiter" value="`"/></plugin>
这里最关键的参数就是 mappers,配置后生成的 Mapper 接口都会自动继承上改接口,如果你定义了一个自己的基础接口,例如:
package xxx.base;import tk.mybatis.mapper.common.Mapper;import tk.mybatis.mapper.common.MySqlMapper;/*** 继承自己的MyMapper*/public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {//TODO//FIXME 特别注意,该接口不能被扫描到,否则会出错}
在配置插件时,可以配置为:
<property name="mappers" value="xxx.base.MyMapper"/>
其他参数的含义:
- caseSensitive 是否区分大小写,默认值
false。如果数据库区分大小写,这里就需要配置为true,这样当表名为USER时,会生成@Table(name = "USER")注解,否则使用小写user时会找不到表。 - forceAnnotation 是否强制生成注解,默认
false,如果设置为true,不管数据库名和字段名是否一致,都会生成注解(包含@Table和@Column)。 - beginningDelimiter 和 endingDelimiter 开始和结束分隔符,对于有关键字的情况下适用。
- useMapperCommentGenerator 是否使用通用 Mapper 提供的注释工具,默认
true使用,这样在生成代码时会包含字段的注释(目前只有 mysql 和 oracle 支持),设置false后会用默认的,或者你可以配置自己的注释插件。 - generateColumnConsts 在生成的 model中,增加字段名的常量,便于使用 Example 拼接查询条件的时候使用。
- lombok 增加 model 代码生成时,可以直接生成 lombok 的
@Getter@Setter@ToString@Accessors(chain = true)四类注解, 使用者在插件配置项中增加<property name="lombok" value="Getter,Setter,ToString,Accessors"/>即可生成对应包含注解的 model 类。
在上面<table 的配置中是针对 MySql 这种自增数据库的,如果使用 ORACLE 序列方式,可以参考下面的配置:
<table tableName="country"><generatedKey column="id"sqlStatement="select SEQ_{1}.nextval from dual"identity="false" type="pre"/></table>
SQL 中的 {1} 代表的是对应表的大写形式,{0} 是小写形式,这个配置生成的代码会像下面这样:
public class Country {@Id@GeneratedValue(strategy = GenerationType.IDENTITY,generator = "select SEQ_COUNTRY.nextval from dual")private Integer id;// 省略其他}
这段配置介绍完了,之后运行前面的JAVA方法,就会生成对应的文件。该文件的样式在最后贴个例子。
4.1.3 使用 Maven 执行MBG
这里有一个完整的例子,MyBatis-Spring,下面讲解的内容出自这个例子。
Maven 中的插件配置如下:
<plugins><plugin><artifactId>maven-compiler-plugin</artifactId><configuration><source>${jdk.version}</source><target>${jdk.version}</target></configuration></plugin><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.6</version><configuration><configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile><overwrite>true</overwrite><verbose>true</verbose></configuration><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.29</version></dependency><dependency><groupId>tk.mybatis</groupId><artifactId>mapper</artifactId><version>4.0.0</version></dependency></dependencies></plugin></plugins>
在插件中配置了配置文件的路径,覆盖和输出详细日志三个参数。
除此之外需要特别注意的是 <dependencies>,MBG 配置中用到的所有外部代码都必须通过依赖方式配置在这里,否则运行时会提示找不到对应的类而报错。这里有两个必须的依赖,一个是 JDBC 驱动,另一个是 Mapper 的插件。
下面看配置文件generatorConfig.xml:
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration><properties resource="config.properties"/><context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat"><property name="beginningDelimiter" value="`"/><property name="endingDelimiter" value="`"/><plugin type="tk.mybatis.mapper.generator.MapperPlugin"><property name="mappers" value="tk.mybatis.mapper.common.Mapper"/><property name="caseSensitive" value="true"/></plugin><jdbcConnection driverClass="${jdbc.driverClass}"connectionURL="${jdbc.url}"userId="${jdbc.user}"password="${jdbc.password}"></jdbcConnection><javaModelGenerator targetPackage="com.isea533.mybatis.model"targetProject="src/main/java"/><sqlMapGenerator targetPackage="mapper"targetProject="src/main/resources"/><javaClientGenerator targetPackage="com.isea533.mybatis.mapper"targetProject="src/main/java"type="XMLMAPPER"/><table tableName="user_info"><generatedKey column="id" sqlStatement="JDBC"/></table></context></generatorConfiguration>
这里和之前相差不多,只是通过 <properties> 引入了外部属性文件,在 <jdbcConnection> 配置时,使用的属性文件中的参数。
运行
在 pom.xml 这一级目录的命令行窗口执行 mvn mybatis-generator:generate即可(前提是配置了mvn)。
生成的代码
下面是自动生成的代码的例子,这些例子可以在Mybatis-Spring这里找到。
一、实体类Country
package com.isea533.mybatis.model;import javax.persistence.*;@Table(name = "country")public class Country {/*** 主键*/@Id@Column(name = "Id")@GeneratedValue(generator = "JDBC")private Integer id;/*** 名称*/private String countryname;/*** 代码*/private String countrycode;/*** 获取主键** @return Id - 主键*/public Integer getId() {return id;}/*** 设置主键** @param id 主键*/public void setId(Integer id) {this.id = id;}/*** 获取名称** @return countryname - 名称*/public String getCountryname() {return countryname;}/*** 设置名称** @param countryname 名称*/public void setCountryname(String countryname) {this.countryname = countryname;}/*** 获取代码** @return countrycode - 代码*/public String getCountrycode() {return countrycode;}/*** 设置代码** @param countrycode 代码*/public void setCountrycode(String countrycode) {this.countrycode = countrycode;}}
可以看到这里生成的注释是有意义的内容,注释来源于数据库表字段的注释。
二、Mapper接口CountryMapper
package com.isea533.mybatis.mapper;import com.isea533.mybatis.model.Country;import tk.mybatis.mapper.common.Mapper;public interface CountryMapper extends Mapper<Country> {}
接口自动继承配置的通用Mapper接口,自动包含泛型实体。
三、Mapper.xml文件CountryMapper.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.isea533.mybatis.mapper.CountryMapper"><resultMap id="BaseResultMap" type="com.isea533.mybatis.model.Country"><!--WARNING - @mbg.generated--><id column="Id" jdbcType="INTEGER" property="id" /><result column="countryname" jdbcType="VARCHAR" property="countryname" /><result column="countrycode" jdbcType="VARCHAR" property="countrycode" /></resultMap></mapper>
xml文件只包含了实体的resultMap映射配置。
4.2 代码生成器文档
代码生成器是基于 MBG 插件的,所以需要配合 MBG 使用。
一个简单的 MBG 配置如下:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration><context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat"><property name="javaFileEncoding" value="UTF-8"/><!--配置是否使用通用 Mapper 自带的注释扩展,默认 true--><!--<property name="useMapperCommentGenerator" value="false"/>--><!--通用 Mapper 插件,可以生成带注解的实体类--><plugin type="tk.mybatis.mapper.generator.MapperPlugin"><property name="mappers" value="tk.mybatis.mapper.common.Mapper,tk.mybatis.mapper.hsqldb.HsqldbMapper"/><property name="caseSensitive" value="true"/><property name="forceAnnotation" value="true"/><property name="beginningDelimiter" value="`"/><property name="endingDelimiter" value="`"/></plugin><!--通用代码生成器插件--><plugin type="tk.mybatis.mapper.generator.TemplateFilePlugin"><property name="targetProject" value="src/test/java"/><property name="targetPackage" value="test.mapper"/><property name="templatePath" value="generator/mapper.ftl"/><property name="mapperSuffix" value="Dao"/><property name="fileName" value="${tableClass.shortClassName}${mapperSuffix}.java"/></plugin><jdbcConnection driverClass="com.mysql.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/test"userId="root"password=""></jdbcConnection><!--MyBatis 生成器只需要生成 Model--><javaModelGenerator targetPackage="test.model" targetProject="./src/test/java"/><table tableName="user%"><generatedKey column="id" sqlStatement="JDBC"/></table></context></generatorConfiguration>
在这个配置中,我们只关注 tk.mybatis.mapper.generator.TemplateFilePlugin。
4.2.1 基于模板的插件 TemplateFilePlugin
这个插件中除了几个必备的属性外,还可以增加任意的属性,属性完全是为了给模板提供数据。
先看一个基本完整的配置:
<!--测试输出单个文件,每个表都会生成一个对应的文件--><plugin type="tk.mybatis.mapper.generator.TemplateFilePlugin"><property name="singleMode" value="false"/><property name="targetProject" value="src/test/resources"/><property name="targetPackage" value=""/><property name="templatePath" value="generator/test-one.ftl"/><property name="fileName" value="${tableClass.shortClassName}Test.txt"/><!--默认值是下面这个,可以不配置--><property name="templateFormatter" value="tk.mybatis.mapper.generator.formatter.FreemarkerTemplateFormatter"/></plugin>
下面介绍必备的属性。
1. targetProject
用于指定目标项目,一般是 src/main/java 或者 src/main/resource 这样的目录。
还可以是 src/test/java 或者 src/test/resource 这样的目录。
在多模块项目中,还能通过相对路径指定为其他的目录,例如:
<property name="targetProject" value="../myproject-api/src/main/java"/>
这个属性值有一个要求,就是目录必须存在,否则不会生成代码!
2. targetPackage
用于指定包的部分,虽然是这个名字,实际上就是路径。
这个属性指定的路径如果不存在,就会自动创建。
这个属性的值可以为空。
例如 mapper/admin 用于生成 mapper/admin/ 目录,或者 tk.mybatis.mapper 生成包(本质上还是目录)。
这个属性还有一个特殊的地方,它还支持使用模板,就和下面的 fileName 一样,举个简单的使用场景。
你可能在生成前端代码的时候,希望将表对应的 JSP 生成在自己的一个目录中,此时可以配置为:
<property name="targetPackage" value="WEB-INF/jsp/${tableClass.lowerCaseName}/"/>模板中可以用到的属性,这里都能用,其他属性后面会介绍。
通过这个路径也能看出来,配置一个插件只能根据模板在一个指定位置(targetProject 和 targetPackage 决定的目录)生成一个文件。
3. templatePath
指定模板路径,可以是任意能够通过 ClassLoader 能够获取的位置,文件类型没有限制。
例如示例中的 generator/test-one.ftl。
这个属性必须指定,否则不会生成代码!
4. fileName
这个属性用于指定生成文件的名字,这个值支持使用模板,例如上面的 ${tableClass.shortClassName}Test.txt,具体可用的属性会在后面介绍。
这个属性必须指定,否则不会生成代码!
5. templateFormatter
这个属性可选,默认使用基于 FreeMarker 的实现!
默认情况下,你需要添加下面的依赖:
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version></dependency>
默认的实现类为:tk.mybatis.mapper.generator.formatter.FreemarkerTemplateFormatter。
这个类实现了两个接口 TemplateFormatter, ListTemplateFormatter。
这俩接口分别对应下面 singleMode 参数值的 true 和 false。
也就是一个表生成一个文件,或者多个表生成一个文件。
对于一般情况下,都是第一种情况。但是在配置文件中,可能会用到多个表的信息。
如果你想使用其他模板引擎,可以自己实现上面的接口。
6. singleMode
上面已经提过,默认为 true。
一个表生成一个文件时,可用属性可以参考 generator/test-one.ftl,表的属性在 tableClass 中。
多个表生成一个文件时,可用属性可以参考 generator/test-all.ftl,所有表的属性在 tableClassSet 中,通过遍历可以获取单个的信息。
7. 其他你需要的属性
模板中需要的特殊信息都可以通过 <property> 方法设置,在模板中直接使用这里定义的属性名来使用,后面例子的中的 mapperSuffix 就是这种属性。
4.2.2 TemplateFilePlugin 配置示例
因为模板需要根据业务进行设计,所以这里只提供了两个简单的 mapper 目标和两个完整属性的示例模板。
因为一个模板只能生成一类的文件,所以如果要生成多个不同的文件,就需要配置多个插件。
这种设计很灵活,因为自由度很高,所以代价就是配置的多。 但是正常情况下,根据业务设计的一套模板基本是固定的,不会有太多变化,所以用起来并不麻烦。
例如下面的示例:
<!--通用代码生成器插件--><!--mapper接口--><plugin type="tk.mybatis.mapper.generator.TemplateFilePlugin"><property name="targetProject" value="src/test/java"/><property name="targetPackage" value="test.mapper"/><property name="templatePath" value="generator/mapper.ftl"/><property name="mapperSuffix" value="Dao"/><property name="fileName" value="${tableClass.shortClassName}${mapperSuffix}.java"/></plugin><!--mapper.xml--><plugin type="tk.mybatis.mapper.generator.TemplateFilePlugin"><property name="targetProject" value="src/test/resources"/><property name="targetPackage" value="mappers"/><property name="mapperPackage" value="test.mapper"/><property name="templatePath" value="generator/mapperXml.ftl"/><property name="mapperSuffix" value="Dao"/><property name="fileName" value="${tableClass.shortClassName}${mapperSuffix}.xml"/></plugin><!--测试输出单个文件,每个表都会生成一个对应的文件--><plugin type="tk.mybatis.mapper.generator.TemplateFilePlugin"><property name="targetProject" value="src/test/resources"/><property name="targetPackage" value=""/><property name="templatePath" value="generator/test-one.ftl"/><property name="fileName" value="${tableClass.shortClassName}Test.txt"/><!--默认值是下面这个,可以不配置--><property name="templateFormatter"value="tk.mybatis.mapper.generator.formatter.FreemarkerTemplateFormatter"/></plugin><!--测试输出整个文件,所有表都可用,一次只生成一个文件,用于聚合所有表使用--><plugin type="tk.mybatis.mapper.generator.TemplateFilePlugin"><property name="singleMode" value="false"/><property name="targetProject" value="src/test/resources"/><property name="targetPackage" value=""/><property name="templatePath" value="generator/test-all.ftl"/><property name="fileName" value="TestAll.txt"/></plugin>
前两个会生成 Dao 后缀的 Mapper 接口和 XML,其中有个针对性的参数 mapperSuffix 用于配置后缀,
还有个 mapperPackage 在生成 XML 时获取接口的包名(因为和这里的 targetPackage 可以不同)。
后两个插件用于演示所有可用的属性,而且是两种不同的模式。
在表和实体上可用的所有属性如下:
特殊:targetPackage值在 ${package} 中。<!-- 详细日期用法参考:http://freemarker.apache.org/docs/ref_builtins_date.html -->当前时间:<#assign dateTime = .now>日期:${dateTime?date}时间:${dateTime?time}格式化:${dateTime?string["yyyy-MM-dd HH:mm:ss"]}所有配置的属性信息:<#list props?keys as key>${key} - ${props[key]}</#list>实体和表的信息:表名:${tableClass.tableName}变量名:${tableClass.variableName}小写名:${tableClass.lowerCaseName}类名:${tableClass.shortClassName}全名:${tableClass.fullClassName}包名:${tableClass.packageName}列的信息:=====================================<#if tableClass.pkFields??>主键:<#list tableClass.pkFields as field>-------------------------------------列名:${field.columnName}列类型:${field.jdbcType}字段名:${field.fieldName}注释:${field.remarks}类型包名:${field.typePackage}类型短名:${field.shortTypeName}类型全名:${field.fullTypeName}是否主键:${field.identity?c}是否可空:${field.nullable?c}是否为BLOB列:${field.blobColumn?c}是否为String列:${field.stringColumn?c}是否为字符串列:${field.jdbcCharacterColumn?c}是否为日期列:${field.jdbcDateColumn?c}是否为时间列:${field.jdbcTimeColumn?c}是否为序列列:${field.sequenceColumn?c}列长度:${field.length?c}列精度:${field.scale}</#list></#if><#if tableClass.baseFields??>基础列:<#list tableClass.baseFields as field>-------------------------------------列名:${field.columnName}列类型:${field.jdbcType}字段名:${field.fieldName}注释:${field.remarks}类型包名:${field.typePackage}类型短名:${field.shortTypeName}类型全名:${field.fullTypeName}是否主键:${field.identity?c}是否可空:${field.nullable?c}是否为BLOB列:${field.blobColumn?c}是否为String列:${field.stringColumn?c}是否为字符串列:${field.jdbcCharacterColumn?c}是否为日期列:${field.jdbcDateColumn?c}是否为时间列:${field.jdbcTimeColumn?c}是否为序列列:${field.sequenceColumn?c}列长度:${field.length?c}列精度:${field.scale}</#list></#if><#if tableClass.blobFields??>Blob列:<#list tableClass.blobFields as field>-------------------------------------列名:${field.columnName}列类型:${field.jdbcType}字段名:${field.fieldName}注释:${field.remarks}类型包名:${field.typePackage}类型短名:${field.shortTypeName}类型全名:${field.fullTypeName}是否主键:${field.identity?c}是否可空:${field.nullable?c}是否为BLOB列:${field.blobColumn?c}是否为String列:${field.stringColumn?c}是否为字符串列:${field.jdbcCharacterColumn?c}是否为日期列:${field.jdbcDateColumn?c}是否为时间列:${field.jdbcTimeColumn?c}是否为序列列:${field.sequenceColumn?c}列长度:${field.length?c}列精度:${field.scale}</#list></#if>=====================================全部列(包含了pk,base,blob 字段,可用的属性和上面的一样):<#if tableClass.allFields??>列名 - 字段名<#list tableClass.allFields as field>${field.columnName} - ${field.fieldName}</#list></#if>
4.2.3 测试执行
上面示例就是本项目的测试代码,在 src/test/resources/generator/generatorConfig.xml 中。
还提供了一种 Java 编码方式运行的类,src/test/java/ 中的 tk.mybatis.mapper.generator.Generator,配置上面 xml 中的数据库信息就可以生成。
测试生成的部分结果如下。
实体:
@Table(name = "`user_info`")public class UserInfo {@Id@Column(name = "`Id`")@GeneratedValue(generator = "JDBC")private Integer id;
Dao:
package test.mapper;import test.model.UserInfo;/*** 通用 Mapper 代码生成器** @author mapper-generator*/public interface UserInfoDao extends tk.mybatis.mapper.common.Mapper<UserInfo> {}
XML:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="test.mapper.UserInfoDao"></mapper>
test-one.ftl 生成的信息如下:
目标package:当前时间:2017-11-622:00:452017-11-06 22:00:45所有配置的属性信息:targetPackage -templateFormatter - tk.mybatis.mapper.generator.formatter.FreemarkerTemplateFormattertemplatePath - generator/test-one.ftltargetProject - src/test/resourcesfileName - ${tableClass.shortClassName}Test.txt实体和表的信息:表名:user_info变量名:userInfo小写名:userinfo类名:UserInfo全名:test.model.UserInfo包名:test.model列的信息:=====================================主键:-------------------------------------列名:Id列类型:INTEGER字段名:id注释:类型包名:java.lang类型短名:Integer类型全名:java.lang.Integer是否主键:true是否可空:false是否为BLOB列:false是否为String列:false是否为字符串列:false是否为日期列:false是否为时间列:false是否为序列列:false列长度:10列精度:0基础列:-------------------------------------列名:username列类型:VARCHAR字段名:username注释:用户名类型包名:java.lang类型短名:String类型全名:java.lang.String是否主键:false是否可空:false是否为BLOB列:false是否为String列:true是否为字符串列:true是否为日期列:false是否为时间列:false是否为序列列:false列长度:32列精度:0-------------------------------------列名:password列类型:VARCHAR字段名:password注释:密码类型包名:java.lang类型短名:String类型全名:java.lang.String是否主键:false是否可空:true是否为BLOB列:false是否为String列:true是否为字符串列:true是否为日期列:false是否为时间列:false是否为序列列:false列长度:32列精度:0-------------------------------------列名:usertype列类型:VARCHAR字段名:usertype注释:用户类型类型包名:java.lang类型短名:String类型全名:java.lang.String是否主键:false是否可空:true是否为BLOB列:false是否为String列:true是否为字符串列:true是否为日期列:false是否为时间列:false是否为序列列:false列长度:2列精度:0-------------------------------------列名:enabled列类型:INTEGER字段名:enabled注释:是否可用类型包名:java.lang类型短名:Integer类型全名:java.lang.Integer是否主键:false是否可空:true是否为BLOB列:false是否为String列:false是否为字符串列:false是否为日期列:false是否为时间列:false是否为序列列:false列长度:10列精度:0-------------------------------------列名:realname列类型:VARCHAR字段名:realname注释:真实姓名类型包名:java.lang类型短名:String类型全名:java.lang.String是否主键:false是否可空:true是否为BLOB列:false是否为String列:true是否为字符串列:true是否为日期列:false是否为时间列:false是否为序列列:false列长度:32列精度:0-------------------------------------列名:qq列类型:VARCHAR字段名:qq注释:QQ类型包名:java.lang类型短名:String类型全名:java.lang.String是否主键:false是否可空:true是否为BLOB列:false是否为String列:true是否为字符串列:true是否为日期列:false是否为时间列:false是否为序列列:false列长度:14列精度:0-------------------------------------列名:email列类型:VARCHAR字段名:email注释:类型包名:java.lang类型短名:String类型全名:java.lang.String是否主键:false是否可空:true是否为BLOB列:false是否为String列:true是否为字符串列:true是否为日期列:false是否为时间列:false是否为序列列:false列长度:100列精度:0-------------------------------------列名:tel列类型:VARCHAR字段名:tel注释:联系电话类型包名:java.lang类型短名:String类型全名:java.lang.String是否主键:false是否可空:true是否为BLOB列:false是否为String列:true是否为字符串列:true是否为日期列:false是否为时间列:false是否为序列列:false列长度:255列精度:0Blob列:=====================================全部列:列名 - 字段名Id - idusername - usernamepassword - passwordusertype - usertypeenabled - enabledrealname - realnameqq - qqemail - emailtel - tel
4.2.4 最后
基础的代码生成器是很简单的,和 Java 拼字符串输出很像,这里只是使用了模板。
几乎所有人都在 JSP 中用过的 EL 就是一种模板,可能你会 <c:forEach 这种,但是联想不到这里的代码生成器而已。
后续会在 https://github.com/abel533/Mybatis-Spring 项目中提供一套模板做为示例。
五、扩展通用接口
项目中提供了大量现成的方法,这些方法可以作为扩展时的参考。
例如 selectAll 方法。
首先定义接口:
@RegisterMapperpublic interface SelectAllMapper<T> {/*** 查询全部结果** @return*/@SelectProvider(type = MySelectProvider.class, method = "dynamicSQL")List<T> selectAll();}
其中 MySelectProvider 是你要实现的一个类,该类需要继承 MapperTemplate。
@RegisterMapper 注解可以避免 mappers 参数配置,通用 Mapper 检测到该接口被继承时,会自动注册。
import org.apache.ibatis.mapping.MappedStatement;import tk.mybatis.mapper.mapperhelper.MapperHelper;import tk.mybatis.mapper.mapperhelper.MapperTemplate;import tk.mybatis.mapper.mapperhelper.SqlHelper;public class MySelectProvider extends MapperTemplate {public BaseSelectProvider(Class<?> mapperClass, MapperHelper mapperHelper) {super(mapperClass, mapperHelper);}/*** 查询全部结果** @param ms* @return*/public String selectAll(MappedStatement ms) {final Class<?> entityClass = getEntityClass(ms);//修改返回值类型为实体类型setResultType(ms, entityClass);StringBuilder sql = new StringBuilder();sql.append(SqlHelper.selectAllColumns(entityClass));sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));sql.append(SqlHelper.orderByDefault(entityClass));return sql.toString();}}
其中 selectAll 方法名要和接口中定义的方法名一致。其次就是该方法的参数为 MappedStatement 类型。
在 selectAll 方法中,首先是获取了当前接口的实体类型:
final Class<?> entityClass = getEntityClass(ms);
因为接口返回值类型为 List<T>,MyBatis 会认为返回值类型为 List<Object>,这和我们想要的实体类型不一样,所以下一行代码就是设置返回值类型:
setResultType(ms, entityClass);
注意,只有返回 T 或者 List 时需要设置,返回 int 类型时不需要设置。
接下来就是纯粹的拼接 XML 形式的 SQL 了。
//select col1,col2...sql.append(SqlHelper.selectAllColumns(entityClass));//from tablename - 支持动态表名sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));//order by xxxsql.append(SqlHelper.orderByDefault(entityClass));
这是其中最简单的一个方法实现。当你想要实现某种方法时,可以从已有的例子中找一个最接近的方法,在此基础上进行修改。
