六步学会mybatis--------第二章, mybatis动态代理开发及动态映射原理 (接口与mapper文件的逻辑连接关系)

第一章已经使用mybatis的核心对象sqlsession做了一个crud

我们仔细看一下执行sql语句的方法代码

 int i = session.insert("com.wh.mapper.UserMapper.addUser", user);
 List<User> list =session.selectList("com.wh.mapper.UserMapper.selAllUser");
  int i = session.update("com.wh.mapper.UserMapper.upUser",user);

在参数里写sql位置时好像很麻烦,例如com.wh.mapper.UserMapper.addUser,一不小心就会写错,找不到sql语句导致报错。而且代码耦合性很强,mapper文件名发生改变,就要去修改java代码

可不可以有一种约定? 让这个sql位置的命名不让人任意起名,而是按照约定指定好,mybatis就可以自动找到这个sql语句。

那么如果有了这种约定,掉crud方法还需要程序员来写吗?
已经通过约定将sql语句的位置告诉mybatis了,mybatis不就可以自动找到sql,执行sql,做crud了吗

于是mybatis便有了mybatis动态代理
mybatis对mapper的命名有以下约束
(1) Namespace 的值是接口的完全限定名
(2) 标签中的id描述的是接口中的方法,id必须是接口中的方法
(3) parameterType一定接口中方法的参数类型要一致。

通过这三点,mybaits就可以自动生成接口的实现类对象了

正文开始
动态代理开发步骤
准备好实体类

public class Person {
    private Integer id;
    private String name;
    private String gender;
    private Integer age;
    private Date birthday;
    // ...省略
    }

1. 创建接口

public interface PersonMapper {
    void addPerson(Person person);
    Person selPersonById(int id);
    List<Person> selAllPerson();
    void delPersonById(int id);
    void upPersonById(Person person);
}

2.创建映射文件

<mapper namespace="com.wh.mapper.PersonMapper">
    <insert id="addPerson" parameterType="Person">
        insert into person (name,gender,age,birthday) values (#{name},#{gender},#{age},#{birthday})
    </insert>

    <select id="selPersonById" parameterType="int" resultType="Person">
        select id,name,gender,age,birthday from person where id = #{id}
    </select>

    <select id="selAllPerson" resultType="Person">
        select id,name,gender,age,birthday from person
    </select>

    <delete id="delPersonById" parameterType="int">
        delete from person where id = #{id}
    </delete>

    <update id="upPersonById" parameterType="Person">
        update person set name = #{name}, gender = #{gender}, age = #{age}, birthday = #{birthday} where id = #{id}
    </update>
    </mapper>

3. 获取mybatis的代理对象
session.getMapper(PersonMapper.class);
**getMapper()**就是获取实现接口的代理类对象,该对象封装的操作就是
第一章中sqlsession的crud案例代码,只不过sql语句的位置已经按照约定命名,mybatis可以自动找到,参数不用程序员在写了。

4.测试

public class PersonMapperTest {

    @Test
    public void testadd(){
        SqlSession session = SessionUtils.getSqlSession();
        // debug查看源码创建代理对象原理
        PersonMapper personMapper = session.getMapper(PersonMapper.class);
        Person person = new Person();
        person.setName("华仔");
        person.setGender("男");
        person.setAge(18);
        person.setBirthday(new Date());
        // debug查看执行操作原理
        personMapper.addPerson(person);
        session.commit();
        session.close();
    }

    @Test
    public void testdel(){
        SqlSession session = SessionUtils.getSqlSession();
        PersonMapper personMapper = session.getMapper(PersonMapper.class);
        personMapper.delPersonById(7);
        session.commit();
        session.close();
    }

    @Test
    public void testup(){
        SqlSession session = SessionUtils.getSqlSession();
        PersonMapper personMapper = session.getMapper(PersonMapper.class);
        Person person = new Person();
        person.setId(8);
        person.setName("华仔");
        person.setGender("男");
        person.setAge(18);
        person.setBirthday(new Date());
        personMapper.upPersonById(person);
        session.commit();
        session.close();
    }

    @Test
    public void testsel(){
        SqlSession session = SessionUtils.getSqlSession();
        PersonMapper personMapper = session.getMapper(PersonMapper.class);
        Person person = personMapper.selPersonById(2);
        System.out.println(person);
        session.commit();
        session.close();
    }

    @Test
    public void testselAll(){
        SqlSession session = SessionUtils.getSqlSession();
        PersonMapper personMapper = session.getMapper(PersonMapper.class);
        List<Person> personList = personMapper.selAllPerson();
        for (Person person : personList) {
            System.out.println(person);
        }
        session.commit();
        session.close();
    }

回忆一下第一章中的
sqlSession.insert()
sqlSession.delete()
sqlSession.update()
sqlSession.select()
这些crud方法,都是有程序员代码手动调用的

其实动态代理的原理就是
按照约定,只要接口名和方法名确定,就能找到sql。
mybatis在要实现的接口方法里自动调用执行了sqlSession.XXX();

两个底层原理
只提一下,想要搞懂原理可以在网上找一下。。。
1.代理对象是如何生成的?用的什么代理技术?
代理技术我了解的有jdk动态代理和cglib,这种实现接口的应该是jdk动态代理吧,可以找一下专门分析原理的文章。
想查看代理对象生成机制可以在session.getMapper()方法打上断点,bebug一下查看代理对象生成的过程

2.如何调用方法执行的sql
personMapper.addPerson(person);
可以在这中执行sql的方法上打个断点,debug一下查看执行过程
根据我的观察,是用的反射技术调用的方法

这两个底层原理,想了解可以找一下专门分析的文章

附上一篇我看到的比较好的分析原理的文章
https://www.cnblogs.com/hopeofthevillage/p/11384848.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值