Mybatis
第一章 Mybatis介绍
下载:https://github.com/mybatis/mybatis-3/releases
Mybatis是apache下的顶级项目。
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
通过mybatis提供的映射方式,自由灵活生成满足需要的sql语句。
向preparedStatement中输入参数自动进行输入映射,将查询结果集灵活映射成java对象。
第二章 配置文件
SqlMapConfig.xml: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 和spring整合后 environments配置将废除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理--> <transactionManager type="JDBC" /> <!-- 数据库连接池--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="mysql" /> </dataSource> </environment> </environments> <mappers> <mapper resource="sqlmap/User.xml"/> </mappers> </configuration>
2.1. Properties
将参数配置在properties中,只需要在SqlMapConfig.xml中加载properties,不需要硬编码,比如db.properties
<properites resource="db.properties"> <property name="age" value="18"/> </properties>
properties 元素体内的属性优先被加载,例如:age
例:
<!-- 通过properites加载 -->
<properties resource="db.properties" />
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="${mysql.Driver}" />
<property name="url" value="${mysql.url}" />
<property name="username" value="${mysql.user}" />
<property name="password" value="${mysql.password}" />
</dataSource>
</environment>
</environments>
2.2.Settings
mybatis全局配置参数,全局参数将会影响mybatis的运行行为。
Setting(设置) |
Description(描述) |
Valid Values(验证值组) |
Default(默认值) |
cacheEnabled |
在全局范围内启用或禁用缓存配置任何映射器在此配置下。 |
true | false |
TRUE |
lazyLoadingEnabled |
在全局范围内启用或禁用延迟加载。禁用时,所有协会将热加载。 |
true | false |
TRUE |
aggressiveLazyLoading |
启用时,有延迟加载属性的对象将被完全加载后调用懒惰的任何属性。否则,每一个属性是按需加载。 |
true | false |
TRUE |
multipleResultSetsEnabled |
允许或不允许从一个单独的语句(需要兼容的驱动程序)要返回多个结果集。 |
true | false |
TRUE |
useColumnLabel |
使用列标签,而不是列名。在这方面,不同的驱动有不同的行为。参考驱动文档或测试两种方法来决定你的驱动程序的行为如何。 |
true | false |
TRUE |
useGeneratedKeys |
允许JDBC支持生成的密钥。兼容的驱动程序是必需的。此设置强制生成的键被使用,如果设置为true,一些驱动会不兼容性,但仍然可以工作。 |
true | false |
FALSE |
autoMappingBehavior |
指定MyBatis的应如何自动映射列到字段/属性。NONE自动映射。 PARTIAL只会自动映射结果没有嵌套结果映射定义里面。 FULL会自动映射的结果映射任何复杂的(包含嵌套或其他)。 |
NONE, PARTIAL, FULL |
PARTIAL |
defaultExecutorType |
配置默认执行人。SIMPLE执行人确实没有什么特别的。 REUSE执行器重用准备好的语句。 BATCH执行器重用语句和批处理更新。 |
SIMPLE REUSE BATCH |
SIMPLE |
defaultStatementTimeout |
设置驱动程序等待一个数据库响应的秒数。 |
Any positive integer |
Not Set (null) |
safeRowBoundsEnabled |
允许使用嵌套的语句RowBounds。 |
true | false |
FALSE |
mapUnderscoreToCamelCase |
从经典的数据库列名A_COLUMN启用自动映射到骆驼标识的经典的Java属性名aColumn。 |
true | false |
FALSE |
localCacheScope |
MyBatis的使用本地缓存,以防止循环引用,并加快反复嵌套查询。默认情况下(SESSION)会话期间执行的所有查询缓存。如果localCacheScope=STATMENT本地会话将被用于语句的执行,只是没有将数据共享之间的两个不同的调用相同的SqlSession。 |
SESSION | STATEMENT |
SESSION |
dbcTypeForNull |
指定为空值时,没有特定的JDBC类型的参数的JDBC类型。有些驱动需要指定列的JDBC类型,但其他像NULL,VARCHAR或OTHER的工作与通用值。 |
JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER |
OTHER |
lazyLoadTriggerMethods |
指定触发延迟加载的对象的方法。 |
A method name list separated by commas |
equals,clone,hashCode,toString |
defaultScriptingLanguage |
指定所使用的语言默认为动态SQL生成。 |
A type alias or fully qualified class name. |
org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
callSettersOnNulls |
指定如果setter方法或地图的put方法时,将调用检索到的值是null。它是有用的,当你依靠Map.keySet()或null初始化。注意原语(如整型,布尔等)不会被设置为null。 |
true | false |
FALSE |
logPrefix |
指定的前缀字串,MyBatis将会增加记录器的名称。 |
Any String |
Not set |
logImpl |
指定MyBatis的日志实现使用。如果此设置是不存在的记录的实施将自动查找。 |
SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING |
Not set |
proxyFactory |
指定代理工具,MyBatis将会使用创建懒加载能力的对象。 |
CGLIB | JAVASSIST |
<settings> <!-- 打开延迟加载开关 全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 将积极加载改为消极加载(按需加载) 当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。 --> <setting name="aggressiveLazyLoading" value="false"/> <!-- 开启二级缓存 对在此配置文件下的所有cache 进行全局性开/关设置。 --> <setting name="cacheEnabled" value="true"/> </settings>
2.3.typeAliases
别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
自定义别名
<typeAliases> <!-- 单个别名定义 --> <typeAlias alias="user" type="cn.kai.mybatis.po.User"/> <!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) --> <package name="cn.kai.mybatis.po"/> <package name="其它包"/> ... </typeAliases>
2.4.typeHandlers(类型处理器)
类型处理器用于java类型和jdbc类型映射
<select id="findUserById" parameterType="int" resultType="user"> select * from user where id = #{id} </select>
mybatis自带的类型处理器基本上满足日常需求,不需要单独定义。
如IntegerTypeHandler,BooleanTypeHandler ....
2.5.mappers(映射器)
2.5.1 使用相对于类路径的资源
<mapper resource="sqlmap/User.xml" />
2.5.2 使用完全限定路径
<mapper url="file:///E:\workspace\newJavaSpace\mybatis\cofnig\sqlmap\User.xml" />
2.5.3 使用mapper接口类路径
<mapper class="cn.kai.mybatis.mapper.UserMapper"/> 此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中(xxxMapper.xml和xxxMapper.java要在同一个目录)。
2.5.3 注册指定包下的所有mapper接口
<package name="cn.kai.mybatis.mapper"/> 此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中
第三章 Mapper.xml映射文件
UserMapper.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="cn.kai.mybatis.mapper.UserMapper"> <select id="findUserById" parameterType="int" resultType="cn.kai.mybatis.po.User"> select * from user where id = #{id} </select> </mapper>
3.1 parameterType(输入类型)
3.1.1 传递简单类型
parameterType="int"
3.1.2 传递pojo对象
parameterType="user" 或 parameterType="cn.kai.mybatis.po.User"
3.1.3 传递pojo包装对象
public class ItemsQueryVo {
private Items items;
3.1.4 传递hashmap
parameterType="hashmap"
where id=#{id}
map.put("id", 1);
map.put("username", "管理员");
3.2 resultType(输出类型)
只有查出来的列名和pojo中的属性名一致,才可以映射成功
输出简单类型:resultType="int"
输出pojo对象:resultType="user"
输出pojo列表:resultType="user"
输出pojo对象和输出pojo列表在sql中定义的resultType是一样的。
返回单个pojo对象要保证sql查询出来的结果集为单条,内部使用session.selectOne方法调用,mapper接口使用pojo对象作为方法返回值。
返回pojo列表表示查询出来的结果集可能为多条,内部使用session.selectList方法,mapper接口使用List<pojo>对象作为方法返回值。
输出hashmap:输出pojo对象可以改用hashmap输出类型,将输出的字段名称作为map的key,value为字段值。
3.3 resultMap
如果resultMap在其他的mapper文件引用,前边需要加namespace
<?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"> <!-- namespace命名空间,作用对sql进行分类化管理 --> <mapper namespace="cn.kai.mybatis.mapper.OrdersMapps"> <!-- 根据订单查询用户信息resultmap --> <resultMap type="cn.kai.mybatis.po.Orders" id="OrdersUserResultMap"> <!-- orders信息 --> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- user信息 --> <association property="user" javaType="cn.kai.mybatis.po.User"> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="address" property="address"/> </association> </resultMap> <resultMap type="cn.kai.mybatis.po.Orders" id="OrdersOrderdetailResultMap" extends="OrdersUserResultMap"> <!-- orders信息 --> <!-- user信息 --> <!-- 订单详情信息 --> <collection property="orderdetails" ofType="cn.kai.mybatis.po.Orderdetail"> <id column="orderdetail_id" property="id"/> <result column="items_id" property="itemsId"/> <result column="items_num" property="itemsNum"/> <result column="orders_id" property="ordersId"/> </collection> </resultMap> <!-- 根据订单查询用户信息 --> <select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap"> SELECT a.*, b.`username`, b.`sex`, b.`birthday`, b.`address` FROM orders a, USER b WHERE a.`user_id` = b.`id` </select> <!-- 根据订单查询订单详情 --> <select id="findOrdersOrderdetailResultMap" resultMap="OrdersOrderdetailResultMap"> SELECT a.*, b.`username`, b.`sex`, b.`birthday`, b.`address` , c.`id` orderdetail_id, c.`items_id`, c.`items_num`, c.`orders_id` FROM orders a, USER b, orderdetail c WHERE a.`user_id` = b.`id` AND c.`orders_id` = a.`id` </select> <!-- 查询用户和购买商品信息ResultMap --> <resultMap type="cn.kai.mybatis.po.User" id="UserAndItemsResultMap"> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="address" property="address"/> <!-- ordersList信息 --> <collection property="ordersList" ofType="cn.kai.mybatis.po.Orders"> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <collection property="orderdetails" ofType="cn.kai.mybatis.po.Orderdetail"> <id column="orderdetail_id" property="id"/> <result column="items_id" property="itemsId"/> <result column="items_num" property="itemsNum"/> <result column="orders_id" property="ordersId"/> <association property="items" javaType="cn.kai.mybatis.po.Items"> <id column="items_id" property="id"/> <result column="items_name" property="name"/> <result column="items_price" property="price"/> </association> </collection> </collection> </resultMap> <!-- 查询用户和购买商品信息 --> <select id="findUserAndItems" resultMap="UserAndItemsResultMap"> SELECT a.*, b.`username`, b.`sex`, b.`birthday`, b.`address` , c.`id` orderdetail_id, c.`items_id`, c.`items_num`, c.`orders_id`, d.`name` items_name, d.`price` items_price FROM orders a, USER b, orderdetail c, items d WHERE a.`user_id` = b.`id` AND c.`orders_id` = a.`id` AND c.`items_id` = d.`id` </select> <!-- 查询订单信息,延迟加载用户信息ResultMap --> <resultMap type="cn.kai.mybatis.po.Orders" id="OrderLazyLogingUserResultMap"> <!-- orders信息 --> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 延迟加载用户信息 --> <association property="user" javaType="cn.kai.mybatis.po.User" select="cn.kai.mybatis.mapper.UserMapper.findUserById" column="user_id" fetchType="lazy"> </association> </resultMap> <!-- 查询订单信息,延迟加载用户信息 --> <select id="findOrderLazyLodingUser" resultMap="OrderLazyLogingUserResultMap"> SELECT * FROM orders </select> <!-- 根据userId查询订单信息 --> <select id="findOrdersByUserId" parameterType="int" resultType="cn.kai.mybatis.po.Orders" > SELECT * FROM orders WHERE user_id = #{user_id} </select> <!-- 查询用户信息,延迟加载订单信息 ResultMap --> <resultMap type="cn.kai.mybatis.po.User" id="UserLazyLodingOrdersResultMap"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="address" property="address"/> <!-- 延迟加载订单信息 --> <collection property="ordersList" ofType="cn.kai.mybatis.po.Orders" select="findOrdersByUserId" column="id" fetchType="lazy"> </collection> </resultMap> <!-- 查询用户信息,延迟加载订单信息 --> <select id="findUserLazyLodingOrders" resultMap="UserLazyLodingOrdersResultMap"> SELECT * FROM USER </select> </mapper>
第四章 mapper接口
- mapper.xml中namespace就是mapper.java的类全路径
- Mapper接口方法名和Mapper.xml中定义的statement的id相同
- Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同
- Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同
使用注解来映射简单语句:
public interface BlogMapper { @Select("SELECT * FROM blog WHERE id = #{id}") Blog selectBlog(int id); }
第五章 动态sql
5.1. If
<select id="findUserList" parameterType="user" resultType="user"> select * from user where 1=1 <if test="id!=null and id!=''"> and id=#{id} </if> <if test="username!=null and username!=''"> and username like '%${username}%' </if> </select>
5.2. Where
<where />可以自动处理第一个and,不用担心会多一个and
<select id="findUserList" parameterType="user" resultType="user"> select * from user <where> <if test="id!=null and id!=''"> and id=#{id} </if> <if test="username!=null and username!=''"> and username like '%${username}%' </if> </where> </select>
5.3 foreach
5.4 Sql片段
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的
<sql id="query_user_where"> <if test="id!=null and id!=''"> and id=#{id} </if> <if test="username!=null and username!=''"> and username like '%${username}%' </if> </sql> <select id="findUserList" parameterType="user" resultType="user"> select * from user <where> <include refid="query_user_where"/> </where> </select>
如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下:
<include refid="namespace.sql片段”/>
第六章 mybatis框架
6.1. SqlMapConfig.xml(文件名字不固定)
全局配置文件,配置了数据源,事务等
6.2. 配置映射文件(配置sql语句)
mapper.xml
6.3. SqlSessionFactory
SqlSession线程不安全,最好放在方法体内创建
创建SqlSession:操作数据库(发出sql增、删、改、查)
//mybatis配置文件 String resource = "SqlMapConfig.xml"; InputStream inputStream; inputStream = Resources.getResourceAsStream(resource); //创建会话工厂 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通过工厂得到SqlSession sqlSession = sqlSessionFactory.openSession();
6.4. Exection(执行器)
是一个接口(基本执行器,缓存执行器)
SqlSession内部通过执行器操作数据库
6.5. Mapped statement(底层封装对象)
对操作数据库存储封装、包括sql语句,输入参数、输出结果类型
输入参数类型:java简单类型、hashmap,pojo自定义类型
#{} ${}:
使用占位符#{}可以有效防止sql注入
#{}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}和#{}不同,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
使用${}不能防止sql注入
第七章 延迟加载
当需要查询关联信息时再去数据库查询,默认不去关联查询,提高数据库性能。
只有使用resultMap支持延迟加载设置。
7.1. 打开延迟开关
方法一、
<!-- setting:mybatis全局配置参数,全局参数将会影响mybatis的运行行为。 -->
<settings>
<!-- 打开延迟加载开关
全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。
-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载(按需加载)
当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。
-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
方法二、用fetchType="lazy" 设置单个延迟加载
<!-- 延迟加载用户信息 -->
<association property="user" javaType="cn.kai.mybatis.po.User"
select="cn.kai.mybatis.mapper.UserMapper.findUserById" column="user_id" fetchType="lazy">
</association>
7.2. 实例
<!-- 查询订单信息,延迟加载用户信息 --> <select id="findOrderLazyLodingUser" resultMap="OrderLazyLogingUserResultMap"> SELECT * FROM orders </select> <!-- 查询订单信息,延迟加载用户信息ResultMap --> <resultMap type="cn.kai.mybatis.po.Orders" id="OrderLazyLogingUserResultMap"> <!-- orders信息 --> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 延迟加载用户信息 --> <association property="user" javaType="cn.kai.mybatis.po.User" select="cn.kai.mybatis.mapper.UserMapper.findUserById" column="user_id" fetchType="lazy"> </association> </resultMap> List<Orders> list = ordersMapps.findOrderLazyLodingUser(); for(Orders order: list) { //调用getUser时延迟加载查询数据库 User user = order.getUser(); System.out.println(user); }
第八章 查询缓存
8.1. 一级缓存
一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
如果缓存中有数据就不用从数据库中获取,大大提高系统性能。
8.2. 二级缓存
二级缓存区域是根据mapper的namespace划分的,相同namespace的mapper查询数据放在同一个区域,如果使用mapper代理方法每个mapper的namespace都不同,此时可以理解为二级缓存区域是根据mapper划分。
每次查询会先从缓存区域找,如果找不到从数据库查询,查询到数据将数据写入缓存。
Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象
sqlSession执行insert、update、delete等操作commit提交后会清空缓存区域。
开启二级缓存:
1.在核心配置文件SqlMapConfig.xml中加入
<setting name="cacheEnabled" value="true"/>
2.要在你的Mapper映射文件中添加一行: <cache /> ,表示此mapper开启二级缓存。
二级缓存需要查询结果映射的pojo对象实现java.io.Serializable接口实现序列化和反序列化操作,注意如果存在父类、成员pojo都需要实现序列化接口。
public class Orders implements Serializable
public class User implements Serializable
禁用二级缓存:
<select ... useCache="false">
每次查询都会发出sql去查询
刷新缓存:
在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。
设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。
如下:
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
flushInterval(刷新间隔)
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU:
1.LRU – 最近最少使用的:移除最长时间不被使用的对象。
2.FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
3.SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
4.WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
8.3. mybatis整合ehcache
为了提高系统并发,性能、一般对系统进行分布式部署,不使用分布缓存,缓存的数据在各各服务单独存储,不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理。
mybatis无法实现分布式缓存,需要和其它分布式缓存框架进行整合。
mybatis提供了一个cache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。
mybatis和ehcache整合,mybatis和ehcache整合包中提供了一个cache接口的实现类。
mybatis默认实现cache类PerpetualCache
整合方法:
1. 加入ehcache包
2. 缓存配置文件ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="F:\develop\ehcache" /> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
属性说明:
diskStore:指定数据在磁盘中的存储位置。
defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
以下属性是必须的:
maxElementsInMemory - 在内存中缓存的element的最大数目
maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
以下属性是可选的:
timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
3. 开启ehcache缓存
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
根据需求调整缓存参数:
<cache type="org.mybatis.caches.ehcache.EhcacheCache" > <property name="timeToIdleSeconds" value="3600"/> <property name="timeToLiveSeconds" value="3600"/> <!-- 同ehcache参数maxElementsInMemory --> <property name="maxEntriesLocalHeap" value="1000"/> <!-- 同ehcache参数maxElementsOnDisk --> <property name="maxEntriesLocalDisk" value="10000000"/> <property name="memoryStoreEvictionPolicy" value="LRU"/> </cache>
第九章 mybatis 和 spring整合
需要spring通过单例方式管理SqlSessionFactory。
spring和mybatis整合生成代理对象,使用SqlSessionFactory创建SqlSession。(spring和mybatis整合自动完成)
持久层的mapper都需要由spring进行管理。
Jar包:
mybatis3.2.7的jar包
spring3.2.0的jar包
9.1. Spring配置文件applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "> <!-- 加载配置文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- dbcp数据源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${mysql.Driver}"/> <property name="url" value="${mysql.url}" /> <property name="username" value="${mysql.user}"/> <property name="password" value="${mysql.password}"/> </bean> <!-- oracle数据源 --> <!-- <bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close"> <property name="serviceName" value="${mysql.Driver}"/> <property name="url" value="${mysql.url}" /> <property name="user" value="${mysql.user}"/> <property name="password" value="${mysql.password}"/> </bean> --> <!-- sqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 配置数据源 --> <property name="dataSource" ref="dataSource"/> <!-- 配置mybatis配置文件 --> <property name="configLocation" value="./mybatis/SqlMapConfig.xml"/> </bean> <bean id="userDao" class="cn.kai.sm.dao.impl.UserDaoImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <!-- 设置mapper接口 --> <property name="mapperInterface" value="cn.kai.sm.mapper.UserMapper"/> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> </beans>
9.2. 用dao和dao的实现
1)dao的实现需要继承SqlSessionDaoSupport:
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao { @Override public User findUserById(int id) throws Exception { SqlSession sqlSession = getSqlSession(); return sqlSession.selectOne("userMapper.findUserById", id); } }
2)加载bean
<!-- dao的实现的方法加载userbean -->
<bean id="userDao" class="cn.kai.sm.dao.impl.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
3)测试
private ApplicationContext applicationContext; @Before public void setUp() throws Exception{ applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); } @Test public void testFindUserById() throws Exception { UserDao userdao = (UserDao) applicationContext.getBean("userDao"); User user = userdao.findUserById(29); System.out.println(user); }
9.3. 使用mapper实现
1)<!-- 通过mapper的方法加载userbean -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!-- 设置mapper接口 -->
<property name="mapperInterface" value="cn.kai.sm.mapper.UserMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
2)<!-- 批量扫描mapper加载userbean -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 要扫描的包,多个包名用,隔开 -->
<property name="basePackage" value="cn.kai.sm.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
3)测试
UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper"); User user = userMapper.findUserById(29); System.out.println(user);
第十章 逆向工程
mybaits需要程序员自己编写sql语句,mybatis官方提供逆向工程 可以针对单表自动生成mybatis执行所需要的代码(mapper.java,mapper.xml、po..)
generatorConfig.xml
例1:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="testTables" targetRuntime="MyBatis3"/> <!-- 配置pojo的序列化 --> <plugin type="org.mybatis.generator.plugin.SerializablePlugin"/> <commentGenerator> <!-- 是否去掉自动生成的注释 true:是 false:否 --> <property name="suppressAllComments" value="true"/> </commentGenerator> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://t5xxx.com.cn:3306/obpapi?characterEncoding=UTF-8" userId="" password=""></jdbcConnection> <!-- 默认false,把JDBC DECIMAL 和 NUMBER类型解析为Integer,为true时,解析为java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- targetProjec:生成PO类的位置 --> <javaModelGenerator targetPackage="com.dao.model" targetProject=".\src\main\java" > <!-- enalbeSubPackages:是否让schema作为包的后缀 --> <property name="enalbeSubPackages" value="false"/> <!-- 从数据库返回的值被清理前后空格 --> <property name="trimStrings" value="true"/> </javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置 --> <sqlMapGenerator targetPackage="com.dao.mapper" targetProject=".src\main\resources"> <property name="enalbeSubPackages" value="false"/> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.dao" targetProject=".\src\main\java"> <property name="enalbeSubPackages" value="false"/> <!-- dao接口继承父接口 --> <property name="rootInterface" value="com.dao.mybatis.BaseMapper"/> </javaClientGenerator> <!-- 指定数据库表 --> <table tableName="db_table_1" enableCountByExample="false" enableUpdateByExample="false" enalbeDeleteByExample="false" enableSelectByExample="false"> <generatedKey column="id" sqlStatement="MySql" identity="true" /> </table> </context> </generatorConfiguration>
例2:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="testTables" targetRuntime="MyBatis3"> <commentGenerator> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password="chenkai123"> </jdbcConnection> <!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" userId="yycg" password="yycg"> </jdbcConnection> --> <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- targetProject:生成PO类的位置 --> <javaModelGenerator targetPackage="cn.kai.sm.bean" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> <!-- 从数据库返回的值被清理前后的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置 --> <sqlMapGenerator targetPackage="cn.kai.sm.mapper" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="cn.kai.sm.mapper" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 指定数据库表 --> <table tableName="items"></table> <table tableName="orders"></table> <table tableName="orderdetail"></table> <table tableName="user"></table> </context> </generatorConfiguration>
mybatis生成配置文件运行方式
1. cmd命令执行
mybatis-generator-core.jar包
generatorConfig.xml
java -jar mybatis-generator-core.jar -configfile generatorConfig.xml overwrite
2. maven运行生成
run as -> maven build
mybatis-generator:generate
3. main方法执行
public class GeneratorSqlmap { public void generator() throws Exception{ List<String> warnings = new ArrayList<String>(); boolean overwrite = true; //指定 逆向工程配置文件 File configFile = new File("generatorConfig.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } public static void main(String[] args) throws Exception { try { GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap(); generatorSqlmap.generator(); } catch (Exception e) { e.printStackTrace(); } } }
汇总: