ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

06-Mapper动态代理

2021-01-30 23:30:34  阅读:145  来源: 互联网

标签:customer Mapper 06 cust 代理 public 参数 id name


Mppaer 动态代理

目录


 

之前我们一直都使用传统开发模式DAO,即定义接口,然后定义实现类。这个其实是较为繁琐的,MyBatis 中提供了 Mapper 动态代理的方法,操作起来十分简洁,只需要定义满足要求的接口,然后通过 sqlSession 获取到 Mapper对象,便可通过 Mapper 对象调用我们定义的方法。

创建 Mapper 工程

定义接口的要求

  • 1、namespace 必须和 Mapper 接口类路径一致。
    不使用 Mapper 的话,namespace 的值可以自定义。
    在这里插入图片描述

  • 2、id 必须和 Mapper 接口方法名一致。
    不使用 Mapper,使用传统DAO开发模式的话,接口方法名可以自定义。
    在这里插入图片描述在这里插入图片描述

  • 3、parameterType 必须和接口方法参数类型一致。
    这个很好理解,传入参数的类型要一样。
    在这里插入图片描述在这里插入图片描述

  • 4、resultType 必须和接口方法返回值类型一致
    这个也很好理解,返回值类型要一样。
    在这里插入图片描述
    在这里插入图片描述

映射文件 Customer.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="myTest">

    <!--根据cust_id查询客户-->
    <select id="queryCustomerById" parameterType="Int" resultType="com.itlike.domain.Customer">
	  SELECT * FROM `customer` WHERE cust_id  = #{cust_id}
	</select>

    <!--查询所有的客户,不需要参数-->
    <select id="queryAllCustomer" resultType="com.itlike.domain.Customer">
	  SELECT * FROM `customer`
	</select>

    <!--根据用户名模糊查询客户-->
    <select id="queryCustomerByName" parameterType="String" resultType="com.itlike.domain.Customer">
        SELECT * FROM customer WHERE cust_name LIKE '%${value}%';
    </select>

    <!--添加客户-->
    <insert id="insertCustomer" parameterType="com.itlike.domain.Customer">

        /*获取插入的最后一个id*/
        <selectKey keyColumn="cust_id" resultType="Integer" order="AFTER">
            SELECT last_insert_id()
        </selectKey>

        INSERT INTO `customer` (cust_id, cust_name, cust_profession, cust_phone, email)
        VALUES (#{cust_id}, #{cust_name}, #{cust_profession}, #{cust_phone}, #{email});
    </insert>

    <!--更新-->
    <update id="updateCustomer" parameterType="com.itlike.domain.Customer">
        UPDATE `customer` SET cust_name = #{cust_name} WHERE cust_id = #{cust_id}
    </update>

    <!--删除-->
    <delete id="deleteCustomer" parameterType="com.itlike.domain.Customer">
        DELETE FROM `customer` WHERE cust_id = #{cust_id}
    </delete>
</mapper>

Mapper 类:

/*
    使用 Mapper 动态代理:
    1.namespace 必须和 Mapper 接口类路径一致
    2.id 必须和 Mapper 接口方法名一致
    3.parameterType 必须和接口方法参数类型一致
    4.resultType 必须和接口方法返回值类型一致
**/
public interface CustomerMapper {
    // 根据 cust_id 查询客户
    public Customer queryCustomerById(Integer id);

    // 查询所有
    public List<Customer> queryAllCustomer();

    // 根据用户名模糊查询客户
    public List<Customer> queryCustomerByName(String name);

    // 添加客户
    public void insertCustomer(Customer customer);

    // 更新
    public void updateCustomer(Customer customer);

    // 删除
    public void deleteCustomer(Customer customer);

}

测试类

在 Test 包中 MyTest2.java 中编写一个测试方法:
只要按规范定义好了接口,根据 sqlSession 可以直接获取到 Mapper 对象,可以直接用 Mapper 对象调用接口中的方法。

public void test2(){
    SqlSession sqlSession = MybatisUtils.openSession();
    CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
    
    List<Customer> customers = mapper.queryAllCustomer();
    for (Customer customer : customers) {
        System.out.println(customer);
    }
    
    sqlSession.close();
}

运行结果:成功查询出数据库中所有的数据。

Opening JDBC Connection
Created connection 422392391.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@192d3247]
==>  Preparing: SELECT * FROM `customer` 
==> Parameters: 
<==    Columns: cust_id, cust_name, cust_profession, cust_phone, email
<==        Row: 1, 鲁班, 射手, 13499887733, 12341241@qq.com
<==        Row: 2, 李白, 刺客, 18977665521, libai@163.com
<==        Row: 3, 阿轲, 刺客, 18977665997, aike@qq.com
<==        Row: 4, 德玛西亚, 肉盾, 13700997665, demaxiya.126.com6
<==        Row: 5, 亚索, 战士, 13586878987, yasuo@qq.com
<==        Row: 6, 奶妈, 辅助, 13398909089, nama@qq.com
<==        Row: 7, 剑圣, 刺客, 13398909088, jiansheng@163.com
<==        Row: 8, 盖伦, 肉盾, 15923242231, gailun@126.com
<==        Row: 9, 锤石, 辅助, 13398908900, 8888@163.com
<==        Row: 11, 孙悟空, 战士, 13728964922, lixin@qq.com
<==        Row: 20, 后裔6, null, 18937485936, null
<==        Row: 21, 后裔6, null, 18937485936, null
<==      Total: 12
Customer{cust_id=1, cust_name='鲁班', cust_profession='射手', cust_phone='13499887733', email='12341241@qq.com'}
Customer{cust_id=2, cust_name='李白', cust_profession='刺客', cust_phone='18977665521', email='libai@163.com'}
Customer{cust_id=3, cust_name='阿轲', cust_profession='刺客', cust_phone='18977665997', email='aike@qq.com'}
Customer{cust_id=4, cust_name='德玛西亚', cust_profession='肉盾', cust_phone='13700997665', email='demaxiya.126.com6'}
Customer{cust_id=5, cust_name='亚索', cust_profession='战士', cust_phone='13586878987', email='yasuo@qq.com'}
Customer{cust_id=6, cust_name='奶妈', cust_profession='辅助', cust_phone='13398909089', email='nama@qq.com'}
Customer{cust_id=7, cust_name='剑圣', cust_profession='刺客', cust_phone='13398909088', email='jiansheng@163.com'}
Customer{cust_id=8, cust_name='盖伦', cust_profession='肉盾', cust_phone='15923242231', email='gailun@126.com'}
Customer{cust_id=9, cust_name='锤石', cust_profession='辅助', cust_phone='13398908900', email='8888@163.com'}
Customer{cust_id=11, cust_name='孙悟空', cust_profession='战士', cust_phone='13728964922', email='lixin@qq.com'}
Customer{cust_id=20, cust_name='后裔6', cust_profession='null', cust_phone='18937485936', email='null'}
Customer{cust_id=21, cust_name='后裔6', cust_profession='null', cust_phone='18937485936', email='null'}
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@192d3247]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@192d3247]
Returned connection 422392391 to pool.

