最近在做创业项目的时候因为有比较多的新需求,需要频繁基于DDL
生成Mybatis
适合的实体、Mapper
接口和映射文件。其中,代码生成器是MyBatis Generator(MBG)
,用到了Mybatis-Generator-Core
相关依赖,这里通过一篇文章详细地分析这个代码生成器的使用方式。本文编写的时候使用的Mybatis-Generator
版本为1.4.0
,其他版本没有进行过调研。
Mybatis-Generator
的运行方式有很多种:
mybatis-generator-core-x.x.x.jar
和其XML
配置文件,通过命令行运行。Ant
的Task
结合其XML
配置文件运行。Maven
插件运行。Java
代码和其XML
配置文件运行。Java
代码和编程式配置运行。Eclipse Feature
运行。这里只介绍通过Maven
插件运行和通过Java
代码和其XML
配置文件运行这两种方式,两种方式有个特点:都要提前编写好XML
配置文件。个人感觉XML
配置文件相对直观,后文会花大量篇幅去说明XML
配置文件中的配置项及其作用。这里先注意一点:默认的配置文件为ClassPath:generatorConfig.xml
。
通过编码方式去运行插件先需要引入mybatis-generator-core
依赖,编写本文的时候最新的版本为:
<dependency>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-coreartifactId>
<version>1.4.0version>
dependency>
假设编写好的XML
配置文件是ClassPath
下的generator-configuration.xml
,那么使用代码生成器的编码方式大致如下:
List<String> warnings = new ArrayList<>();
// 如果已经存在生成过的文件是否进行覆盖
boolean overwrite = true;
File configFile = new File("ClassPath路径/generator-configuration.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator generator = new MyBatisGenerator(config, callback, warnings);
generator.generate(null);
如果使用Maven
插件,那么不需要引入mybatis-generator-core
依赖,只需要引入一个Maven
的插件mybatis-generator-maven-plugin
:
<plugins>
<plugin>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-maven-pluginartifactId>
<version>1.4.0version>
<executions>
<execution>
<id>Generate MyBatis Artifactsid>
<goals>
<goal>generategoal>
goals>
execution>
executions>
<configuration>
<verbose>trueverbose>
<overwrite>trueoverwrite>
<configurationFile>${basedir}/src/main/resources/generator-configuration.xmlconfigurationFile>
configuration>
plugin>
plugins>
mybatis-generator-maven-plugin
的更详细配置和可选参数可以参考:Running With Maven。插件配置完毕之后,使用下面的命令即可运行:
mvn mybatis-generator:generate
XML
配置文件才是Mybatis-Generator
的核心,它用于控制代码生成的所有行为。所有非标签独有的公共配置的Key
可以在mybatis-generator-core
的PropertyRegistry
类中找到。下面是一个相对完整的配置文件的模板:
<generatorConfiguration>
<properties resource="db.properties"/>
<classPathEntry location="/Program Files/IBM/SQLLIB/java/db2java.zip" />
<context id="DB2Tables" targetRuntime="MyBatis3">
<jdbcConnection driverClass="COM.ibm.db2.jdbc.app.DB2Driver"
connectionURL="jdbc:db2:TEST"
userId="db2admin"
password="db2admin">
jdbcConnection>
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
commentGenerator>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
javaTypeResolver>
<javaModelGenerator targetPackage="test.model" targetProject="\MBGTestProject\src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
javaModelGenerator>
<sqlMapGenerator targetPackage="test.xml" targetProject="\MBGTestProject\src">
<property name="enableSubPackages" value="true" />
sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER" targetPackage="test.dao" targetProject="\MBGTestProject\src">
<property name="enableSubPackages" value="true" />
javaClientGenerator>
<table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" >
<property name="useActualColumnNames" value="true"/>
<generatedKey column="ID" sqlStatement="DB2" identity="true" />
<columnOverride column="DATE_FIELD" property="startDate" />
<ignoreColumn column="FRED" />
<columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" />
table>
context>
generatorConfiguration>
配置文件中,最外层的标签为
,它的子标签包括:
标签,用于指定全局配置文件,下面可以通过占位符的形式读取
指定文件中的值。
标签,
只有一个location
属性,用于指定数据源驱动包(jar
或者zip
)的绝对路径,具体选择什么驱动包取决于连接什么类型的数据源。
标签,用于运行时的解析模式和具体的代码生成行为,所以这个标签里面的配置是最重要的。下面分别列举和分析一下
标签和它的主要子标签的一些属性配置和功能。
标签在mybatis-generator-core
中对应的实现类为org.mybatis.generator.config.Context
,它除了大量的子标签配置之外,比较主要的属性是:
id
:Context
示例的唯一ID
,用于输出错误信息时候作为唯一标记。targetRuntime
:用于执行代码生成模式。defaultModelType
:控制Domain
类的生成行为。执行引擎为MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置,可选值:
conditional
:默认值,类似hierarchical
,但是只有一个主键的时候会合并所有属性生成在同一个类。flat
:所有内容全部生成在一个对象中。hierarchical
:键生成一个XXKey对象,Blob等单独生成一个对象,其他简单属性在一个对象中。targetRuntime
属性的可选值比较多,这里做个简单的小结:
属性 | 功能描述 |
---|---|
MyBatis3DynamicSql |
默认值,兼容JDK8+ 和MyBatis 3.4.2+ ,不会生成XML 映射文件,忽略 的配置项,也就是Mapper 全部注解化,依赖于MyBatis Dynamic SQL 类库 |
MyBatis3Kotlin |
行为类似于MyBatis3DynamicSql ,不过兼容Kotlin 的代码生成 |
MyBatis3 |
提供基本的基于动态SQL 的CRUD 方法和XXXByExample 方法,会生成XML 映射文件 |
MyBatis3Simple |
提供基本的基于动态SQL 的CRUD 方法,会生成XML 映射文件 |
MyBatis3DynamicSqlV1 |
已经过时,不推荐使用 |
笔者偏向于把SQL
文件和代码分离,所以一般选用MyBatis3
或者MyBatis3Simple
。例如:
<context id="default" targetRuntime="MyBatis3">
标签支持0或N个
标签,
的可选属性有:
property属性 | 功能描述 | 默认值 | 备注 |
---|---|---|---|
autoDelimitKeywords |
是否使用分隔符号括住数据库关键字 | false |
例如MySQL 中会使用反引号括住关键字 |
beginningDelimiter |
分隔符号的开始符号 | " |
|
endingDelimiter |
分隔符号的结束号 | " |
|
javaFileEncoding |
文件的编码 | 系统默认值 |
来源于java.nio.charset.Charset |
javaFormatter |
类名和文件格式化器 | DefaultJavaFormatter |
见JavaFormatter 和DefaultJavaFormatter |
targetJava8 |
是否JDK8和启动其特性 | true |
|
kotlinFileEncoding |
Kotlin 文件编码 |
系统默认值 |
来源于java.nio.charset.Charset |
kotlinFormatter |
Kotlin 类名和文件格式化器 |
DefaultKotlinFormatter |
见KotlinFormatter 和DefaultKotlinFormatter |
xmlFormatter |
XML 文件格式化器 |
DefaultXmlFormatter |
见XmlFormatter 和DefaultXmlFormatter |
标签用于指定数据源的连接信息,它在mybatis-generator-core
中对应的实现类为org.mybatis.generator.config.JDBCConnectionConfiguration
,主要属性包括:
属性 | 功能描述 | 是否必须 |
---|---|---|
driverClass |
数据源驱动的全类名 | Y |
connectionURL |
JDBC 的连接URL |
Y |
userId |
连接到数据源的用户名 | N |
password |
连接到数据源的密码 | N |
标签是可选的,用于控制生成的实体的注释内容。它在mybatis-generator-core
中对应的实现类为org.mybatis.generator.internal.DefaultCommentGenerator
,可以通过可选的type
属性指定一个自定义的CommentGenerator
实现。
标签支持0或N个
标签,
的可选属性有:
property属性 | 功能描述 | 默认值 |
---|---|---|
suppressAllComments |
是否生成注释 | false |
suppressDate |
是否在注释中添加生成的时间戳 | false |
dateFormat |
配合suppressDate 使用,指定输出时间戳的格式 |
java.util.Date#toString() |
addRemarkComments |
是否输出表和列的Comment 信息 |
false |
笔者建议保持默认值,也就是什么注释都不输出,生成代码干净的实体。
标签是
的子标签,用于解析和计算数据库列类型和Java
类型的映射关系,该标签只包含一个type
属性,用于指定org.mybatis.generator.api.JavaTypeResolver
接口的实现类。
标签支持0或N个
标签,
的可选属性有:
property属性 | 功能描述 | 默认值 |
---|---|---|
forceBigDecimals |
是否强制把所有的数字类型强制使用java.math.BigDecimal 类型表示 |
false |
useJSR310Types |
是否支持JSR310 ,主要是JSR310 的新日期类型 |
false |
如果useJSR310Types
属性设置为true
,那么生成代码的时候类型映射关系如下(主要针对日期时间类型):
数据库(JDBC)类型 | Java类型 |
---|---|
DATE |
java.time.LocalDate |
TIME |
java.time.LocalTime |
TIMESTAMP |
java.time.LocalDateTime |
TIME_WITH_TIMEZONE |
java.time.OffsetTime |
TIMESTAMP_WITH_TIMEZONE |
java.time.OffsetDateTime |
引入mybatis-generator-core
后,可以查看JavaTypeResolver
的默认实现为JavaTypeResolverDefaultImpl
,从它的源码可以得知一些映射关系:
BIGINT --> Long
BIT --> Boolean
INTEGER --> Integer
SMALLINT --> Short
TINYINT --> Byte
......
有些时候,我们希望INTEGER
、SMALLINT
和TINYINT
都映射为Integer
,那么我们需要覆盖JavaTypeResolverDefaultImpl
的构造方法:
public class DefaultJavaTypeResolver extends JavaTypeResolverDefaultImpl {
public DefaultJavaTypeResolver() {
super();
typeMap.put(Types.SMALLINT, new JdbcTypeInformation("SMALLINT",
new FullyQualifiedJavaType(Integer.class.getName())));
typeMap.put(Types.TINYINT, new JdbcTypeInformation("TINYINT",
new FullyQualifiedJavaType(Integer.class.getName())));
}
}
注意一点的是这种自定义实现JavaTypeResolver
接口的方式使用编程式运行MBG
会相对方便,如果需要使用Maven
插件运行,那么需要把上面的DefaultJavaTypeResolver
类打包到插件中。
标签是
的子标签,主要用于控制实体(Model
)类的代码生成行为。它支持的属性如下:
属性 | 功能描述 | 是否必须 | 备注 |
---|---|---|---|
targetPackage |
生成的实体类的包名 | Y |
例如club.throwable.model |
targetProject |
生成的实体类文件相对于项目(根目录)的位置 | Y |
例如src/main/java |
标签支持0或N个
标签,
的可选属性有:
property属性 | 功能描述 | 默认值 | 备注 |
---|---|---|---|
constructorBased |
是否生成一个带有所有字段属性的构造函数 | false |
MyBatis3Kotlin 模式下忽略此属性配置 |
enableSubPackages |
是否允许通过Schema 生成子包 |
false |
如果为true ,例如包名为club.throwable ,如果Schema 为xyz ,那么实体类文件最终会生成在club.throwable.xyz 目录 |
exampleTargetPackage |
生成的伴随实体类的Example 类的包名 |
- | - |
exampleTargetProject |
生成的伴随实体类的Example 类文件相对于项目(根目录)的位置 |
- | - |
immutable |
是否不可变 | false |
如果为true ,则不会生成Setter 方法,所有字段都使用final 修饰,提供一个带有所有字段属性的构造函数 |
rootClass |
为生成的实体类添加父类 | - | 通过value 指定父类的全类名即可 |
trimStrings |
Setter 方法是否对字符串类型进行一次trim 操作 |
false |
- |
标签是
的子标签,主要用于控制Mapper
接口的代码生成行为。它支持的属性如下:
属性 | 功能描述 | 是否必须 | 备注 |
---|---|---|---|
type |
Mapper 接口生成策略 |
Y |
标签的targetRuntime 属性为MyBatis3DynamicSql 或者MyBatis3Kotlin 时此属性配置忽略 |
targetPackage |
生成的Mapper 接口的包名 |
Y |
例如club.throwable.mapper |
targetProject |
生成的Mapper 接口文件相对于项目(根目录)的位置 |
Y |
例如src/main/java |
type
属性的可选值如下:
ANNOTATEDMAPPER
:Mapper
接口生成的时候依赖于注解和SqlProviders
(也就是纯注解实现),不会生成XML
映射文件。XMLMAPPER
:Mapper
接口生成接口方法,对应的实现代码生成在XML
映射文件中(也就是纯映射文件实现)。MIXEDMAPPER
:Mapper
接口生成的时候复杂的方法实现生成在XML
映射文件中,而简单的实现通过注解和SqlProviders
实现(也就是注解和映射文件混合实现)。注意两点:
标签的targetRuntime
属性指定为MyBatis3Simple
的时候,type
只能选用ANNOTATEDMAPPER
或者XMLMAPPER
。
标签的targetRuntime
属性指定为MyBatis3
的时候,type
可以选用ANNOTATEDMAPPER
、XMLMAPPER
或者MIXEDMAPPER
。
标签支持0或N个
标签,
的可选属性有:
property属性 | 功能描述 | 默认值 | 备注 |
---|---|---|---|
enableSubPackages |
是否允许通过Schema 生成子包 |
false |
如果为true ,例如包名为club.throwable ,如果Schema 为xyz ,那么Mapper 接口文件最终会生成在club.throwable.xyz 目录 |
useLegacyBuilder |
是否通过SQL Builder 生成动态SQL |
false |
|
rootInterface |
为生成的Mapper 接口添加父接口 |
- | 通过value 指定父接口的全类名即可 |
标签是
的子标签,主要用于控制XML
映射文件的代码生成行为。它支持的属性如下:
属性 | 功能描述 | 是否必须 | 备注 |
---|---|---|---|
targetPackage |
生成的XML 映射文件的包名 |
Y |
例如mappings |
targetProject |
生成的XML 映射文件相对于项目(根目录)的位置 |
Y |
例如src/main/resources |
标签支持0或N个
标签,
的可选属性有:
property属性 | 功能描述 | 默认值 | 备注 |
---|---|---|---|
enableSubPackages |
是否允许通过Schema 生成子包 |
false |
- |
标签是
的子标签,用于引入一些插件对代码生成的一些特性进行扩展,该标签只包含一个type
属性,用于指定org.mybatis.generator.api.Plugin
接口的实现类。内置的插件实现见Supplied Plugins。例如:引入org.mybatis.generator.plugins.SerializablePlugin
插件会让生成的实体类自动实现java.io.Serializable
接口并且添加serialVersionUID
属性。
如果需要深度定制一些代码生成行为,建议引入 假设项目的结构如下: 下面会基于此前提举三个例子。编写基础的 使用纯注解需要引入 需要修改两个位置: 运行结果会生成三个类: 极简 生成三个文件: 笔者喜欢把所有的非长整型的数字,统一使用 此时最好使用编程式运行代码生成器,修改 运行方法代码如下: 数据库的 本文相对详尽地介绍了 参考资料: (本文完 c-5-d e-a-20191216 1:00)标签是
的子标签,主要用于配置要生成代码的数据库表格,定制一些代码生成行为等等。它支持的属性众多,列举如下:
属性
功能描述
是否必须
备注
tableName
数据库表名称
Y
例如
t_order
schema
数据库
Schema
N
-
catalog
数据库
Catalog
N
-
alias
表名称标签
N
如果指定了此值,则查询列的时候结果格式为
alias_column
domainObjectName
表对应的实体类名称,可以通过
.
指定包路径N
如果指定了
bar.User
,则包名为bar
,实体类名称为User
mapperName
表对应的
Mapper
接口类名称,可以通过.
指定包路径N
如果指定了
bar.UserMapper
,则包名为bar
,Mapper
接口类名称为UserMapper
sqlProviderName
动态
SQL
提供类SqlProvider
的类名称N
-
enableInsert
是否允许生成
insert
方法N
默认值为
true
,执行引擎为MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置
enableSelectByPrimaryKey
是否允许生成
selectByPrimaryKey
方法N
默认值为
true
,执行引擎为MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置
enableSelectByExample
是否允许生成
selectByExample
方法N
默认值为
true
,执行引擎为MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置
enableUpdateByPrimaryKey
是否允许生成
updateByPrimaryKey
方法N
默认值为
true
,执行引擎为MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置
enableDeleteByPrimaryKey
是否允许生成
deleteByPrimaryKey
方法N
默认值为
true
,执行引擎为MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置
enableDeleteByExample
是否允许生成
deleteByExample
方法N
默认值为
true
,执行引擎为MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置
enableCountByExample
是否允许生成
countByExample
方法N
默认值为
true
,执行引擎为MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置
enableUpdateByExample
是否允许生成
updateByExample
方法N
默认值为
true
,执行引擎为MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置
selectByPrimaryKeyQueryId
value
指定对应的主键列提供列表查询功能N
执行引擎为
MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置
selectByExampleQueryId
value
指定对应的查询ID
提供列表查询功能N
执行引擎为
MyBatis3DynamicSql
或者MyBatis3Kotlin
时忽略此配置
modelType
覆盖
的defaultModelType
属性N
见
的defaultModelType
属性
escapeWildcards
是否对通配符进行转义
N
-
delimitIdentifiers
标记匹配表名称的时候是否需要使用分隔符去标记生成的SQL
N
-
delimitAllColumns
是否所有的列都添加分隔符
N
默认值为
false
,如果设置为true
,所有列名会添加起始和结束分隔符标签支持0或N个
标签,
的可选属性有:
property属性
功能描述
默认值
备注
constructorBased
是否为实体类生成一个带有所有字段的构造函数
false
执行引擎为
MyBatis3Kotlin
的时候此属性忽略
ignoreQualifiersAtRuntime
是否在运行时忽略别名
false
如果为
true
,则不会在生成表的时候把schema
和catalog
作为表的前缀
immutable
实体类是否不可变
false
执行引擎为
MyBatis3Kotlin
的时候此属性忽略
modelOnly
是否仅仅生成实体类
false
-
rootClass
如果配置此属性,则实体类会继承此指定的超类
-
如果有主键属性会把主键属性在超类生成
rootInterface
如果配置此属性,则实体类会实现此指定的接口
-
执行引擎为
MyBatis3Kotlin
或者MyBatis3DynamicSql
的时候此属性忽略
runtimeCatalog
指定运行时的
Catalog
-
当生成表和运行时的表的
Catalog
不一样的时候可以使用该属性进行配置
runtimeSchema
指定运行时的
Schema
-
当生成表和运行时的表的
Schema
不一样的时候可以使用该属性进行配置
runtimeTableName
指定运行时的表名称
-
当生成表和运行时的表的表名称不一样的时候可以使用该属性进行配置
selectAllOrderByClause
指定字句内容添加到
selectAll()
方法的order by
子句之中-
执行引擎为
MyBatis3Simple
的时候此属性才适用
trimStrings
实体类的字符串类型属性会做
trim
处理-
执行引擎为
MyBatis3Kotlin
的时候此属性忽略
useActualColumnNames
是否使用列名作为实体类的属性名
false
-
useColumnIndexes
XML
映射文件中生成的ResultMap
使用列索引定义而不是列名称false
执行引擎为
MyBatis3Kotlin
或者MyBatis3DynamicSql
的时候此属性忽略
useCompoundPropertyNames
是否把列名和列备注拼接起来生成实体类属性名
false
-
标签还支持众多的非
property
的子标签:
用于指定主键生成的规则,指定此标签后会生成一个
标签:
<generatedKey column="id" sqlStatement="MySql" type="post" identity="true" />
用于指定实体类重命名规则:
<domainObjectRenamingRule searchString="^Sys" replaceString=""/>
用于指定列重命名规则:
<columnRenamingRule searchString="^CUST_" replaceString=""/>
用于指定具体列的覆盖映射规则:
<columnOverride column="customer_name" property="customerName" javaType="" jdbcType="" typeHandler="" delimitedColumnName="" isGeneratedAlways="">
<property name="trimStrings" value="true"/>
<columnOverride/>
用于指定忽略生成的列:<ignoreColumn column="version" delimitedColumnName="false"/>
实战
mybatis-generator-core
并且通过编程式执行代码生成方法,否则可以选用Maven
插件。假设我们在本地数据local
有一张t_order
表如下:CREATE TABLE `t_order`
(
id BIGINT UNSIGNED PRIMARY KEY COMMENT '主键',
order_id VARCHAR(64) NOT NULL COMMENT '订单ID',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
amount DECIMAL(10, 2) NOT NULL DEFAULT 0 COMMENT '金额',
order_status TINYINT NOT NULL DEFAULT 0 COMMENT '订单状态',
UNIQUE uniq_order_id (`order_id`)
) COMMENT '订单表';
mbg-sample
- main
- java
- club
- throwable
- resources
XML
配置文件:
<generatorConfiguration>
<classPathEntry
location="I:\Develop\Maven-Repository\mysql\mysql-connector-java\5.1.48\mysql-connector-java-5.1.48.jar"/>
<context id="default" targetRuntime="这里选择合适的引擎">
<property name="javaFileEncoding" value="UTF-8"/>
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
commentGenerator>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/local"
userId="root"
password="root">
jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
javaTypeResolver>
<javaModelGenerator targetPackage="club.throwable.entity" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
javaModelGenerator>
<sqlMapGenerator targetPackage="mappings" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
sqlMapGenerator>
<javaClientGenerator type="这里选择合适的Mapper类型" targetPackage="club.throwable.dao" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
javaClientGenerator>
<table tableName="t_order"
enableCountByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
enableUpdateByExample="false"
domainObjectName="Order"
mapperName="OrderMapper">
<generatedKey column="id" sqlStatement="MySql"/>
table>
context>
generatorConfiguration>
纯注解
mybatis-dynamic-sql
:<dependency>
<groupId>org.mybatis.dynamic-sqlgroupId>
<artifactId>mybatis-dynamic-sqlartifactId>
<version>1.1.4version>
dependency>
<context id="default" targetRuntime="MyBatis3DynamicSql">
...
// club.throwable.entity
public class Order {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Long id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String orderId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private BigDecimal amount;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Byte orderStatus;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Long getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Long id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getOrderId() {
return orderId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setOrderId(String orderId) {
this.orderId = orderId;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Date getCreateTime() {
return createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public BigDecimal getAmount() {
return amount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Byte getOrderStatus() {
return orderStatus;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setOrderStatus(Byte orderStatus) {
this.orderStatus = orderStatus;
}
}
// club.throwable.dao
public final class OrderDynamicSqlSupport {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final Order order = new Order();
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Long> id = order.id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<String> orderId = order.orderId;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Date> createTime = order.createTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<BigDecimal> amount = order.amount;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final SqlColumn<Byte> orderStatus = order.orderStatus;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public static final class Order extends SqlTable {
public final SqlColumn<Long> id = column("id", JDBCType.BIGINT);
public final SqlColumn<String> orderId = column("order_id", JDBCType.VARCHAR);
public final SqlColumn<Date> createTime = column("create_time", JDBCType.TIMESTAMP);
public final SqlColumn<BigDecimal> amount = column("amount", JDBCType.DECIMAL);
public final SqlColumn<Byte> orderStatus = column("order_status", JDBCType.TINYINT);
public Order() {
super("t_order");
}
}
}
@Mapper
public interface OrderMapper {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
BasicColumn[] selectList = BasicColumn.columnList(id, orderId, createTime, amount, orderStatus);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
long count(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@DeleteProvider(type=SqlProviderAdapter.class, method="delete")
int delete(DeleteStatementProvider deleteStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insert")
@SelectKey(statement="SELECT LAST_INSERT_ID()", keyProperty="record.id", before=true, resultType=Long.class)
int insert(InsertStatementProvider<Order> insertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@Results(id="OrderResult", value = {
@Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true),
@Result(column="order_id", property="orderId", jdbcType=JdbcType.VARCHAR),
@Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP),
@Result(column="amount", property="amount", jdbcType=JdbcType.DECIMAL),
@Result(column="order_status", property="orderStatus", jdbcType=JdbcType.TINYINT)
})
Optional<Order> selectOne(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@Results(id="OrderResult", value = {
@Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true),
@Result(column="order_id", property="orderId", jdbcType=JdbcType.VARCHAR),
@Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP),
@Result(column="amount", property="amount", jdbcType=JdbcType.DECIMAL),
@Result(column="order_status", property="orderStatus", jdbcType=JdbcType.TINYINT)
})
List<Order> selectMany(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@UpdateProvider(type=SqlProviderAdapter.class, method="update")
int update(UpdateStatementProvider updateStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default long count(CountDSLCompleter completer) {
return MyBatis3Utils.countFrom(this::count, order, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int delete(DeleteDSLCompleter completer) {
return MyBatis3Utils.deleteFrom(this::delete, order, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int deleteByPrimaryKey(Long id_) {
return delete(c ->
c.where(id, isEqualTo(id_))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insert(Order record) {
return MyBatis3Utils.insert(this::insert, record, order, c ->
c.map(id).toProperty("id")
.map(orderId).toProperty("orderId")
.map(createTime).toProperty("createTime")
.map(amount).toProperty("amount")
.map(orderStatus).toProperty("orderStatus")
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertSelective(Order record) {
return MyBatis3Utils.insert(this::insert, record, order, c ->
c.map(id).toProperty("id")
.map(orderId).toPropertyWhenPresent("orderId", record::getOrderId)
.map(createTime).toPropertyWhenPresent("createTime", record::getCreateTime)
.map(amount).toPropertyWhenPresent("amount", record::getAmount)
.map(orderStatus).toPropertyWhenPresent("orderStatus", record::getOrderStatus)
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional<Order> selectOne(SelectDSLCompleter completer) {
return MyBatis3Utils.selectOne(this::selectOne, selectList, order, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default List<Order> select(SelectDSLCompleter completer) {
return MyBatis3Utils.selectList(this::selectMany, selectList, order, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default List<Order> selectDistinct(SelectDSLCompleter completer) {
return MyBatis3Utils.selectDistinct(this::selectMany, selectList, order, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional<Order> selectByPrimaryKey(Long id_) {
return selectOne(c ->
c.where(id, isEqualTo(id_))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int update(UpdateDSLCompleter completer) {
return MyBatis3Utils.update(this::update, order, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
static UpdateDSL<UpdateModel> updateAllColumns(Order record, UpdateDSL<UpdateModel> dsl) {
return dsl.set(id).equalTo(record::getId)
.set(orderId).equalTo(record::getOrderId)
.set(createTime).equalTo(record::getCreateTime)
.set(amount).equalTo(record::getAmount)
.set(orderStatus).equalTo(record::getOrderStatus);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
static UpdateDSL<UpdateModel> updateSelectiveColumns(Order record, UpdateDSL<UpdateModel> dsl) {
return dsl.set(id).equalToWhenPresent(record::getId)
.set(orderId).equalToWhenPresent(record::getOrderId)
.set(createTime).equalToWhenPresent(record::getCreateTime)
.set(amount).equalToWhenPresent(record::getAmount)
.set(orderStatus).equalToWhenPresent(record::getOrderStatus);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKey(Order record) {
return update(c ->
c.set(orderId).equalTo(record::getOrderId)
.set(createTime).equalTo(record::getCreateTime)
.set(amount).equalTo(record::getAmount)
.set(orderStatus).equalTo(record::getOrderStatus)
.where(id, isEqualTo(record::getId))
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKeySelective(Order record) {
return update(c ->
c.set(orderId).equalToWhenPresent(record::getOrderId)
.set(createTime).equalToWhenPresent(record::getCreateTime)
.set(amount).equalToWhenPresent(record::getAmount)
.set(orderStatus).equalToWhenPresent(record::getOrderStatus)
.where(id, isEqualTo(record::getId))
);
}
}
极简XML映射文件
XML
映射文件生成只需要简单修改配置文件:<context id="default" targetRuntime="MyBatis3Simple">
...
// club.throwable.entity
public class Order {
private Long id;
private String orderId;
private Date createTime;
private BigDecimal amount;
private Byte orderStatus;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Byte getOrderStatus() {
return orderStatus;
}
public void setOrderStatus(Byte orderStatus) {
this.orderStatus = orderStatus;
}
}
// club.throwable.dao
public interface OrderMapper {
int deleteByPrimaryKey(Long id);
int insert(Order record);
Order selectByPrimaryKey(Long id);
List<Order> selectAll();
int updateByPrimaryKey(Order record);
}
// mappings
<?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="club.throwable.dao.OrderMapper">
<resultMap id="BaseResultMap" type="club.throwable.entity.Order">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="order_id" jdbcType="VARCHAR" property="orderId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="amount" jdbcType="DECIMAL" property="amount"/>
<result column="order_status" jdbcType="TINYINT" property="orderStatus"/>
</resultMap>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
delete
from t_order
where id = #{
id,jdbcType=BIGINT}
</delete>
<insert id="insert" parameterType="club.throwable.entity.Order">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
insert into t_order (order_id, create_time, amount,
order_status)
values (#{
orderId,jdbcType=VARCHAR}, #{
createTime,jdbcType=TIMESTAMP}, #{
amount,jdbcType=DECIMAL},
#{
orderStatus,jdbcType=TINYINT})
</insert>
<update id="updateByPrimaryKey" parameterType="club.throwable.entity.Order">
update t_order
set order_id = #{
orderId,jdbcType=VARCHAR},
create_time = #{
createTime,jdbcType=TIMESTAMP},
amount = #{
amount,jdbcType=DECIMAL},
order_status = #{
orderStatus,jdbcType=TINYINT}
where id = #{
id,jdbcType=BIGINT}
</update>
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
select id, order_id, create_time, amount, order_status
from t_order
where id = #{
id,jdbcType=BIGINT}
</select>
<select id="selectAll" resultMap="BaseResultMap">
select id, order_id, create_time, amount, order_status
from t_order
</select>
<resultMap id="BaseResultMap" type="club.throwable.entity.Order">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="order_id" jdbcType="VARCHAR" property="orderId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="amount" jdbcType="DECIMAL" property="amount"/>
<result column="order_status" jdbcType="TINYINT" property="orderStatus"/>
</resultMap>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
delete
from t_order
where id = #{
id,jdbcType=BIGINT}
</delete>
<insert id="insert" parameterType="club.throwable.entity.Order">
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
insert into t_order (id, order_id, create_time,
amount, order_status)
values (#{
id,jdbcType=BIGINT}, #{
orderId,jdbcType=VARCHAR}, #{
createTime,jdbcType=TIMESTAMP},
#{
amount,jdbcType=DECIMAL}, #{
orderStatus,jdbcType=TINYINT})
</insert>
<update id="updateByPrimaryKey" parameterType="club.throwable.entity.Order">
update t_order
set order_id = #{
orderId,jdbcType=VARCHAR},
create_time = #{
createTime,jdbcType=TIMESTAMP},
amount = #{
amount,jdbcType=DECIMAL},
order_status = #{
orderStatus,jdbcType=TINYINT}
where id = #{
id,jdbcType=BIGINT}
</update>
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
select id, order_id, create_time, amount, order_status
from t_order
where id = #{
id,jdbcType=BIGINT}
</select>
<select id="selectAll" resultMap="BaseResultMap">
select id, order_id, create_time, amount, order_status
from t_order
</select>
</mapper>
编程式自定义类型映射
Integer
接收,因此需要自定义类型映射。编写映射器如下:public class DefaultJavaTypeResolver extends JavaTypeResolverDefaultImpl {
public DefaultJavaTypeResolver() {
super();
typeMap.put(Types.SMALLINT, new JdbcTypeInformation("SMALLINT",
new FullyQualifiedJavaType(Integer.class.getName())));
typeMap.put(Types.TINYINT, new JdbcTypeInformation("TINYINT",
new FullyQualifiedJavaType(Integer.class.getName())));
}
}
XML
配置文件:<javaTypeResolver type="club.throwable.mbg.DefaultJavaTypeResolver">
<property name="forceBigDecimals" value="false"/>
javaTypeResolver>
...
public class Main {
public static void main(String[] args) throws Exception {
List<String> warnings = new ArrayList<>();
// 如果已经存在生成过的文件是否进行覆盖
boolean overwrite = true;
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(Main.class.getResourceAsStream("/generator-configuration.xml"));
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator generator = new MyBatisGenerator(config, callback, warnings);
generator.generate(null);
}
}
order_status
是TINYINT
类型,生成出来的文件中的orderStatus
字段全部替换使用Integer
类型定义。小结
Mybatis Generator
的使用方式,具体分析了XML
配置文件中主要标签以及标签属性的功能。因为Mybatis
在Java
的ORM
框架体系中还会有一段很长的时间处于主流地位,了解Mybatis Generator
可以简化CRUD
方法模板代码、实体以及Mapper
接口代码生成,从而解放大量生产力。Mybatis Generator
有不少第三方的扩展,例如tk.mapper
或者mybatis-plus
自身的扩展,可能附加的功能不一样,但是基本的使用是一致的。
原文链接
你可能感兴趣的:(Mybatis,mybatis)