Mybatis动态代理的好处
传统分层模式,我们在处理业务的时候需要些 dao 层,然后再 写 dao层的实现类
具体处理业务在 dao 层的实现类中进行处理, 而 mybatis 在配置 实体类的 Mapper文件之后, 只需要写 相当于 dao(Maper接口) 层接口 , mybatis 就会自动生成 dao (Mapper接口) 的实现类,就可以 调用 dao(Mapper实现类) 的接口了
先来温习一下非动态代理的Mybatis操作:如果有疑问,请看上一篇mybatis的基本入门
数据库的实体bean类,`
package com.puya.mybatis.pojo;
import java.io.Serializable;
public class User implements Serializable {
private Integer id;
private String name;
private String station;
private String telephone;
private String address;
private String decidedzone_id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStation() {
return station;
}
public void setStation(String station) {
this.station = station;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getDecidedzone_id() {
return decidedzone_id;
}
public void setDecidedzone_id(String decidedzone_id) {
this.decidedzone_id = decidedzone_id;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", station=" + station + ", telephone=" + telephone + ", address="
+ address + ", decidedzone_id=" + decidedzone_id + "]";
}
}
- [ ]对应的 Mapper文件 ,User.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">
<!-- 写sql语句的地方 -->
<mapper namespace="user">
<!--
mapper参数详解:
namespace:命名空间,区分不同的sql,调用的时候使用 user.findUserById
select 参数详解
parameterType : 传入参数的类型,mybatis封装了基本类,只需要写
resultType : 返回的数据类型,一般是全类名
-->
<select id="findUserById" parameterType="Integer" resultType="com.puya.mybatis.pojo.User">
select * from t_customer where id = #{v}
</select>
<!--
#{v} 表示占位符v可以是任何字符 select * from t_customer where id = ?
${value} 表示字符拼接,只能是value select * from t_customer where name like '%张三%' ,有单引号的
为了防止sql注入 ${value} 可以这样写 select * from t_customer where name like "%"#{value}"%"
-->
<select id="findUserByUserName" parameterType="String" resultType="com.puya.mybatis.pojo.User">
<!-- select * from t_customer where username like '%${value}%' -->
select * from t_customer where name like "%"#{value}"%" <!-- 这个可以防止sql注入 -->
</select>
<insert id="insertUser" parameterType="com.puya.mybatis.pojo.User">
<!--private Integer id;
private String name;
private String station;
private String telephone;
private String address;
private String decidedzone_id; -->
<selectKey keyProperty="id" resultType="Integer" order="AFTER">
select LAST_INSERT_ID() <!-- 这个表示执行最新的id 服装到User的id中去-->
</selectKey>
insert into t_customer (name,station,telephone,address,decidedzone_id) value(#{name},#{station},#{telephone},#{address},#{decidedzone_id})
</insert>
<update id="updateUserById" parameterType="com.puya.mybatis.pojo.User">
update t_customer
set name=#{name},station=#{station},telephone=#{telephone},address=#{address},decidedzone_id=#{decidedzone_id}
where id=#{id}
</update>
<delete id="deleteUserById" parameterType="Integer">
delete from t_customer where id =#{value}
</delete>
</mapper>
//这次测试只用到了一条sql ----- findUserById
非动态代理的代码逻辑
@Test
public void testMybatis() throws Exception {
//加载核心的配置文件
String path ="sqlMapConfig.xml";
//读取配置文件获取流
InputStream in = Resources.getResourceAsStream(path);
//创建sqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建session
SqlSession session = sessionFactory.openSession();
//执行sql语句
User user = session.selectOne("user.findUserById", 1);
System.out.println(user);
}
这个就是非动态代理的主要步骤: 注意键User.xml文件配置在sqlMapConfig,xml文件中去,为了查看方便,贴出sqlMapConfig,xml整体文件,下面动态代理也是这个配置文件
<?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>
<!-- 和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/bos_puya32?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<!-- Mapper的位置 Mapper.xml 写Sql语句的文件的位置 -->
<mappers>
<mapper resource="com/puya/mybatis/sqlmap/User.xml"/>
<mapper resource="com/puya/mybatis/sqlmap/UserMapper.xml"/>
</mappers>
</configuration>
调用 testMybatis() 方法后,就查到了响应的 User 对象,这就是 非动态代理的配置以及全部流程,看上去也不复杂
接下来讲一下动态代理,动态代理起始就 mybatis 根据接口生成响应的实体类,然后调用方法;所以手下得写一个接口;
接口书写的四个原则
|- 接口方法名 == 对应的Mapper.xml 中的id 名字 ,这样就能找到这个sql
|- 接口中的返回值类型 与 Mapper.xml文件中的返回值一样
|- 方法的 形参 与Mapper.xml文件中的 形参类型一样
|- 将Mapper.xml 文件 命名空间 和 接口 捆绑(就是maper.xml文件对应的 名称空间 为 接口的全类名)
接下来写一个Mapper接口
/**动态代理接口
. */
public interface UserMapper {
//遵循四个原则
//接口方法名 == User.xml 中的id 名字
//接口中的返回值类型 与 Mapper.xml文件中的返回值一样
//方法的 形参 与Mapper.xml文件中的 形参一样
//将Mapper.xml 文件 命名空间 和 接口 捆绑
public User findUserById(Integer id);
}
- 写一个Mappe.xml文件(UserMapper.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">
<!-- 写sql语句的地方 -->
<mapper namespace="com.puya.mybatis.mapper.UserMapper">
<!--
mapper参数详解:
namespace:命名空间,区分不同的sql,调用的时候使用 user.findUserById
select 参数详解
parameterType : 传入参数的类型,mybatis封装了基本类,只需要写
resultType : 返回的数据类型,一般是全类名
-->
<select id="findUserById" parameterType="Integer" resultType="com.puya.mybatis.pojo.User">
select * from t_customer where id = #{v}
</select>
</mapper>
将mapper.xml文件配置到 sqlMapConfig.xml文件中去
<mapper resource="com/puya/mybatis/sqlmap/UserMapper.xml"/>
在 UserMapper文件配置 全类名 的别名
<mapper namespace="com.puya.mybatis.mapper.UserMapper">
@Test
public void testMapper() throws Exception {
String path ="sqlMapConfig.xml";
//读取配置文件获取流
InputStream in = Resources.getResourceAsStream(path);
//创建sqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建session
SqlSession session = sessionFactory.openSession();
//获取动态代理对象
UserMapper mapper = session.getMapper(UserMapper.class);
//更加动态代理对象执行sql
User user = mapper.findUserById(1);
System.out.println(user);
}