Mapper 中参数传递

单个参数

如果接受的是单个参数,可以接受基本类型,对象类型,集合类型的值。
MyBatis 可直接使用这个参数,不需要经过任何处理。
即,单个参数,参数名字可以自定义。

<?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.itlike.mapper.CustomerMapper">

    <!--根据id查询用户-->
    <select id="getCustomerWithID" parameterType="Integer" resultType="com.itlike.domain.Customer">
        SELECT * FROM `customer` WHERE cust_id = #{id}
    </select>

</mapper>

测试类:

public class MyTest {
    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtils.openSession();
        CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
        // 查询id为2的用户
        Customer customer = mapper.getCustomerWithID(2);
        System.out.println(customer);
        sqlSession.close();

    }
}

运行结果:成功查询到id为2的用户

多个参数

在这里插入图片描述
多个参数时不需要写 parameterType 。
任意多个参数,都会被 MyBatis 重新包装成一个 Map 传入。
Map 的 key 是 param1,param2,arg0,arg1,值就是参数的值。
即,多个参数,参数名字必须是 param1,param2 或者 arg0, arg1。

以下两种写法都对:

<select id="getCustomerWithID" resultType="com.itlike.domain.Customer">
    SELECT * FROM `customer` WHERE cust_id = #{arg0} AND cust_name = #{arg1}
</select>
<select id="getCustomerWithID" resultType="com.itlike.domain.Customer">
    SELECT * FROM `customer` WHERE cust_id = #{param1} AND cust_name = #{param2}
</select>

测试类:

public void test(){
    SqlSession sqlSession = MybatisUtils.openSession();
    CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
    Customer customer = mapper.getCustomerWithID(2, "李白");
    System.out.println(customer);
    sqlSession.close();
}

运行结果:

Opening JDBC Connection
Created connection 1122805102.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@42eca56e]
==>  Preparing: SELECT * FROM `customer` WHERE cust_id = ? AND cust_name = ? 
==> Parameters: 2(Integer), 李白(String)
<==    Columns: cust_id, cust_name, cust_profession, cust_phone, email
<==        Row: 2, 李白, 刺客, 18977665521, libai@163.com
<==      Total: 1
Customer{cust_id=2, cust_name='李白', cust_profession='刺客', cust_phone='18977665521', email='libai@163.com'}
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@42eca56e]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@42eca56e]
Returned connection 1122805102 to pool.

