MyBatis动态代理
1、传统Dao开发
1.1 创建Dao实现类
创建MybatisUtils工具类
public class MybatisUtils {
private static SqlSessionFactory factory = null;
static {
String config = "mybatis.xml";
try {
InputStream is = Resources.getResourceAsStream(config);
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
SqlSession session = null;
if (factory != null) {
session = factory.openSession();
}
return session;
}
}
public class ServantDaoImpl implements ServantDao {
@Override
public List<Servant> selectServant() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
String sqlid = "com.b0kuwa.dao.selectServant";
List<Servant> servantList = sqlSession.selectList(sqlid);
sqlSession.close();
return servantList;
}
}
mapper文件
<select id="selectServant" resultType="com.b0kuwa.entity.Servant">
select * from servant
</select>
测试
@Test
public void selectServant() {
ServantDao servantDao = new ServantDaoImpl();
List<Servant> servants = servantDao.selectServant();
servants.forEach(servant -> System.out.println(servant));
}
结果
1.2 传统 Dao 开发方式的分析
- 在前面例子中自定义 Dao 接口实现类时发现一个问题:Dao 的实现类其实并没有干什么实质性的工作,它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper 中相应 id 的 SQL 语句,真正对 DB 进行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。
- 所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对
DB 进行操作。这种对 Dao 的实现方式称为 Mapper 的动态代理方式。 - Mapper 动态代理方式无需程序员实现 Dao 接口。接口是由 MyBatis 结合映射文件自动生成的动态代理实现的。
2、MyBatis 框架 Dao 代理
2.1 Dao 代理实现 CURD
1)getMapper 获取代理对象
只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对象。该方法的参数为指定 Dao接口类的 class 值。
ServantDao.java
public interface ServantDao {
List<Servant> selectServant();
int insertServant(Servant servant);
}
ServantDao.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="com.b0kuwa.dao.ServantDao">
<select id="selectServant" resultType="com.b0kuwa.entity.Servant">
select * from servant
</select>
<insert id="insertServant">
insert into servant values (#{sno},#{sname},#{sgen},#{sage})
</insert>
</mapper>
测试
@Test
public void selectServant() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
ServantDao dao = sqlSession.getMapper(ServantDao.class);
List<Servant> servants = dao.selectServant();
servants.forEach(servant -> System.out.println(servant));
}
@Test
public void insertServant() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
ServantDao dao = sqlSession.getMapper(ServantDao.class);
Servant servant = new Servant();
servant.setSno("1001");
servant.setSname("张三");
servant.setSgen("男");
servant.setSage(30);
int update = dao.insertServant(servant);
sqlSession.commit();
sqlSession.close();
System.out.println(update);
}
2.2 原理
动态代理
MapperProxy 类定义:
public class MapperProxy<T> implements InvocationHandler, Serializable {
invoke()方法:
重点方法: