文章目录
MyBatis
基本介绍
Hibernate:全自动化的持久化(把内存中的瞬时数据永久的保存在磁盘上/数据库中的过程)框架
MyBatis:ORM 半自动化的持久化框架(SQL语句可以自己管理)
都是ORM (对象 关系 映射)框架
- O:javabean
- R:关系型数据库
- M:映射
MyBatis开发(常规)
① 下载地址
https://github.com/mybatis/mybatis-3/releases
https://github.com/mybatis/mybatis-3/releases/tag/mybatis-3.4.6
② 导入相应jar
③ 创建核心配置文件
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf8" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<!-- 加载sql映射文件 -->
<mappers>
<mapper resource="mapper/User.xml" />
</mappers>
</configuration>
在url后加上?useUnicode=true&characterEncoding=utf8是因为可能会出现字符集不匹配的问题
④ 创建实体映射bean
⑤ 创建sql映射文件(mapper文件)
<?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="org.mybatis.example.BlogMapper">
<select id="selectUser" parameterType="int" resultType="bean.User">
select * from usertable where uid = #{uid}
</select>
</mapper>
⑥ 在核心配置文件中加载sql映射文件
<mappers>
<mapper resource="mapper/User.xml" />
</mappers>
⑦ 测试
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import bean.User;
public class Test {
public static void main(String[] args) {
String resource = "configuration.xml";
SqlSession session = null;
InputStream is = Test.class.getClassLoader().getResourceAsStream(resource);
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
session = ssf.openSession();
//User user1 = (User)session.selectOne("namespace1.selectUser", 1);
//接口方式
UserDao userdao = session.getMapper(UserDao.class);
User user2 = userdao.selectUser(1);
System.out.println(user2);
session.close();
}
}
⑧ 日志显示
MyBatis开发(接口)
① 创建接口和映射文件
- 映射文件的namespace和接口全路径一致 (让接口和映射文件进行动态绑定)
- 接口中抽象方法名、参数、返回值类型和映射文件中SQL的id、parameterType、resultType一致, (让接口方法和映射文件SQL进行动态绑定 )
② 核心配置文件中加载映射文件或接口
package dao;
import bean.User;
public interface UserDao {
public User selectUser(int uid);
}
<?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="dao.UserDao">
<select id="selectUser" parameterType="int" resultType="bean.User">
select * from usertable where uid = #{uid}
</select>
</mapper>
③ 测试
mybatis通过接口方式是以Java动态代理模式进行实现的。
MyBatis开发(注解)
① 无需创建xml映射文件
② 创建接口DAO,并在接口方法前通过@Select定义sql语句
“_name” --> @Param指定当前参数(sql中)的值
③ 在核心配置文件(configuration.xml)中加载接口
④ 测试
以接口的方式进行测试即可
MyBatis的基本架构
MyBatis的作用域和生命周期
1. 作用域
●SqISessionFactoryBuilder
可以在任何时候被实例化、使用和销毁。一旦您创造 了SqISessionFactory就不需要再保留它
●SqlSessionFactory
SqlSessionFactory 一旦创建将会存在于您的应用程序整个运行生命周期中,不要在一个应用中多次创 建SqlSessionFactory
●SqISession
每个线程都有一个SqlSession 实例,SqlSession 实例是不被共享的,并且是线程不安全的作用域是request或者method
2. SqlSessionFactory对象的自定义获取
import java.beans.PropertyVetoException;
import javax.sql.DataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import bean.User;
import dao.UserDao;
public class Test2 {
public static void main(String[] args) {
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("deve", transactionFactory, getDataSource());
Configuration config = new Configuration(environment);
//加载映射文件
config.addMapper(UserDao.class);
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
SqlSession session = ssf.openSession();
System.out.println("----------注解方式-------------");
UserDao userdao = session.getMapper(UserDao.class);
int i = userdao.selectUidByName("吴治峰");
System.out.println(i);
session.close();
}
private static DataSource getDataSource() {
ComboPooledDataSource ds = new ComboPooledDataSource();
try {
ds.setDriverClass("com.mysql.cj.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC");
ds.setUser("root");
ds.setPassword("123456");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return ds;
}
}
MyBatis的简单封装
package utils;
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class GetSqlSession {
/**
* 获取SqlSession对象
* @return SqlSession
*/
public static SqlSession getSqlSession() {
String resource = "configuration.xml";
Reader reader = null;
try {
reader = Resources.getResourceAsReader(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = ssf.openSession();
return session;
}
}
核心配置文件Configuration.xml的几种元素
① properties
引入外部属性文件
② Settings
设置或改变Mybatis运行过程中的行为方式
如上例子:mapUnderscoreToCamelCase选项开启,则开启驼峰命名映射,
如果数据库字段为A_NAME,则会映射为aName,首字母小写,去掉下划线,后面驼峰
③ typeAliases
别名使用注意:
④ Typehandlers
⑤ Plugins
⑥ Environments
⑦ databaseIdProvider
⑧ Mappers
核心映射文件Mappers.xml
1. 修改sql操作
public class Test4 {
public static void main(String[] args) {
String resource = "configuration.xml";
SqlSession session = GetSqlSession.getSqlSession(resource);
User user = new User(0,"张五","24",1);
UserDao userdao = session.getMapper(UserDao.class);
int i = userdao.insert(user);
if( i == 1) {
System.out.println("插入成功");
} else {
System.out.println("插入失败");
}
//session.commit();需要此函数才能提交到数据库
//或者SqlSession session = ssf.openSession(true);
//封装在了GetSqlSession.getSqlSession()里
session.close();
}
}
<mapper namespace="dao.UserDao">
<select id="selectUser" parameterType="int" resultType="bean.User">
select * from usertable where uid = #{uid}
</select>
<insert id="insert" parameterType="bean.User" useGeneratedKeys="true" keyProperty="uid">
insert into usertable(name,age,sex) values(#{name},#{age},#{sex})
</insert>
<delete id="delete" parameterType="int">
delete from usertable where uid = #{uid}
</delete>
<update id="updateAge" parameterType="User">
update usertable set age = #{age} where uid = #{uid}
</update>
</mapper>
扩展:
插入数据时mybatis自动获取从数据库生成的主键(mysql自增长主键)方法:
解:java中对象之间支持值传递,不支持引用传递,即测试用例中的user和传过去的参数user指向同一块内存地址,如果在insert之后得到主键uid,可以改变这块内存地址user的主键, 再用getUid()便可以获取到。
设置useGeneratedKeys,允许JDBC支持自动生成主键,并在执行添加记录之后可以获取到数据库自动生成的主键ID。
设置keyProperty指定接受返回的属性,不指定的话也不会生成。
<insert id="insert" parameterType="bean.User" useGeneratedKeys="true" keyProperty="uid">
insert into usertable(name,age,sex) values(#{name},#{age},#{sex})</insert>
User user = new User(0,"张五","24",1);
UserDao userdao = session.getMapper(UserDao.class);
int i = userdao.insert(user);
if( i == 1) {
System.out.println("插入成功,uid为:" + user.getUid());
} else {
System.out.println("插入失败");
}
插入数据时获取插入的主键值(非自增长主键):
order设置为BEFORE表示先执行selectKey,在insert,AFTER相反,一般是BRFORE
rand()返回一个随机数,0~1。会有重复,这里仅演示,并不严谨。(后面的id是别名)
2. 入参处理
参数处理方式
① 单个参数
MyBatis中可以接受基本类型以及对象类型的参数
基本类型:直接通过#{name}获取即可,name可自定义
对象类型:直接通过#{属性名}获取即可[建议]
Mybatis可以接受一个Map集合作为参数类型,sql中就可以通过获取map的key来得到参数值
② 多个参数
MyBatis可以接受任意多个参数
多个参数传入时都会被重新包装成一个Map,Map的key是arg0,arg1… 或者 param1,param2…,Map的值就是入参的值,在sql语句中获取Map的key从而得到参数的值
③ 命名参数
多个参数传入时,为了方便在sql中获取对于的参数值,从而可以在方法入参前指定sql中获取的参数名称
<!-- 多个参数
<update id="updateParamAge">
update usertable set age = #{param1} where uid = #{param2}
</update>
-->
<!-- 取别名,增加可读性 -->
<update id="updateParamAge">
update usertable set age = #{Param1_age} where uid = #{Param1_uid}
</update>
public int updateParamAge(@Param("Param1_age")int age,@Param("Param1_uid")int uid);
入参处理源码分析
在调用接口处打上断点进行代码跟踪:
3. Sql中的取值方式
① 两种方式:#{name}-通过Preparestatement的方式进行设置 ${name}-通过statement的方式进行设置
${}方式取值:
② mybatis对所有传入的NULL值映射的都是原生jdbc的OTHER类型(jdbcTypes.class文件中定义的枚举类型)
③ Mysql能够识别出OTHER类型,但是Oracle数据库则不能处理OTHER类型,可以在取值表达式中手动定义Null值得处理:*#{name,jdbcType=NULL}* 或者在核心配置文件
中设置全局null值处理,如下:
4. 返回值类型的处理
① Int/bean对象 对修改操作的返回值
② List 在sql映射文件中指定resultType的类型,此类型是List中的元素类型,mybatis会把查询结果中的每一条数据封装成一个resultType指定的类型并添加到List中
public List<User> selectParam(User user);
<select id="selectParam" parameterType="User" resultType="User">
select uid,name,sex from usertable where name like #{name,jdbcType=NULL} order by #{sex}
</select>
③ Map<String,Object>
A、返回单条记录:key就是列名,value为列的值,resultType=”map”/“Map”
public Map<String,Object> selectMapOne(int uid);
<select id="selectMapOne" parameterType="int" resultType="Map">
select uid,name,sex from usertable where uid = #{uid}
</select>
B、返回多条记录Map<String,User>:key为指定的属性值,value为当前对象(一个属性值对应一条记录),resultType=”map中值(value)的类型”,另外需要在接口方法前通过@MapKey(“uid”)来指定key
@MapKey("name")//指定某个bean的属性值作为Map的key,这里指定的是name
public Map<String,User> selectMap(int uid);
<select id="selectMap" parameterType="int" resultType="Map">
select uid,name,sex from usertable where uid < #{uid}
</select>
System.out.println("--------返回List---------");
User user = new User(5, "张%", "age", 1);
List<User> list = userdao.selectParam(user);
for(User t :list) {
System.out.println(t);
}
System.out.println("--------返回Map(单条记录)---------");
Map<String,Object> map = userdao.selectMapOne(1);
for(Entry<String,Object> entry : map.entrySet()) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
System.out.println("--------返回Map(多条记录)---------");
Map<String,User> map1 = userdao.selectMap(5);
for(Entry<String,User> entry : map1.entrySet()) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
符号 | 转义字符 | 说明 |
---|---|---|
< | < | 小于 |
<= | <= | 小于等于 |
> | > | 大于 |
>= | >= | 大于等于 |
& | & | 逻辑与 |
‘xxx’ | ' | 单引号 |
“xxx” | " | 双引号 |
5. select元素
① parameterType可省略,mybatis会根据TypeHandler.class and TypeHandlerRegistry.class进行自动匹配转换
② 元素属性
6. 返回结果映射规则
① 可在全局setting中进行设置,实现的是自动映射
Setting的属性:默认是开启自动映射的功能,要求列名和属性名要一致,如果把值设为null,则取消自动映射
② 驼峰映射规则:A_COLUMN 自动映射成属性 aColumn,需要开启mapUnderscoreToCamelCase
③ 手动映射配置
级联关系-association
1. N-1
方式一:对象限定符
① 在N端定义1端的对象属性
② 定义resultMap映射
<resultMap id="myMap1" type="User" >
<id column="uid" property="uid" jdbcType="INTEGER" javaType="int"/>
<result column="name" property="name" jdbcType="VARCHAR" javaType="String"/>
<result column="age" property="age" jdbcType="VARCHAR" javaType="String"/>
<result column="sex" property="sex" jdbcType="INTEGER" javaType="int"/>
<result column="aid" property="address.aid" jdbcType="INTEGER" javaType="int"/>
<result column="aname" property="address.aname" jdbcType="VARCHAR" javaType="String"/>
</resultMap>
③ Sql语句
<select id="getUserN1" parameterType="int" resultMap="myMap1">
select uid,name,sex,a.aid aid,aname
from usertable u ,address a
where u.aid=a.aid and uid = #{uid}
</select>
方式二:association赋值
<resultMap id="myMap2" type="User" >
<id column="uid" property="uid" jdbcType="INTEGER" javaType="int"/>
<result column="name" property="name" jdbcType="VARCHAR" javaType="String"/>
<result column="age" property="age" jdbcType="VARCHAR" javaType="String"/>
<result column="sex" property="sex" jdbcType="INTEGER" javaType="int"/>
<association property="address" javaType="bean.Address">
<id column="aid" property="aid" jdbcType="INTEGER" javaType="int"/>
<result column="aname" property="aname" jdbcType="VARCHAR" javaType="String"/>
</association>
</resultMap>
方式三:分步查询
① 创建1端的根据id查询对象的映射文件
<?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="dao.AddressDao">
<select id="selectAnameByAid" parameterType="int" resultType="Address">
select aid,aname from address where aid = #{aid}
</select>
</mapper>
② 在N端通过association元素进行映射
<resultMap id="myMap3" type="User" >
<id column="uid" property="uid" jdbcType="INTEGER" javaType="int"/>
<result column="name" property="name" jdbcType="VARCHAR" javaType="String"/>
<result column="age" property="age" jdbcType="VARCHAR" javaType="String"/>
<result column="sex" property="sex" jdbcType="INTEGER" javaType="int"/>
<association column="aid" select="dao.AddressDao.selectAnameByAid" property="address" >
<!-- column 是N端(user)查询的外键列字段名,作为select指定sql的入参 -->
</association>
</resultMap>
<select id="getUserN1_Step" parameterType="int" resultMap="myMap3">
select uid,name,sex,aid
from usertable
where uid = #{uid}
</select>
③ 延迟加载 | 懒加载
当开发者代码中调用哪个对象时才会向数据库发送sql请求
在全局配置文件中进行设置:
System.out.println("----------延迟加载/懒加载----");
User user3 = userdao.getUserN1_Step(1);
// System.out.println(user3);
//当直接输出对象时,因为address是它的属性,所以会立即加载
System.out.println(user3.getName());
//当输出的属性不涉及address时,延迟加载。
System.out.println(user3.getAddress());
2. 1-N
方式一:collection元素进行赋值
① 在1端的bean中创建接收N端的集合
② 在1端的映射文件中创建resultMap结果集的映射
<resultMap type="Address" id="map1_N">
<id column="aid" property="aid"/>
<result column="aname" property="aname"/>
<collection property="userlist" ofType="User">
<id column="uid" property="uid" jdbcType="INTEGER" javaType="int"/>
<result column="name" property="name" jdbcType="VARCHAR" javaType="String"/>
</collection>
</resultMap>
<select id="getUserByAid" parameterType="int" resultMap="map1_N">
select a.aid aid,aname,uid,name from address a, usertable u
where a.aid = u.aid and a.aid = #{aid}
</select>
方式二:分步查询
<resultMap type="Address" id="map1_N_Step">
<id column="aid" property="aid"/>
<result column="aname" property="aname"/>
<!-- 把1端的某个字段作为参数值传入N端作为N端的入参 -->
<collection property="userlist" ofType="User"
column="aid" select="dao.UserDao.getUserByAid" >
</collection>
</resultMap>
<select id="getAnameByAid" parameterType="int" resultMap="map1_N_Step">
select aid,aname from address
where aid = #{aid}
</select>
<resultMap id="myMap4" type="User" >
<id column="uid" property="uid" jdbcType="INTEGER" javaType="int"/>
<result column="name" property="name" jdbcType="VARCHAR" javaType="String"/>
</resultMap>
<select id="getUserByAid" parameterType="int" resultMap="myMap4">
select uid,name from usertable
where aid = #{aid}
</select>
注意:映射文件中的sql元素需要和接口中的方法名要一致,mybatis是通过接口的动态代理去调用sql元素
懒加载策略和N-1中的一致
分步查询中传递多个参数:
把1端的多个元素作为查询的条件
延迟加载策略属性:
3. Discriminator鉴别器
根据得到的某个参数值,不同的值/情况将会有不同的动作,其实就是if/else
动态sql
动态sql可以灵活的根据业务逻辑条件自动组装最终执行的sql语句
OGNL:对象图导航语言,object.name
先附上测试:
public static void main(String[] args) {
String resource = "configuration.xml";
SqlSession session = GetSqlSession.getSqlSession(resource);
UserDao userDao = session.getMapper(UserDao.class);
User user = new User(0, "张%", "45", 1);
// System.out.println("----------动态sql:if/choose-----------");
// List<User> userlist = userDao.getUser_if_choose(user);
// for(User u : userlist) {
// System.out.println(u);
// }
// System.out.println("----------动态sql:where/trim-----------");
// List<User> userlist1 = userDao.getUser_where_trim(user);
// for(User u : userlist1) {
// System.out.println(u);
// }
// System.out.println("----------动态sql:set-----------");
// User user1 = new User(9, "王五", "45", 0);
// int i = userDao.updateUser_set(user1);
// System.out.println(i);
System.out.println("----------动态sql:foreach-----------");
List<Integer> list = Arrays.asList(1,2,4,5,9);
List<User> userlist2 = userDao.getUser_foreach(list);
for(User u : userlist2) {
System.out.println(u);
}
session.close();
}
1. if
test是条件,特殊字符用转义字符来写,&—>& “”
2. choose
从多个选项中选择一个值,类似switch…case
子标签:when otherwise
<select id="getUser_if_choose" resultType="User">
select <include refid="commonsql"></include> from usertable
where 1 = 1
<!--
<if test="name != null && name.trim() != """>
and name like #{name}
</if>
<if test="age != 0">
and sex = #{sex}
</if>
-->
<choose>
<when test="name != null && name.trim() != """>
and name like #{name}
</when>
<when test="age != 0">
and sex = #{sex}
</when>
<otherwise>
and age = #{age}
</otherwise>
</choose>
</select>
3. where
4. trim
注意:prefix(加前缀),suffix(加后缀), prefixOverrides(去掉首个…),suffixOverrides(去掉最后的…)
<select id="getUser_where_trim" resultType="User">
select <include refid="commonsql"></include>
from usertable
<!-- 会自动加上where关键字,并且去除where后的第一个条件连接关键字(and/or)
<where>
<if test="name != null && name.trim() != """>
and name like #{name}
</if>
<if test="age != 0">
and sex = #{sex}
</if>
</where>
-->
<trim prefix="where" prefixOverrides="and">
<if test="name != null && name.trim() != """>
and name like #{name}
</if>
<if test="age != 0">
and sex = #{sex}
</if>
</trim>
</select>
5. set
<update id="updateUser_set">
update usertable
<set>
<if test="name != null && name.trim() != """>
name = #{name},
</if>
<if test="age != 0">
age = #{age},
</if>
</set>
where uid = #{uid}
</update>
使用trim替换set实现:
6. foreach
接口中的参数可以是集合或数组类型,MyBatis会把参数自动的封装成Map对象,其中List对象的key是“list”,数组对象的key是”array”。
<select id="getUser_foreach" resultType="User">
select <include refid="commonsql"></include>
from usertable where uid in
<foreach collection="list" open="(" separator="," close=")" index="index" item="item">
#{item}
</foreach>
</select>
批量保存:
7. bind标签
把某一个参数值绑定到上下文中的一个变量中,可以在sql中重复使用
8. Sql片段
MyBatis内置参数
特殊字符处理
MyBatis的缓存
MyBatis中默认的缓存有两级缓存,分别是一级缓存和二级缓存
一级缓存LocalCaching
与数据库在同一次会话期间所查询的数据会自动缓存到一级缓存中(本地缓存),如果后续对相同数据的查询,那么就会直接从本地缓存中进行获取,就不会再去查询数据库了。
String resource = "configuration.xml";
SqlSession session = GetSqlSession.getSqlSession(resource);
//注意是同一个session
UserDao userDao = session.getMapper(UserDao.class);
//首次查询的结果会放入一级缓存中
User user = userDao.selectUser(1);
System.out.println(user);
//第二次查询相同的数据时就直接从以及缓存中获取
User user1 = userDao.selectUser(1);
System.out.println(user1);
System.out.println(user==user1);
session.close();
二级缓存CachingExecutor
① 二级缓存介绍
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import bean.User;
import dao.UserDao;
public class TestGlobalCache {
public static void main(String[] args) {
String resource = "configuration.xml";
Reader reader = null;
try {
reader = Resources.getResourceAsReader(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = ssf.openSession(true);
UserDao userDao = session.getMapper(UserDao.class);
//首次查询的结果放在一级缓存里
User user = userDao.selectUser(1);
System.out.println(user);
//关闭session,会把一级缓存里的内容转移到二级缓存里
session.close();
SqlSession session1 = ssf.openSession(true);
UserDao userDao1 = session1.getMapper(UserDao.class);
//查找: 先二级缓存,在一级缓存,最后DB
User user1 = userDao1.selectUser(1);
System.out.println(user1);
System.out.println(user==user1);//true
session1.close();
}
}
SqlSessionFactory要是同一个!!!
③ 二级缓存的运行过程
第三方缓存接口Ehcache
MyBatis主要是处理ORM的业务,并非专门做缓存处理的,MyBatis定义了Cache缓存接口方便开发者自定义缓存扩展,MyBatis官方提供了很多种集成缓存的Adapter适配器。
Ehcache是纯java写的缓存框架,是Hibernate中默认的缓存策略。
SSM框架整合
SSM主要是指spring和mybatis的整合,spring和mybatis的整合需要在mybatis官网上下载mybatis-spring.jar整合包
① 创建web工程,引入ssm的jar
② 搭建Mybatis的环境
③ 搭建SpringMVC的环境
④ 搭建Spring的环境(Spring整合MyBatis的配置)
MBG
MyBatis源码分析