mybatis
mybatis 配置
- 导入jar包:分别是Mybatis.jar、log4j.jar(同时要引入log4j.xml配置文件)、mysql.jar
- 创建Mybatis的核心(全局)配置文件 (如何连接数据库),并配置
- 创建映射文件(sql语句写在这里),并配置
- 创建Mapper接口 (Mybatis可以面向接口编程),实现两个绑定
- 获取mybatis操作数据库的会话对象SqlSession
- 测试
xml的提示功能(无网状况下)
标签
<configuration>
<!--用于设置或引入外部的资源文件
resourse:类路径下访问的
url:网络或者磁盘路径下访问的资源文件
-->
<properties resource="db.properties"></properties>
<!--
environments:设置连接数据库的环境,default:设置默认使用的环境
-->
<environments default="development">
<!--environment: 设置某个具体的数据库连接环境,id:数据库环境的唯一标识-->
<environment id="development">
<!--transactionManager: 设置事务管理方式
type= “JDBC” or “MANAGE”
JDBC:使用JDBC原生的事物管理,commit和rollback都需要自己手动实现
-->
<transactionManager type="JDBC"></transactionManager>
<!--type="POOLED":使用Mybatis自带的数据库连接池
type="UNPOOLED": 不使用数据库连接池
type="JNDI": 调用上下文中的数据源
-->
<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>
<mappers>
<mapper resource="UserMapper.xml"></mapper>
<!--
也可使用resource 导入一个包名,来减少以后的工作量,但是需要注意***.xml文件要和***Mapper
接口在一个包下
<package name="com.yzh.mapper"></mapper>
-->
</mappers>
</configuration>
需要注意的是在idea中配置文件不能防止src目录下,因此可以在conf文件中创建一个同名的包路径在存放相关xml文件
简单的测试CRUD
- 创建一个bean,为Emp.class
包含了一些基本属性 - 创建该类的一个mapper接口,这个接口定义了一系列的方法
public interface EmpMapper {
Emp getEmpByEid(String eid);
List<Emp> getAllEmp();
void addEmp(Emp emp);
void updateEmp(Emp emp);
void deleteEmp(String eid);
}
- 创建一个EmpMapper.xml文件
该xml文件里主要设置对应的EmpMapper接口中的方法执行的sql语句
<mapper namespace="com.yzh.mapper.EmpMapper">
<!--
<select> 定义查询语句
id: 设置SQL语句的唯一标识
-->
<select id="getEmpByEid" resultType="com.yzh.bean.Emp">
select * from emp where eid = #{id}
</select>
<select id="getAllEmp" resultType="com.yzh.bean.Emp">
select * from emp
</select>
<insert id="addEmp">
insert into emp values(null, #{ename},#{age},#{sex})
</insert>
<update id="updateEmp">
update emp set ename=#{ename}, age=#{age}, sex=#{sex} where eid=#{eid}
</update>
<delete id="deleteEmp">
delete from emp where eid=#{eid}
</delete>
</mapper>
- 在mybatisConfig.xml中引入这个EmpMapper.xml文件
<configuration>
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<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>
<mappers>
<mapper resource="EmpMapper.xml"></mapper>
</mappers>
</configuration>
- 定义一个测试类(查找)
@Test
public void testCRUD() throws Exception{
//加载mybatis的资源文件
InputStream inputStream = Resources.getResourceAsStream("mybatisConfig.xml");
/**
* 1. 使用XMLConfigBuilder解析mybatisConfig.xml,装配到Configuration中
* 2. 将配置文件中的Mapper添加到Configuration mapperRegistry 实现注册
* 3. 使用configuration获取默认的DefaultSqlSessionFactory
*/
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//获得Mapper接口
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp empByEid = mapper.getEmpByEid("2");
System.out.println(empByEid);
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210702103634695.png)
- 添加、删除、修改
必须要手动提交事物,
此外也可在创建sqlSession的时候手动设置true。
Emp emp = new Emp(null,"yzz",21,"男");
mapper.addEmp(emp);
sqlSession.commit();
List<Emp> allEmp = mapper.getAllEmp();
System.out.println(allEmp);
mybatis查询的三种方式
- 查询全部数据,返回List数组
- 只查询一条数据
- 将查询结果保存在HashMap中
<select id="getCount" resultType="Integer">
select count(eid) from emp
</select>
<select id="getEmpMapByEid" resultType="java.util.HashMap">
select eid,ename,age,sex from emp where eid=#{eid}
</select>
<select id="getAllEmpMap" resultType="com.yzh.bean.Emp">
select eid,ename,age,sex from emp
</select>
mybatis获取参数值的两种方式
- ${} 对应了JDBC里面的statement ,使用的是字符串拼接的方法,完成sql的编写,如果用这种方式需要手动添加单引号
- #{} 对应了JDBC里面的preparedstatement,能够防止sql注入
使用建议:推荐使用#{},特殊情况下使用${},例如模糊查询和批量删除
<insert id="addEmp">
insert into emp values(null , '${ename}', '${age}', '${sex}')
</insert>
不同参数类型:
- 当传输参数为单个String或基本数据类型和其他包装类
#{}:可以以任意的名字获取参数值
: 只 能 以 {}:只能以 :只能以{value} 或 {_parameter}获取 - 当传输参数为bean时
都可以通过属性名直接获取值,但是要注意单引号问题 - 当传输多个参数时
#{}: 传入参数的序号如:#{0}、#{1}、……
也可以#{param1}、#{param2}、……
${}:只能用 p a r a m 1 、 {param1}、 param1、{param2}、……
原理:mybatis默认会把传进来的参数放入hashmap中,以0~N-1 或者param0~paramN-1为键,参数为值 - 当传输map参数时
可以直接调用map的键
- 使用注解 @Param
List getEmpBySex(@Param(“sex”)String sex);
它其实也是放在map中 - 当传入参数为List或者Array,mybatis会把List或者Array放在map中,list以list为键,Array以Array为键
多对一自定义映射
方式一
如多个学生对应着某一个班级,多位公司职员对应着一个部门
- 首先有一个职员表,一个部门表,员工表有一个部门id字段
- 在项目中创建好对应的类,创建好一个接口类名称为EmpDeptMapper.java,有一个方法 getAllEmp()获取所有员工信息
- 创建一个EmpDeptMapper.xml,
<mapper namespace="com.yzh.mapper.EmpDeptMapper">
<resultMap id="empDeptMap" type="com.yzh.bean.Emp">
<id column="eid" property="eid"></id>
<result column="ename" property="ename"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
<result column="did" property="dept.did"></result>
<result column="dname" property="dept.dname"></result>
<!-- id: 设置主键的映射关系
column:设置字段名
property:设置属性名
result:设置会主键的映射关系
-->
</resultMap>
<select id="getAllEmp" resultMap="empDeptMap">
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创建一个结果的映射,这个结果包含的字段需要自己来写
需要注意,获取员工信息的时候要考虑没有设置部门的情况,因此使用左外连接。
方式二 常用
使用association
<resultMap id="empDeptMap" type="com.yzh.bean.Emp">
<id column="eid" property="eid"></id>
<result column="ename" property="ename"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
<association property="dept" javaType="com.yzh.bean.Dept">
<id column="did" property="did"></id>
<result column="dname" property="dname"></result>
</association>
</resultMap>
方式三 多对一分布查询
如查询一个学生的信息,要求同时返回该学生的所在班级名称,除了上面的两种方式外,还可以分布查询
- 根据学生id查询学生的基本信息,可以得到did
- 根据did得到学生的班级信息
<resultMap id="empMapStep" type="com.yzh.bean.Emp">
<id column="eid" property="eid"></id>
<result column="ename" property="ename"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
<association property="dept" select="com.yzh.mapper.DeptMapper.getDeptByDid" column="did">
<!--
select: 分布查询的SQL的id,即接口的全限定名,方法名或者namespace.SQL的id
column:分布查询的条件,注意此条件必须是从数据库查询获得
-->
</association>
</resultMap>
<select id="getEmpStep" resultMap="empMapStep">
select eid, ename, age, sex ,did from emp where eid=#{eid}
</select>
分布查询的延迟加载
以上一个部分为例,原本我们使用分布查询获取到了员工的部门信息。但是可能我们并不是立即要使用到部门信息。那么可以采用懒加载的设置,就是说,在用到这部分数据的时候再执行相应的sql语句
- 需要在mybatisConfig.xml文件里配置setting
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启延时加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--是否查询所有数据-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
- 测试
@Test
public void test02() throws Exception{
InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = build.openSession();
EmpDeptMapper mapper = sqlSession.getMapper(EmpDeptMapper.class);
Emp empStep = mapper.getEmpStep("1");
System.out.println(empStep.getEid());
System.out.println(empStep.getDept());
}
可以看到第一次只获得员工id的时候,是没有进行部门信息查询的
一对多映射
常规
在部门类里面 定义一个变量保存所有的员工信息0.0
<resultMap type="com.yzh.bean.Dept" id="deptMap">
<id column="did" property="did"></id>
<result column="dname" property="dname"></result>
<collection property="emps" ofType="com.yzh.bean.Emp">
<id column="eid" property="eid"></id>
<result column="ename" property="ename"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
</collection>
<!--
collection:处理一对多和多对多的关系
ofType: 指定集合的类型,不需要指定javaType
-->
</resultMap>
<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>
多对一的分布查询
<resultMap id="deptMapStep" type="com.yzh.bean.Dept">
<id property="did" column="did"></id>
<result column="dname" property="dname"></result>
<collection property="emps" select="com.yzh.mapper.EmpDeptMapper.getEmpListByDid" column="did" ></collection>
</resultMap>
<select id="getEmpListByDid" resultType="com.yzh.bean.Emp">
select eid, ename, age ,sex from emp where did=#{did}
</select>
<select id="getOnlyDeptByDid" resultMap="deptMapStep">
select did, dname from dept where did=#{did}
</select>
mybatis 动态sql
- 动态sql是MyBatis强大特性之一。极大简化了我们拼装sql的操作
- 动态sql元素和使用JSTL或其他类似于xml的文本处理器类似
- mybatis采用功能强大的OGNL的表达式来简化操作
如果进行多条件查询的时候,有一个字段为空的话,那么可能查询出的结果是错误的、
如下
- 编写对应接口的xml文件,根据输入的若干项条件进行查询
<select id="getEmpListByMoreCondition" resultType="com.yzh.bean.Emp">
select eid,ename,age,sex,did from emp
where
eid = #{eid}
and ename=#{ename}
and age = #{age}
and sex = #{sex}
</select>
- . 这是在测试类中,假如没有添加某一个查询条件的值,那么得到的结果很可能是空
public void test01() throws Exception{
EmpMapper mapper = getMapper(EmpMapper.class);
Emp emp = new Emp();
emp.setEid(1);
// emp.setEname("tony");
emp.setAge(44);
emp.setSex("男");
List<Emp> empListByMoreCondition = mapper.getEmpListByMoreCondition(emp);
System.out.println(empListByMoreCondition);
}
if 标签
可以改成这样,使用if标签来判断条件是否为空
<select id="getEmpListByMoreCondition" resultType="com.yzh.bean.Emp">
select eid,ename,age,sex,did from emp
where 1=1
<if test="eid != null">
and eid = #{eid}
</if>
<if test="ename != null and ename !='' " >
and ename=#{ename}
</if>
<if test="age != null">
and age = #{age}
</if>
<if test="sex == '1' or sex=='0'">
and sex = #{sex}
</if>
</select>
where 标签
也可以这样写,where标签可以去掉多余的and,这样就不用写 1=1这个条件了
<select id="getEmpListByMoreCondition" resultType="com.yzh.bean.Emp">
select eid,ename,age,sex,did from emp
<where>
<if test="eid != null">
and eid = #{eid}
</if>
<if test="ename != null and ename !='' " >
and ename=#{ename}
</if>
<if test="age != null">
and age = #{age}
</if>
<if test="sex == 1 or sex==0 ">
and sex = #{sex}
</if>
</where>
</select>
trim标签
也可以这样,使用trim标签,他有如下属性:
prefix:在操作的sql语句前加入某些内容
suffix:在操作的sql语句后加入某些内容
prefixOverrides:把操作的sql语句前的某些内容去掉
suffixOverrides:把操作的sql语句后的某些内容去掉
<select id="getEmpListByMoreCondition" resultType="com.yzh.bean.Emp">
select eid,ename,age,sex,did from emp
<trim prefix="where" prefixOverrides="and">
<if test="eid != null">
and eid = #{eid}
</if>
<if test="ename != null and ename !='' " >
and ename=#{ename}
</if>
<if test="age != null">
and age = #{age}
</if>
<if test="sex == 1 or sex==0 ">
and sex = #{sex}
</if>
</trim>
</select>
如果有多个需要去掉的,比如where语句的开头可能会出现or,那么可以改写 prefixOverrides=“and|or”。即可
set标签
主要是为了解决修改操作中sql语句可能多出逗号的问题,一般情况下还是用trim
<update id="updateEmp" >
update emp
<set>
<if test="ename!=null and ename!=''">
ename = #{ename},
</if>
<if test="age !=null">
age = #{age},
</if>
<if test="sex==1 or sex==0">
sex = #{sex}
</if>
</set>
where eid = #{eid}
</update>
choose(when,otherwise)
主要用于分支判断 相当于 if、、、elseif 、、、、elseif、、、、、else
<select id="getEmpListByChoose" resultType="com.yzh.bean.Emp">
select eid,ename,age,sex from emp
where
<choose>
<when test="eid != null">
eid = #{eid}
</when>
<when test="ename != null and ename!=''">
ename = #{ename}
</when>
<when test="age != null">
age = #{age}
</when>
<when test="sex == 1 or sex == 0">
sex = #{sex}
</when>
</choose>
</select>
批量删除
一般方法是,将要删除的员工id,用逗号拼接在一起,用$接收
<delete id="deleteMoreEmp">
delete from emp where eid in(
${value}
)
</delete>
foreach实现
<!--
<foreach collection="" item="" close="" open="" separator="" index="">
</foreach>
collection: 指定要遍历的集合或数组
item:设置别名
close:设置循环体的结束内容
open:设置循环体的开始内容
separator:设置每次循环的分隔符
index: 若遍历的是list,index表示下表;若遍历的是map,index代表键
-->
<delete id="deleteMoreEmpByList">
delete from emp where eid in(
<foreach collection="list" item="eid" separator=",">
#{eid}
</foreach>
)
</delete>
批量查询
select * from emp where eid in ();
select * from emp where eid=?? or eid=?? or eid=??
批量添加
insert into emp values(),(),();
批量修改
修改为相同的值: update emp set …… where eid in();
修改各自的值,需要将mysql的连接地址url 添加参数 allowMultiQueries=true
<foreach collection="emps" iteam=“emp”>
update emp set ename=#{emp.ename}, age=#{emp.age} where eid=#{emp.eid};
</foreach>
sql 标签
为了避免同一个sql字段要写很多次,即公共sql。以后要使用只需要使用include标签调用即可
<sql id="selectHeadForEmp">
select eid,ename,age,sex from emp
</sql>
<select id="getEmpListByChoose" resultType="com.yzh.bean.Emp">
<include refid="selectHeadForEmp"></include>
where
<choose>
<when test="eid != null">
eid = #{eid}
</when>
<when test="ename != null and ename!=''">
ename = #{ename}
</when>
<when test="age != null">
age = #{age}
</when>
<when test="sex == 1 or sex == 0">
sex = #{sex}
</when>
</choose>
</select>
mybatis的缓存
一级缓存
mybatis中的一级缓存默认开启,是SqlSession级别的
即同一个SqlSession下对一个sql语句执行后会存储在缓存中,下次执行相同的sql,直接从缓存中取
public void test06()throws Exception{
EmpMapper mapper = getMapper(EmpMapper.class);
System.out.println("执行sql");
Emp empByEid = mapper.getEmpByEid("10");
System.out.println(empByEid);
System.out.println("执行sql");
Emp empByEid2 = mapper.getEmpByEid("10");
System.out.println(empByEid2);
}
可以看到只进行了一次查询
一级缓存失效的几种情况
- 不同的SqlSession对应不同的一级缓存
- 同一个SqlSession查询的条件不同
- 同一个SqlSession两次查询期间执行了任何一次增删改操作,不管增删改成功与否都会清空缓存。
- 同一个SqlSession两次查询期间手动清空了缓存。通过SqlSession 里面的 clearCache()方法
二级缓存
- 二级缓存默认不开启
- 二级缓存,全局作用域缓存
- MyBatis提供二级缓存的接口以及实现,缓存实现要求POJO实现Serializable接口
- 二级缓存存在SqlSession关闭或提交后才生效
- 二级缓存的使用步骤
- 全局配置文件中开启二级缓存 < setting name=“cacheEnabled” value=“true”>< /setting>
- 需要使用二级缓存的映射文件处使用cache配置缓存
- POJO实现Serializable接口
- 二级缓存的相关属性
- eviction:缓存回收策略
- LRU:最近最少使用的:移除最长时间不被使用的对象(默认)
- FIFO:先进先出,按照对象进入缓存的顺序来移除他们
- SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
- WEAK:弱引用,更积极的移除基于垃圾回收器状态和软引用规则的对象
- flushInterval:刷新间隔,单位时间毫秒,默认情况不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
- size:引用数目,正整数,代表缓存最多可以存储多少个对象,太大容易内存泄露
- readOnly:只读,true/false。默认false
true:只读缓存,会给所有调用者返回缓存相同的实例。因此这些对象不能被修改。提供了性能优势
false:读写缓存,会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全
- eviction:缓存回收策略
public void test07()throws Exception{
SqlSession sqlSession = getSqlSession();
EmpMapper mapper1 = sqlSession.getMapper(EmpMapper.class);
EmpMapper mapper2 = sqlSession.getMapper(EmpMapper.class);
Emp empByEid1 = mapper1.getEmpByEid("10");
System.out.println(empByEid1);
sqlSession.commit();
Emp empByEid2 = mapper2.getEmpByEid("10");
System.out.println(empByEid2);
sqlSession.commit();
}
缓存的相关属性设置
- 全局setting的 cacheEnable:配置二级缓存的开关
- select 标签的useCache属性,配置这个select是否使用二级缓存
- sql 标签的flushCache属性:增删改查默认flushCache=true。sql执行以后,会同时清空一级和二级缓存
- sqlSession.clearCache():只是用来清空一级缓存。
整合第三方缓存
- 为了提高扩展性,Mybatis定义了缓存接口Cache。我们可以通过实现Cache接口来定义二级缓存
- EhCache是一个纯java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider
- 整合EnCache缓存的步骤
-
导入EnCache包,以及整合包,日志包
深色部分是依赖的包 -
编写encache.xml配置文件
-
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path="D:\yzh\ehcache" />
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
<!--
属性说明:
l diskStore:指定数据在磁盘中的存储位置。
l defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
以下属性是必须的:
l maxElementsInMemory - 在内存中缓存的element的最大数目
l maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
l eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
l overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
以下属性是可选的:
l timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
l timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
l diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
l diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
l memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
-->
3. 在mapper.xml 的cache标签中导入
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
逆向工程
巴拉巴拉
分页插件 PageHelper
- 导包
导入pagehelper-5.0.0.jar 和 jsqlparser-0.9.5.jar - 核心配置文件中配置
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
- 使用
只需要在sql语句执行前,添加PageHelper.startPage(第几页, 多少个数据)即可
@Test
public void test08()throws Exception{
SqlSession sqlSession = getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
PageHelper.startPage(2, 3);
List<Emp> allEmp = mapper.getAllEmp();
// PageInfo<Emp> pageInfo = new PageInfo<>(allEmp,5);
System.out.println();
for (Emp emp:allEmp){
System.out.println(emp);
}
}
SSM 框架整合
- 导入jar
- spring
- springMVC
- mybatis
- 第三方支持:log4j,pageHelper,AspectJ,jackson,jstl,ehCache
- 搭建springMVC
- web.xml文件配置:
- DispatcherServlet
- HiddenHttpMethodFilter
- CharacterEncodingFilter
- springMVC.xml
- 扫描控制层组件
- 视图解析器
- Default Servlet
- MVC驱动
- 文件解析器 MultipartResolver(可选)
- 拦截器(可选)
- web.xml文件配置:
- 整合springMVC和spring
- web.xml :
- ContextLoaderListener
- context-param
- spring.xml
- 扫描组件,但是要排除控制层
- 事务管理
- web.xml :
- 搭建mybatis
- 核心配置文件
- mapper接口和mapper.xml
- spring 整合mybatis
- spring.xml:
- properties资源文件的引入,内含数据库连接的信息
- DataSource数据源的配置
- 事务管理器
- 开启事务驱动
- SqlSessionFactoryBean
- spring.xml:
- 创建sqlSession对象,通过getMapper