一、配置文件
属性(properties)
用来加载外部资源文件,这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。例如:
<properties resource="org/mybatis/example/config.properties"> <property name="username" value="dev_user"/> <property name="password" value="F2Fa3!33TYyg"/> </properties>
定义外部资源文件的key时,key的格式:xxx.xxx.xxx…,以免产生覆盖。
设置(settings)
<settings> <!--全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认值为true --> <setting name="cacheEnabled" value="true" /> <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。默认值false --> <setting name="lazyLoadingEnabled" value="true" /> <!-- 是否开启自动驼峰命名规则(camel case)映射,默认值false--> <setting name="mapUnderscoreToCamelCase" value="false" /> <!-- 指定 MyBatis 增加到日志名称的前缀,任何字符串。默认未设置 --> <setting name="logPrefix" value="mybatis" /> <!-- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找 --> <setting name="logImpl" value="SLF4J" /> </settings>
类型别名(typeAliases)
为Java类的全限定名设置一个简短的名字,主要是减少冗余
<typeAliases> <typeAlias alias="Student" type="com.raven.vo.Student"/> </typeAliases>
也可以通过包进行设置,扫描整个包,
<typeAliases> <package name="com.raven.vo"/> </typeAliases>
每一个在包 com.raven.vo 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 com.raven.vo.Student 的别名为 student;若有注解,则别名为其注解值。见下面的例子:
@Alias("student")
public class Student {
...
}
常见的 Java 类型内建的相应的类型别名。它们都是不区分大小写的,注意对基本类型名称重复采取的特殊命名风格。
别名 | 映射的类型 | 别名 | 映射的类型 |
---|---|---|---|
_byte | byte | double | Double |
_long | long | float | Float |
_short | short | boolean | Boolean |
_int | int | date | Date |
_integer | int | decimal | BigDecimal |
_double | double | bigdecimal | BigDecimal |
_float | float | object | Object |
_boolean | boolean | map | Map |
string | String | hashmap | HashMap |
byte | Byte | list | List |
long | Long | arraylist | ArrayList |
short | Short | collection | Collection |
int | Integer | iterator | Iterator |
integer | Integer |
类型处理器(typeHandlers)
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。mybatis默认给我们实现了需多typeHandlers,基本能满足开发。你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型,比如:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler。
BooleanTypeHandler |
java.lang.Boolean, boolean |
数据库兼容的 BOOLEAN |
ByteTypeHandler |
java.lang.Byte, byte |
数据库兼容的 NUMERIC 或 BYTE |
ShortTypeHandler |
java.lang.Short, short |
数据库兼容的 NUMERIC 或 SMALLINT |
IntegerTypeHandler |
java.lang.Integer, int |
数据库兼容的 NUMERIC 或 INTEGER |
LongTypeHandler |
java.lang.Long, long |
数据库兼容的 NUMERIC 或 BIGINT |
FloatTypeHandler |
java.lang.Float, float |
数据库兼容的 NUMERIC 或 FLOAT |
DoubleTypeHandler |
java.lang.Double, double |
数据库兼容的 NUMERIC 或 DOUBLE |
BigDecimalTypeHandler |
java.math.BigDecimal |
数据库兼容的 NUMERIC 或 DECIMAL |
StringTypeHandler |
java.lang.String |
CHAR, VARCHAR |
ClobReaderTypeHandler |
java.io.Reader |
- |
ClobTypeHandler |
java.lang.String |
CLOB, LONGVARCHAR |
NStringTypeHandler |
java.lang.String |
NVARCHAR, NCHAR |
NClobTypeHandler |
java.lang.String |
NCLOB |
BlobInputStreamTypeHandler |
java.io.InputStream |
- |
ByteArrayTypeHandler |
byte[] |
数据库兼容的字节流类型 |
BlobTypeHandler |
byte[] |
BLOB, LONGVARBINARY |
DateTypeHandler |
java.util.Date |
TIMESTAMP |
DateOnlyTypeHandler |
java.util.Date |
DATE |
TimeOnlyTypeHandler |
java.util.Date |
TIME |
SqlTimestampTypeHandler |
java.sql.Timestamp |
TIMESTAMP |
SqlDateTypeHandler |
java.sql.Date |
DATE |
SqlTimeTypeHandler |
java.sql.Time |
TIME |
ObjectTypeHandler |
Any |
OTHER 或未指定类型 |
EnumTypeHandler |
Enumeration Type |
VARCHAR 或任何兼容的字符串类型,用以存储枚举的名称(而不是索引值) |
EnumOrdinalTypeHandler |
Enumeration Type |
任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的序数值(而不是名称)。 |
SqlxmlTypeHandler |
java.lang.String |
SQLXML |
InstantTypeHandler |
java.time.Instant |
TIMESTAMP |
LocalDateTimeTypeHandler |
java.time.LocalDateTime |
TIMESTAMP |
LocalDateTypeHandler |
java.time.LocalDate |
DATE |
LocalTimeTypeHandler |
java.time.LocalTime |
TIME |
OffsetDateTimeTypeHandler |
java.time.OffsetDateTime |
TIMESTAMP |
OffsetTimeTypeHandler |
java.time.OffsetTime |
TIME |
ZonedDateTimeTypeHandler |
java.time.ZonedDateTime |
TIMESTAMP |
YearTypeHandler |
java.time.Year |
INTEGER |
MonthTypeHandler |
java.time.Month |
INTEGER |
YearMonthTypeHandler |
java.time.YearMonth |
VARCHAR 或 LONGVARCHAR |
JapaneseDateTypeHandler |
java.time.chrono.JapaneseDate |
DATE |
插件(plugins)
通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。
@Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class ExamplePlugin implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { return invocation.proceed(); } public Object plugin(Object target) { return Plugin.wrap(target, this); } public void setProperties(Properties properties) { } }
在全局配置中增加:
<plugins> <plugin interceptor="org.mybatis.example.ExamplePlugin"> <property name="someProperty" value="100"/> </plugin> </plugins>
上面的插件将会拦截在 Executor 实例中所有的 “update” 方法调用, 这里的 Executor 是负责执行低层映射语句的内部对象。
映射器(mappers)
直接映射xml配置
<mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers>
或者类映射:
<mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/> </mappers>
或者包扫描:
<mappers> <package name="org.mybatis.builder"/> </mappers>
二、结果映射
resultType
mybatis会满足大部分的映射,将查询的列映射到实体上
<select id="selectStudents" resultType="com.raven.vo.Student"> select * from student where id = #{id} </select>
注意:默认不支持驼峰映射,如果存在驼峰和下划线对应的话,比如stu_id和stuId,是无法自动映射的,除非开启驼峰映射。
resultMap
<select id="getStudentById" resultMap="BaseResultMap" parameterType="int"> select * from student t where t.stu_id = #{stuId} </select> <resultMap id="BaseResultMap" type="com.zhi.prictice.vo.Student" > <constructor> <idArg column="stu_id" javaType="int" jdbcType="INTEGER"/> <arg column="name" javaType="string" jdbcType="VARCHAR"/> </constructor> <result column="age" property="age" jdbcType="INTEGER" /> <result column="gender" property="gender" jdbcType="VARCHAR" /> <result column="birthday" property="birthday" jdbcType="DATE" /> <result column="addr" property="addr" jdbcType="VARCHAR" /> <result column="reg_time" property="regTime" jdbcType="TIMESTAMP" /> <result column="status" property="status" jdbcType="BOOLEAN" /> </resultMap>
resultmap下的节点
- constructor - 用于在实例化类时,注入结果到构造方法中
- idArg - ID 参数;标记出作为 ID 的结果可以帮助提高整体性能
- arg - 将被注入到构造方法的一个普通结果
- id – 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能
- result – 注入到字段或 JavaBean 属性的普通结果
- association – 一个复杂类型的关联;许多结果将包装成这种类型
- 嵌套结果映射 – 关联本身可以是一个 resultMap 元素,或者从别处引用一个
- collection – 一个复杂类型的集合
- 嵌套结果映射 – 集合本身可以是一个 resultMap 元素,或者从别处引用一个
- discriminator – 使用结果值来决定使用哪个 resultMap
- case – 基于某些值的结果映射
- 嵌套结果映射 – case 本身可以是一个 resultMap 元素,因此可以具有相同的结构和元素,或者从别处引用一个
- case – 基于某些值的结果映射
关联(一对一映射)
<association property="author" column="blog_author_id" javaType="Author"> <id property="id" column="author_id"/> <result property="username" column="author_username"/> </association>
集合(一对多映射)
<collection property="posts" ofType="domain.blog.Post"> <id property="id" column="post_id"/> <result property="subject" column="post_subject"/> <result property="body" column="post_body"/> </collection>
三、动态sql
if判断
<if test="name != null"> t.name=#{name,jdbcType=VARCHAR}, </if>
choose, when, otherwise
相当于if...else if....else...
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>
trim, where, set
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG <where> <if test="state != null"> state = #{state} </if> </where> </select>
如果 where 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
<trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>
类似的用于动态更新语句的解决方案叫做 set。set 元素可以用于动态包含需要更新的列,而舍去其它的。比如:
类似的用于动态更新语句的解决方案叫做 set。set 元素可以用于动态包含需要更新的列,而舍去其它的。比如:
这里,set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。(译者注:因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留)
若你对 set 元素等价的自定义 trim 元素的代码感兴趣,那这就是它的真面目:
<trim prefix="SET" suffixOverrides=","> ... </trim>
foreach
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
bind
bind元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:
<select id="selectBlogsLike" resultType="Blog"> <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" /> SELECT * FROM BLOG WHERE title LIKE #{pattern} </select>
参考:http://www.mybatis.org/mybatis-3/zh/index.html