MyBatis知识点汇总
2021-03-18 20:05:33 115 举报
AI智能生成
根据自身项目进行MyBatis的知识点汇总,包含MyBatis搭建过程,参数获取,延迟加载,动态SQL,缓存机制、逆向工程等。同时进行SSM整合记录。 公众号【小张日拱一卒】,回复ssm获取视频文档资源。
作者其他创作
大纲/内容
框架:具有约束性的去支持我们完成各种功能的半成品项目(框架+业务逻辑 = 完整项目)
框:具有约束性 定义标准(多人开发,最终整合)
架:能够支撑某些东西 Spring对java底层的封装
持久层框架
整合型框架/设计型框架
spring
MyBatis
简介
支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架
避免了
几乎所有的 JDBC 代码(对JDBC进行封装)
手动设置参数
不需要设置通配符,用${value}、#{}
获取结果集
以使用简单的 XML 或 注解 用于配置和原始映射
XML
SQL语句写在XML中,方便更改业务需求
推荐
注解方式
SQL语句需要放在类中
上线部署过程对java进行打包,如果也业务需求变更,不易更改
半自动的ORM(Object Relation Mapping)框架
Object:Java对象
Relation:关系型数据库中的一条记录
Mysql为关系型数据库
两者创建映射关系
将接口和POJO映射成数据库中的记录
Plain Old Java Objects,普通的Java对象
为什么要使用MyBatis – 现有持久化技术的对比
JDBC
开发效率最低
手动完成过程:
加载驱动
创建连接
创建预编译对象
为通配符赋值
赋值后执行SQL语句
处理结果
执行效率最高
MyBatis需要对其封装,使用过程需要解析
Hibernate
长难复杂SQL,处理不易
对自动生成的SQL语句不易优化
开发效率最快,执行效率最低
MyBatis
开发容易
SQL语句手动优化
解耦
SQL和java编码分离
功能分界清晰
一个专注业务,一个专注数据
MyBatis搭建过程
①导入jar
log4j(log4j配置文件定义日志输出格式)、mybatis、mysql-connector-java
mysql-connector-java建议与mysql版本一致,不一致可能无法连接
②创建mybatis的核心(全局)配置文件mybatis-config.xml,并配置
核心配置:如何连接数据库
<settings>(常用)
<setting name="mapUnderscoreToCamelCase" value="true"/>
将下划线转换成驼峰命名法
例如:数据库字段user_name,实体类字段userName
<select id="getUserByUid" resultType="org.xinzhang.mybatistest.bean.User">
select uid,user_name,password,age,sex from user where uid = ${value }
</select>
select uid,user_name,password,age,sex from user where uid = ${value }
</select>
配置之前
User [uid=1, userName=null, password=123, age=25, sex=man]
配置之后
User [uid=1, userName=xinzhang, password=123, age=25, sex=man]
<typeAliases>
为类型设置类型别名
<typeAliases>
<typeAlias alias="Page" type="cn.ac.sict.common.persistence.Page" /><!--分页 -->
</typeAliases>
<typeAlias alias="Page" type="cn.ac.sict.common.persistence.Page" /><!--分页 -->
</typeAliases>
<typeAliases>
<package name="org.xinzhang.mybatistest.bean"/>
</typeAliases>
<package name="org.xinzhang.mybatistest.bean"/>
</typeAliases>
配置之前
<select id="getUserByUid" resultType="org.xinzhang.mybatistest.bean.User">
select uid,user_name,password,age,sex from user where uid = ${value }
</select>
select uid,user_name,password,age,sex from user where uid = ${value }
</select>
需要写满全称
配置之后
<select id="getUserByUid" resultType="User">
select uid,user_name,password,age,sex from user where uid = ${value }
</select>
select uid,user_name,password,age,sex from user where uid = ${value }
</select>
只需填写类名
<environments>
default
设置默认数据库
可以多个<environment>
设置某个具体的数据库的环境
id
数据库环境的唯一标示
<transactionManager type="JDBC" />
type="JDBC|MANAGED"
JDBC
使用JDBC原生的事务管理方式,即提交和回滚都需要手动处理
手动处理事务
SqlSession sqlSession1 = sqlSessionFactory.openSession()
自动处理事务
SqlSession sqlSession = sqlSessionFactory.openSession(true);
操作数据库,增加一次,自增id无论成功与否都会自增
数据源、声明事务均在Spring中配置
<mappers>
引入映射文件
③创建映射文件XxxMapper.xml,并配置
SQL语句写在映射文件中
映射文件:操作数据库
<select>标签
定义查询语句
id
设置SQL语句的唯一标示
resultType
结果类型,即实体类的全限定名
将返回结果自动放入相应容器中
查询所有数据,返回实体类类型,MyBatis自动选择容器
resultType="Emp"
resultType="Integer"
resultType="java.util.HashMap"
<mapper>标签
<mapper namespace="org.xinzhang.mybatistest.mapper.UserMapper">
namespace指向java的DAO层的接口
④创建mapper接口(面向接口编程),实现两个绑定(调用接口中的方法执行SQL语句)
接口全限定名要和XML映射文件的namespace保持一致
接口中方法名和SQL语句的id保持一致
CRUD增删改查接口
增删改返回结果
Boolean
返回结果是否成功
Integer
返回操作影响了几行(常用)
@MapKey("eid")
Map<String,Object> getAllEmps();
Map<String,Object> getAllEmps();
设置map的键,因为在查询时传出所有的员工信息,可以把员工信息作为值,但是必须设置键
resultType="java.util.HashMap"
结果
{1=Emp{eid=1, ename='张三', age=23, sex='man', dept=null}, 2=Emp{eid=2, ename='李四', age=32, sex='man', dept=null},
⑤获取mybatis操作数据库的会话对象SqlSession,通过getMapper()获取接口的动态代理实现类
⑥测试
MyBatis获取参数的两种方式
区别
单引号问题
${value}
Statement对象来处理SQL语句,拼接,控制台直接显示输入的值
<insert id="insertEmp" useGeneratedKeys="true" keyProperty="eid">
insert into emp values(null, '${ename}', ${age}, '${sex}')
</insert>
控制台显示:insert into emp values(null, admin , 23 , man)
insert into emp values(null, '${ename}', ${age}, '${sex}')
</insert>
控制台显示:insert into emp values(null, admin , 23 , man)
只能用字符串拼接(注意要加单引号问题)
使用场景
批量删除
delete from emp where eid in (6,11,12);
<delete id="deleteMoreEmp">
delete from emp where eid in (${value})
</delete>
delete from emp where eid in (${value})
</delete>
模糊查询
需求:主键自增,添加数据的同时获取数据的id
<insert id="insertEmp" useGeneratedKeys="true" keyProperty="eid">
insert into emp values(null, #{ename}, #{age}, #{sex})
</insert>
insert into emp values(null, #{ename}, #{age}, #{sex})
</insert>
Emp admain = new Emp(null, "admain", 15, "man");
mapper.insertEmp(admain);
System.out.println(admain.getEid());
mapper.insertEmp(admain);
System.out.println(admain.getEid());
useGeneratedKeys
可以使用自动生成的主键
keyProperty
将自动生成的主键赋值给传递过来的参数的哪一个属性
适用于一对多,多对一等场景
#{}
创建Preparestatement预编译对象,显示通配符?问号
可以防止SQL注入
<insert id="insertEmp" useGeneratedKeys="true" keyProperty="eid">
insert into emp values(null, #{ename}, #{age}, #{sex})
</insert>
控制台显示:insert into emp values(null, ? , ? , ?)
insert into emp values(null, #{ename}, #{age}, #{sex})
</insert>
控制台显示:insert into emp values(null, ? , ? , ?)
自动加入单引号
不同参数类型,两者不同的取值方式
传输参数为单个String或基本数据类型和其包装类
${value}
大括号内只能写value或_parameter获取
#{}
大括号内可以写任意值
当传输参数为javaBean时
都可以通过属性名直接获取值
${value}
'${ename}'
#{}
#{ename}
当传输多个参数时,MyBatis默认将这些参数放入Map集合中
${value}
select eid,ename,age,sex from emp where eid = ${param1} and ename = '${param2}'
键
param1、param2……
#{}
select eid,ename,age,sex from emp where eid=#{0} and ename=#{1}
键
0、1、2……
BindingException
获取参数异常
当传输Map参数时
两种都可以通过键的名字直接获取值
注意${}的单引号问题
(建议)命名参数:自定义键值
Emp getEmpByEidAndEnameByParam(@Param("eid")String eid, @Param("ename")String ename);
<select id="getEmpByEidAndEnameByParam" resultType="Emp">
select eid,ename,age,sex from emp where eid = #{eid} and ename = #{ename}
</select>
select eid,ename,age,sex from emp where eid = #{eid} and ename = #{ename}
</select>
void deleteMoreByList(@Param("eids")List<Integer> eids);
<delete id="deleteMoreByList">
delete from emp where eid in
<foreach collection="eids" item="eid" separator="," open="(" close=")">
#{eid}
</foreach>
</delete>
delete from emp where eid in
<foreach collection="eids" item="eid" separator="," open="(" close=")">
#{eid}
</foreach>
</delete>
测试
List<Integer> eids = new ArrayList<>();
eids.add(7);
eids.add(8);
eids.add(10);
mapper.deleteMoreByList(eids);
eids.add(7);
eids.add(8);
eids.add(10);
mapper.deleteMoreByList(eids);
当传输参数为List或Array,MyBatis会将List或Array放到map中(动态SQL语句)
List以list为键
void deleteMoreByList(List<Integer> eids);
<delete id="deleteMoreByList">
delete from emp where eid in
<foreach collection="list" item="eid" separator="," open="(" close=")">
#{eid}
</foreach>
</delete>
delete from emp where eid in
<foreach collection="list" item="eid" separator="," open="(" close=")">
#{eid}
</foreach>
</delete>
测试
List<Integer> eids = new ArrayList<>();
eids.add(7);
eids.add(8);
eids.add(10);
mapper.deleteMoreByList(eids);
eids.add(7);
eids.add(8);
eids.add(10);
mapper.deleteMoreByList(eids);
Array以array为键
Emp多、Dept一两张表(多对一,一对多)
实现:查询员工的信息(包含部门信息)
多个员工对应一个部门,多对一关系
多个员工对应一个部门,多对一关系
SQL语句实现(两表联查)
select * from emp e ,dept d where e.did = d.did;
条件不匹配(有空值)造成数据丢失
select * from emp e left join dept d on e.did = d.did;
左外连接
以左张表为标准
映射关系不匹配,解决:自定义映射关系
方案一(很少使用)
<mapper namespace="org.xinzhang.mybatistest.mapper.EmpDeptMapper">
<resultMap type="Emp" id="empMap">
<id column="eid" property="eid"/>
<result column="ename" property="ename"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<result column="did" property="dept.did"/>
<result column="dname" property="dept.dname"/>(方案二代码替换此处)
</resultMap>
<select id="getAllEmp" resultMap="empMap">
select e.eid, e.ename, e.age, e.sex, e.did, d.dname from emp e left join dept d on e.did = d.did
</select>
</mapper>
<resultMap type="Emp" id="empMap">
<id column="eid" property="eid"/>
<result column="ename" property="ename"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<result column="did" property="dept.did"/>
<result column="dname" property="dept.dname"/>(方案二代码替换此处)
</resultMap>
<select id="getAllEmp" resultMap="empMap">
select e.eid, e.ename, e.age, e.sex, e.did, d.dname from emp e left join dept d on e.did = d.did
</select>
</mapper>
<resultMap>
id
设置主键的映射关系
column对应数据库字段
property对应实体类属性
result
设置其他映射,不能省略
type
返回类型,实体类型
select
resultMap属性填<resultMap>中的id
方案二
<association property="dept" javaType="Dept">
<id column="did" property="did"/>
<result column="dname" property="dname"/>
</association>
<id column="did" property="did"/>
<result column="dname" property="dname"/>
</association>
<association>
解决多对一的表对应关系
需要使用javaType属性
不能确定property中具体是什么属性
帮忙创建对象,javaType所写类型对象,底层:大量反射(无反射无框架)
did,dname均为Dept中属性
把查询出来的结果赋值给Dept中did和dname
创建对象后再赋值给dept属性
方案三:常用分步查询(避免两表联查)
查询员工所有信息,包括员工的部门id
通过部门id查询部门名称,而非一步查询出所有信息
通过部门id查询部门名称,而非一步查询出所有信息
<resultMap id="EmpMapStep" type="Emp">
<id column="eid" property="eid"/>
<result column="ename" property="ename"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<association property="dept"
select="org.xinzhang.mybatistest.mapper.DeptMapper.getDeptByDid" column="did"/>
</resultMap>
<select id="getEmpStep" resultMap="EmpMapStep">
select eid,ename,age,sex,did from emp where eid = #{eid}
</select>
<id column="eid" property="eid"/>
<result column="ename" property="ename"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<association property="dept"
select="org.xinzhang.mybatistest.mapper.DeptMapper.getDeptByDid" column="did"/>
</resultMap>
<select id="getEmpStep" resultMap="EmpMapStep">
select eid,ename,age,sex,did from emp where eid = #{eid}
</select>
<mapper namespace="org.xinzhang.mybatistest.mapper.DeptMapper">
<select id="getDeptByDid" resultType="Dept">
select did,dname from dept where did = #{did}
</select>
</mapper>
<select id="getDeptByDid" resultType="Dept">
select did,dname from dept where did = #{did}
</select>
</mapper>
select
通过查询语句得到结果为property的dept赋值
接口需要加入全限定命名(namespace)确定为唯一标识
column
要把哪个字段作为分步查询的条件
此条件必须为数据库查询而得
实现:查询某个部门中包含所有的员工的信息
一个部门可以有多个员工,一对多的关系
一个部门可以有多个员工,一对多的关系
java接口:Dept getDeptEmpsByDid(String did);
xml配置映射文件:
<select id="getDeptEmpsByDid" resultMap="deptMap">
select d.did,d.dname,e.eid,e.ename,e.age,e.sex from dept d left join emp e on d.did = e.did where d.did = #{did}
</select>
xml配置映射文件:
<select id="getDeptEmpsByDid" resultMap="deptMap">
select d.did,d.dname,e.eid,e.ename,e.age,e.sex from dept d left join emp e on d.did = e.did where d.did = #{did}
</select>
不能使用resultType="Dept"
因为返回结果是多个员工,多条数据
<resultMap id="deptMap" type="Dept">
<id column="did" property="did"/>
<result column="dname" property="dname"/>
<collection property="emps" ofType="Emp">
<id column="eid" property="eid"/>
<result column="ename" property="ename"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
</collection>
</resultMap>
<id column="did" property="did"/>
<result column="dname" property="dname"/>
<collection property="emps" ofType="Emp">
<id column="eid" property="eid"/>
<result column="ename" property="ename"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
</collection>
</resultMap>
使用collection标签(处理一对多,多对一)
不会关注返回的是否是集合类型
即,不适用javaType
即,不适用javaType
使用ofType
标记集合中一条数据的类型
分步实现方式
java接口文件
//根据did 查部门信息
Dept getOnlyDeptByDid(String did);
//根据did 查所有员工信息
List<Emp> getEmpsListByDid(String did);
//根据did 查部门信息
Dept getOnlyDeptByDid(String did);
//根据did 查所有员工信息
List<Emp> getEmpsListByDid(String did);
<select id="getEmpsListByDid" resultType="Emp">
select eid,ename,age,sex from emp where did = #{id}
</select>
<resultMap id="getOnlyDept" type="Dept">
<id column="did" property="did"/>
<result column="dname" property="dname"/>
<collection property="emps"
select="org.xinzhang.mybatistest.mapper.EmpDeptMapper.getEmpsListByDid"
column="{id=did}}"
fetchType="eager"
/>
</resultMap>
<select id="getOnlyDeptByDid" resultMap="getOnlyDept">
select did,dname from dept where did=#{did}
</select>
select eid,ename,age,sex from emp where did = #{id}
</select>
<resultMap id="getOnlyDept" type="Dept">
<id column="did" property="did"/>
<result column="dname" property="dname"/>
<collection property="emps"
select="org.xinzhang.mybatistest.mapper.EmpDeptMapper.getEmpsListByDid"
column="{id=did}}"
fetchType="eager"
/>
</resultMap>
<select id="getOnlyDeptByDid" resultMap="getOnlyDept">
select did,dname from dept where did=#{did}
</select>
fetchType="eager"
全局配置为延迟加载,某一个部分SQL设置全局加载(渴望)
column="{id=did}}"
可以设置map键值对
id为键,要与#{id}中名字对应
emps为Dept实体类中的属性
查询结果返回多个用collection
说说MyBatis的延迟加载
只对分步查询有效
<setting name="lazyLoadingEnabled" value="true"/>
是否开启延迟加载,默认为false
分步查询均加载(控制台可看日志)
开启:true
<setting name="aggressiveLazyLoading" value="true"/>
默认为false不开启,false为开启深度延迟加载
Emp empStep = mapper.getEmpStep("13");
System.out.println(empStep.getEname());
System.out.println(empStep.getEname());
之后的分表查询不加载
开启:true
Emp empStep = mapper.getEmpStep("13");
System.out.println(empStep.getEname());
System.out.println(empStep.getEname());
之后的分表查询会加载
侵入式延迟加载
动态SQL语句(更好拼接SQL语句)
多条件查询
页面中设置条件,才需要加入SQL语句中
没有设置条件一定不能加
服务器默认值会影响查询结果
单选框复选框
要么有值,要么null
没有空字符串的情况
<if>
<if test="taskModel != null and taskModel != ''">
AND a.task_model = #{taskModel}
</if>
AND a.task_model = #{taskModel}
</if>
<if test=""></if>
通过test表达式,拼接SQL
输入框
null
地址栏输入未给某个属性赋值
“”
空字符串,在表单中未添加信息
<where>
添加where关键字,同时去掉多余的and
<trim prefix="" suffix="" prefixOverrides="" suffixOverrides="">
截取并拼接
prefix
在操作的SQL语句前加入某些内容
suffix
在操作的SQL语句后加入某些内容
prefixOverrides
把操作的SQL语句前的某些内容去掉
suffixOverrides
把操作的SQL语句后的某些内容去掉
<choose>:选择某一个when或otherwise拼接SQL
<when test=""></when>:通过test表达式拼接SQL
<otherwise></otherwise>:当when都不符合条件,就会选择otherwise拼接SQL
</choose>
<when test=""></when>:通过test表达式拼接SQL
<otherwise></otherwise>:当when都不符合条件,就会选择otherwise拼接SQL
</choose>
类似if/if/else
<foreach collection="" item="" close="" open="" separator="" index="">
</foreach>
</foreach>
对一个数组或集合进行遍历
collection
指定要遍历的集合或数组
item
设置别名
open
设置循环体的开始内容
close
设置循环体的结束内容
separator
设置每一次循环之间的分隔符
index
若遍历的是list,index代表下标
若遍历的是map,index代表键
批量操作
delete
delete from emp where eid in ();
delete from emp where eid = 1 or eid = 2 or eid = 3
select
select * from emp where eid in ();
select * from emp where eid = 1 or eid = 2 or eid = 3
update
把每条数据修改为相同内容
update emp set ... where eid in ();
单条数据
UPDATE mybatis_test.emp t SET t.ename = 'xinzhang', t.age = 19, t.did = 2 WHERE t.eid = 14
update emp set ... where eid = 1 or eid = 2 or eid = 3
把每条数据修改为对应内容
update emp set ... where eid = 1;
update emp set ... where eid = 2;
update emp set ... where eid = 3;
update emp set ... where eid = 2;
update emp set ... where eid = 3;
预编译过程只允许一条SQL语句
必须在配置文件的连接地址(url)后添加参数&allowMultiQueries=true
insert
insert into emp values(),(),()
INSERT INTO mybatis_test.emp (ename, age, sex, did) VALUES ('xx', 22, '1', 2),('ccc', 13, '0', 1)
sql
<sql id=""></sql>
设置一段SQL片段,即公共SQL,可以被当前映射文件中所有的SQL语句所访问
<include refid="empColumns"></include>
访问某个SQL片段
说说MyBatis的缓存机制
MySQL数据存储在硬盘
相对:存储在内存读取速度更快
Redis缓存
缓存服务器
一级缓存
默认开启
SqlSession级别
同一个SqlSession,对于一个sql语句,执行之后就会存储在缓存中,下次执行相同的sql,直接从缓存中取
一级缓存工作机制
同一次会话期间(SqlSession)只要查询过的数据都会保存在当前SqlSession的一个Map中
key: hashCode+查询的SqlId+编写的sql查询语句+参数
一级缓存失效情况
不同的SQLSession执行相同的查询语句
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession(true);
SelectByConditions mapper = sqlSession.getMapper(SelectByConditions.class);
Emp emp = mapper.selectTestCache("13");
System.out.println(emp);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
SelectByConditions mapper = sqlSession.getMapper(SelectByConditions.class);
Emp emp = mapper.selectTestCache("13");
System.out.println(emp);
System.out.println("----------不同sqlSession的情况-----------");
SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
EmpMapper mapper2 = sqlSession2.getMapper(EmpMapper.class);
Emp emp2 = mapper2.getEmpByEid("13");
System.out.println(emp2);
SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
EmpMapper mapper2 = sqlSession2.getMapper(EmpMapper.class);
Emp emp2 = mapper2.getEmpByEid("13");
System.out.println(emp2);
同一个SqlSession但是查询条件不同
System.out.println("---------查询条件不同时------------");
Emp emp2 = mapper.selectTestCache("14");
System.out.println(emp2);
Emp emp2 = mapper.selectTestCache("14");
System.out.println(emp2);
同一个SqlSession两次查询期间执行了任何一次增删改操作,会自动将缓存清空
同一个SqlSession两次查询期间手动清空了缓存
sqlSession1.clearCache();
只用来清除一级缓存
在XML某个<select>标签中配置flushCache="true"
增删改默认flushCache="true"
同时清空一级缓存和二级缓存
查询flushCache默认false
二级缓存
二级缓存存在于 SqlSessionFactory 生命周期中
使用步骤
在核心配置文件myBatis-config.xml中开启二级缓存总开关
<settings>
<!--全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!--全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。 -->
<setting name="cacheEnabled" value="true"/>
</settings>
一级缓存一直是打开的
在Mapper.xml映射文件中,开启二级缓存分开关
默认不开启
<cache />
eviction
缓存回收策略
LRU(默认)
最近最少使用的:移除最长时间不被使用的对象
FIFO
先进先出:按对象进入缓存的顺序来移除它们
SOFT
软引用:移除基于垃圾回收器状态和软引用规则的对象
WEAK
弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象
flushInterval
刷新间隔,单位毫秒
默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
size
引用数目,正整数
代表缓存最多可以存储多少个对象,太大容易导致内存溢出
readOnly
true
只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势
false
读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false
select标签的useCache属性
配置这个select是否使用二级缓存。一级缓存一直是使用的
二级缓存开启的情况下,控制当前某一个select不开启二级缓存
POJO需要实现Serializable接口
二级缓存的数据不一定都存储到内存,它的存储介质多种多样,所以需要给缓存的对象执行序列化
缓存默认是存入内存中,但是如果需要把缓存对象存入硬盘需要序列化(实体类要实现)
缓存默认是存入内存中,但是如果需要把缓存对象存入硬盘需要序列化(实体类要实现)
常用第三方缓存(EhCache、Redis)
EhCache 是纯Java的进程内缓存框架,具有快速、精干特点
提高扩展性,定义缓存接口Cache,通过实现Cache接口来自定义二级缓存
内存中放不下,放入到磁盘中
通过序列化接口实现
整合EhCache缓存的步骤
①导入ehcache包
ehcache-core-2.6.8.jar
mybatis-ehcache-1.0.3.jar
slf4j-api-1.6.1.jar、slf4j-log4j12-1.6.2.jar
②ehcache.xml配置文件
③配置cache标签
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
MyBatis逆向工程(MyBatis Generator,MBG)
代码生成器
可以快速的根据表生成对应的映射文件,接口,以及bean类
支持基本的增删改查,以及QBC风格的条件查询
表连接、存储过程等复杂sql的定义需要手工编写
条件语句
Criteria c1 = example.createCriteria();
类似MongoDB非关系型数据库(QBC风格)
案例:WMS如何自动生成七个文件
拓展:分页插件
mybatis-config.xml中插件配置
<plugins>
<plugin interceptor="cn.ac.sict.common.persistence.interceptor.PaginationInterceptor" />
</plugins>
<plugin interceptor="cn.ac.sict.common.persistence.interceptor.PaginationInterceptor" />
</plugins>
/wms/wms-system/src/main/java/cn/ac/sict/common/persistence/Page.java
分页类
@author ThinkGem
@version 2013-7-2
@param <T>
@author ThinkGem
@version 2013-7-2
@param <T>
SSM框架整合
SpringMVC控制层+MyBatis持久层,两者不会相互影响
整合Spring与SpringMVC
整合Spring与MyBatis
Spring功能:IOC、AOP
利用好Spring功能
IOC管理对象
MyBatis对象均交给Spring来管理
优势:创建对象为单例,管理对象生命周期
SqlSessionFactory
MyBatis操作数据库的数据源交给Spring
声明事务
MyBatis-Spring适配包
将MyBatis对象进行封装方便Spring来管理
SSM整合步骤
①导入jar
Spring
SpringMVC
MyBatis
第三方支持
log4j、pageHelper、AspectJ、jackson、jstl
②搭建SpringMVC
web.xml
DispatcherServlet
<!-- springMVC核心控制器DispatcherServlet -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
HiddenHttpMethodFilter
<!-- REST请求方式处理 -->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
CharacterEncodingFilter
<!-- spring编码过滤器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
springMVC.xml
扫描控制层组件
<!-- 扫描控制层组件 -->
<context:component-scan base-package="org.xinzhang.ssm.controller"></context:component-scan>
<context:component-scan base-package="org.xinzhang.ssm.controller"></context:component-scan>
视图解析器
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
Default Servlet
<!-- 默认的servlet -->
<mvc:default-servlet-handler/>
<mvc:default-servlet-handler/>
MVC驱动
<!-- MVC驱动 -->
<mvc:annotation-driven />
<mvc:annotation-driven />
可选
MultipartResolver
拦截器
③整合SpringMVC和Spring
web.xml
ContextLoaderListener
<!-- 配置spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
context-param
<!-- 自定义spring配置文件的位置和名称 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
spring.xml
扫描组件(排除控制层)
<!-- 扫描组件 -->
<context:component-scan base-package="org.xinzhang.ssm" >
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<context:component-scan base-package="org.xinzhang.ssm" >
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
④搭建MyBatis
核心配置文件
<settings>
<!-- 将下划线映射成驼峰,user_name映射为userName -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 是否开启深度延迟加载false开启-->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 是否开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 将下划线映射成驼峰,user_name映射为userName -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 是否开启深度延迟加载false开启-->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 是否开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 插件配置 -->
<plugins>
<plugin interceptor="cn.ac.sict.common.persistence.interceptor.PaginationInterceptor" />
</plugins>
<plugins>
<plugin interceptor="cn.ac.sict.common.persistence.interceptor.PaginationInterceptor" />
</plugins>
mapper接口和mapper映射文件
⑤Spring整合Mybatis
Spring.xml
properties文件的引入
<!-- 引入资源文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<context:property-placeholder location="classpath:jdbc.properties"/>
DataSource数据源的配置
<!-- 数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
事务管理器
<!-- 声明事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
开启事务驱动
<!-- 开启事务注解驱动 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
SqlSessionFactoryBean
管理SqlSession
<!-- 管理mybatis操作数据库的会话对象SqlSession -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 设置mybatis核心配置文件的路径 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 设置数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 设置类型别名 -->
<property name="typeAliasesPackage" value="org.xinzhang.ssm.bean"></property>
<!-- 设置映射文件的路径 -->
<property name="mapperLocations" value="classpath:org/xinzhang/ssm/mapper/*.xml"></property>
</bean>
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 设置mybatis核心配置文件的路径 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 设置数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 设置类型别名 -->
<property name="typeAliasesPackage" value="org.xinzhang.ssm.bean"></property>
<!-- 设置映射文件的路径 -->
<property name="mapperLocations" value="classpath:org/xinzhang/ssm/mapper/*.xml"></property>
</bean>
工厂模式getObject()
返回SqlSessionFactory对象来创建SqlSession
通过MyBatis配置文件完成
SqlSession操作数据库需要数据源
注意package和Location
以点分割
以斜杠分割
MapperScannerConfigurer
<!-- 在所设置的包下,将所有的接口生成动态代理实现类,并由spring容器管理 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.xinzhang.ssm.mapper"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.xinzhang.ssm.mapper"></property>
</bean>
@Autowired
private EmpMapper empMapper;
private EmpMapper empMapper;
0 条评论
下一页
为你推荐
查看更多