@param命名参数

为参数使用 @Param 起一个名字,
MyBatis 就会将这些参数封装进 Map 中,key 就是我们自己指定的名字。
即,只要在 CustomerMapper 中使用 @Param 就能使用自定义的名字这个自定义名字只能是 @Param() 括号里写的名字)。

CustomerMapper.java 中:

public interface CustomerMapper {
    public Customer getCustomerWithID(@Param("id") Integer id, @Param("name") String name);
}

像上面这样,就可以自定义参数名字:

<select id="getCustomerWithID" resultType="com.itlike.domain.Customer">
    SELECT * FROM `customer` WHERE cust_id = #{id} AND cust_name = #{name}
</select>

测试类:

public void test(){
    SqlSession sqlSession = MybatisUtils.openSession();
    CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
    Customer customer = mapper.getCustomerWithID(2, "李白");
    System.out.println(customer);
    sqlSession.close();
}

运行结果:可以正常查询出结果。

注: 如果使用了 @Param 命名参数,param1,param2 作为参数名称依旧可以使用,但是 arg0, arg1 不可用。

多个参数封装成 Map

我们也可以封装多个参数为 Map,直接传递
在 CustomerMppaer.java 中重载一个参数为 Map 类型的方法:

public interface CustomerMapper {
    public Customer getCustomerWithID(@Param("id") Integer id, @Param("name") String name);
    public Customer getCustomerWithID(Map<String, Object> map);
}

测试类:将数据封装到 Map 中,然后将 Map 传入上面重载的方法。

public void test(){
    SqlSession sqlSession = MybatisUtils.openSession();
    CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);

    HashMap<String, Object> hashMap = new HashMap<>(); 
    // 将参数封装到 Map 中
    hashMap.put("id", 1); 
    hashMap.put("name", "鲁班");
    Customer customer = mapper.getCustomerWithID(hashMap);
    System.out.println(customer);
    sqlSession.close();
}

如果通过 Map 传值,在映射文件中的参数名就必须和 Map 的 key 值相同,如下:

<select id="getCustomerWithID" resultType="com.itlike.domain.Customer">
    SELECT * FROM `customer` WHERE cust_id = #{id} AND cust_name = #{name}
</select>

多个参数之 POJO

我们可以直接传入 POJO 类,但是参数名必须与业务 POJO 中的字段一致。
在 CustomerMppaer.java 中重载一个参数为 POJO 的方法:

public interface CustomerMapper {
    public Customer getCustomerWithID(@Param("id") Integer id, @Param("name") String name);
    public Customer getCustomerWithID(Map<String, Object> map);
    public Customer getCustomerWithID(Customer customer);
}

映射文件 Customer.xml 中参数名必须与POJO中字段一致

<select id="getCustomerWithID" resultType="com.itlike.domain.Customer">
    SELECT * FROM `customer` WHERE cust_id = #{cust_id} AND cust_name = #{cust_name}
</select>

测试类:自己创建的对象,必须给它设定好 sql 语句中所需的参数,这里需要给它设置 cust_id 与 cust_name。

public void test(){
    SqlSession sqlSession = MybatisUtils.openSession();
    CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
    
    Customer customer = new Customer();
    customer.setCust_name("李白");
    customer.setCust_id(2);
    Customer customer1 = mapper.getCustomerWithID(customer);
    System.out.println(customer1);

    sqlSession.close();
}

参数处理源码分析

接收参数后,会把参数给放到一个数组当中,如果是一个参数,内部处理时,会自动把该参数返回。
在这里插入图片描述
如果是多个参数,内部会做判断,判断是否有 @Param 注解。
如果没有注解的话:就直接使用 arg0,arg1…为 key,放到 map 中,并且还会以 param1 和param2… 为 key 放一份到 map 中。
在这里插入图片描述
如果有注解的话: 会使用注解当中的值,替换掉默认的 arg0 和 arg1,使用 @Param 中的值,作为 key 放到一个 map 当中。并且还会以 param1 和 param2… 为 key 放一份到 map 中。
在这里插入图片描述
综上,所以传递多个参数时,无论有没有 @Param ,param1、param2 作为参数名都是可以的当有了 @Param 后,arg0、arg1 便会被替换为 @Param 中的值。

标签:customer,Mapper,06,cust,代理,public,参数,id,name
来源: https://blog.csdn.net/qq_35885612/article/details/113398697

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有