Mybatis学习笔记
mybatis有官方的中文开发文档并且针对使用者比较友好:http://www.mybatis.org/mybatis-3/zh/
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
在mybatis中有这么几个需要关注的点:
mybatis的配置文件mybatis-config.xml
properties 属性
settings 设置
typeAliases 类型别名
typeHandlers 类型处理器
objectFactory 对象工厂
plugins 插件
environments 环境
environment 环境变量
transactionManager 事务管理器
dataSource 数据源
databaseIdProvider 数据库厂商标识
mappers 映射器
这是mybatist配置文件中需要配置的属性, 有些属性可以配置,有些属性可以不配置, 但是所有的属性配置按照以上的顺序进行, 否则会出现配置错误。
-
首先是对properties的配置,可以引入 .properties 文件,作为信息,例如jdbc.properties
<properties resource="jdbc.properties">
<property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}"/> <property name="url" value="${jdbc.url}"/> <property name="driver" value="${jdbc.dirver}"/>
</properties>
jdbc.properties中的内容
jdbc.username=root
jdbc.password=root
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_mybatis_demo?serverTimezone=GMT&useSSL=false
如果使用这种方式配置最好加上jdbc.xxxx避免与编辑器或系统变量产生冲突,以致于连接数据库失败。
如果直接在 properties 元素体内指定属性值也是可以的,,以上配置的方式作为第二种方式, 还可以通过java代码的方式来引入配置。属性也可以被传递到 SqlSessionFactoryBuilder.build()方法中,
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props);
// ... or ...
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);
这以上的三种方式优先级递增, 如果同时配置了,将会使用最后一种中的值。(推荐使用第二种方式),另外还有默认值配置, 详见文档。
- 下面是对 setting 的讲解
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。setting有诸多属性, 官方文档中对这些属性有详尽的介绍, 按需配置。例如:
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
- typeAliases 别名
类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余,为了简化xxxMapper.xml中的书写。例如
mybatis-config.xml
<typeAliases>
<typeAlias type="com.ultrapower.practice.mybatis.pojo.UserDO" alias="User"/>
</typeAliases>
UserMapper.xml
<select id="getUser" useCache="true" parameterType="User">
</select>
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
<typeAliases>
<package name="com.ultrapower.practice.mybatis.pojo"/>
</typeAliases>
<font color="red">这里有一点值得注意的是Mapper.xml中得明明空间不能使用别名, 只能使用类路径名,例如:</font>
<mapper namespace="com.ultrapower.practice.mybatis.mapper.UserMapper">
<select id="getUser" useCache="true" parameterType="User">
select * from t_user;
</select>
</mapper>
- typeHandlers 类型处理器
使用这个的类型处理器将会覆盖已经存在的处理 Java 的 String 类型属性和 VARCHAR 参数及结果的类型处理器。 要注意 MyBatis 不会窥探数据库元信息来决定使用哪种类型,所以你必须在参数和结果映射中指明那是 VARCHAR 类型的字段, 以使其能够绑定到正确的类型处理器上。 这是因为:MyBatis 直到语句被执行才清楚数据类型。(这个我在后面的demo中使用了用的是枚举类型的SexEnum)
- objectFactory 对象工厂
(没有使用过,详见官方文档)
- plugins 插件
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。
这里我使用了 pagehelper 分页的插件,地址是https://pagehelper.github.io/
<!--配置分页插件拦截器-->
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
<property name="param" value="value"/>
</plugin>
</plugins>
- environments 配置环境
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者共享相同 Schema 的多个生产数据库, 想使用相同的 SQL 映射。许多类似的用例。
<!--环境配置-->
<environments default="">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
默认的环境 ID(比如:default=”development”)。
每个 environment 元素定义的环境 ID(比如:id=”development”)。
事务管理器的配置(比如:type=”JDBC”)。
数据源的配置(比如:type=”POOLED”)。
由于mybatis少单独使用, 大多情况下会结合spring使用, 所以我们并不用太关系他的事务管理,因为spring会做这件事。
- Mapper映射器
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了。但是首先我们需要告诉 MyBatis 到哪里去找到这些语句。 Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。
<mappers>
<mapper>com/ultrapower/practice.mybatis/mapper/UserMapper.xml</mapper>
</mappers>
文档中有几种不同的方式, 请选用适合你的方式。
Mapper XML 文件
- select
- insert
- update
- delete
这四个语句是最长用的几个语句,在文档中应用的属性有详细的说明。这里有个例子:
<select id="getUser" useCache="true" parameterType="User" resultMap="userResult"
flushCache="false" statementType="PREPARED">
SELECT * FROM t_user
<where>
<if test='username != null and username != ""'>
username = #{username}
</if>
<if test='age != null and age != ""'>
AND age >= 5 AND age <= 20
</if>
</where>
</select>
需要注意的一点是在使用username的时候对 username进行了一次判断, 这里不仅需要判断username是否为null, 还要判断是否为 "",但是一般会错写为<if test="username != null and username != """> 就是双引号和单引号的问题,同时最好为#{username}加上jdbcType(避免有允许为空的列而不知道参数类型),javaType就一般无需指定了,因为mybatis会根据你传来的对象自行判断是什么类型的值,除非你传的值是一个hashmap
另外还需要对大于小于等符号进行转义, 如上述age的操作。
<还没有看resultmap的高级映射>
动态sql
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
有些时候,我们不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
foreach
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。
在mybatis中还有两个符号需要注意:
1. 符号#{} 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符。
2. 一个 #{ } 被解析为一个参数占位符 ? 。
3. ${} 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换
4. 表名作为变量时,必须使用 ${}
5. 能用#{}就用#{},因为它会对sql进行预编译, 可以提高性能。
针对以上的所讲的功能实现了一个demo,只包含mybatis的相关内容:
在这可以去github下载源码
集合、高级映射、handlerType(后面补)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。