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(后面补)