1、概述
- Mapper 代理开发方式(基于接口代理方式实现持久层的开发),是当前使用 MyBatis 的主流。基于接口代理方式的开发只需要程序员编写 Mapper 接口,MyBatis 框架会为我们动态生成实现类的对象。
2、传统开发方式
- 在传统的开发中,持久层开发的“套路”是,编写接口,再编写接口的实现类,最后基于多态(接口的引用指向实现类的实例)去调用实现的方法。
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* 当前,数据库中字段名 与 类中属性名 需保持一致
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Xxx {
private Integer id;
private String name;
}
<?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>
<properties resource="jdbc.properties" />
<typeAliases>
<typeAlias type="com.yscyber.mybatis.one.Xxx" alias="Xxx" />
</typeAliases>
<environments default="dev">
<!-- 配置数据源 -->
<environment id="dev">
<transactionManager type="JDBC" />
<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="xxxMapper.xml"/>
</mappers>
</configuration>
<?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">
<select id="listAllXxx" resultType="Xxx">
SELECT id, name
FROM xxx
</select>
</mapper>
import com.yscyber.mybatis.one.Xxx;
import java.util.List;
public interface XxxRepo {
List<Xxx> listAllXxx();
}
import com.yscyber.mybatis.one.Xxx;
import com.yscyber.mybatis.one.repo.XxxRepo;
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 java.io.IOException;
import java.util.List;
// 代码可能存在不合理,请忽略
public class XxxRepoImpl implements XxxRepo {
private static SqlSession sqlSession;
static {
try {
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis.xml"));
sqlSession = sqlSessionFactory.openSession();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public List<Xxx> listAllXxx() {
if (sqlSession != null) {
List<Xxx> xxxList = sqlSession.selectList("xxxMapper.listAllXxx");
return xxxList;
}
return null;
}
}
@Test
public void test6() {
XxxRepo xxxRepo = new XxxRepoImpl();
List<Xxx> xxxList = xxxRepo.listAllXxx();
for (Xxx val : xxxList) {
System.out.println(val);
}
}
传统开发方式的问题,比如实现类中,如果专门设计、抽取一个工具类的话,会存在 MyBatis 模板代码重复的问题;在实现类中,需要使用到映射配置文件中的namespace.id
,这属于“硬编码”,一旦映射配置文件中发生变化,实现类也必须要及时调整。
于是,MyBatis 提供了一种接口代理方案,使得无需编写实现类,只编写持久层接口以及映射配置文件即可。
3、接口代理开发方式
-
只需要编写持久层接口,由 MyBatis 框架根据接口定义创建接口的动态代理对象。
-
使用这种开发方式,需要遵循一定的规则,否则无法实现。

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* 当前,数据库中字段名 与 类中属性名 需保持一致
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Xxx {
private Integer id;
private String name;
}
<?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>
<properties resource="jdbc.properties"/>
<typeAliases>
<typeAlias type="com.yscyber.mybatis.one.Xxx" alias="Xxx"/>
</typeAliases>
<environments default="dev">
<!-- 配置数据源 -->
<environment id="dev">
<transactionManager type="JDBC" />
<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="xxxMapper.xml"/>
</mappers>
</configuration>
<?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.yscyber.mybatis.one.repo.XxxRepo">
<select id="listAllXxx" resultType="Xxx">
SELECT id, name
FROM xxx
</select>
</mapper>
@Test
public void test7() {
try {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
XxxRepo xxxRepo = sqlSession.getMapper(XxxRepo.class);
List<Xxx> xxxList = xxxRepo.listAllXxx();
for (Xxx val : xxxList) {
System.out.println(val);
}
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
- 补充,在核心配置文件中,
<mappers>
标签下的<mapper>
标签,有两个专门配合代理开发的写法,一个是<mapper class="">
,一个是<mapper package="">
。
<mapper class="">
,可以直接配置接口的完全限定名,但要求,映射配置文件与接口同名,且编译后.class
文件与.xml
文件处于同一目录下。
<mapper package="">
,可以直接配置接口所在包的完全限定名,要求同上。


4、接口代理开发的原理


网友评论