Mybatis学习系列(四)Mapper接口动态代理

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

实现原理及规范

Mapper接口动态代理的方式需要手动编写Mapper接口,Mybatis框架将根据接口定义创建接口的动态代理对象,代理对象的方法体实现Mapper接口中定义的方法。

使用Mapper接口需要遵守以下规范:

1.  Mapper.xml文件中的namespace与mapper接口的类路径相同

2.  Mapper接口方法名和Mapper.xml中定义的每个statement的id相同

3.  Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

4.  Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

编写Mapper.xml映射文件

定义mapper映射文件ProductMapper.xml,需要修改namespace的值为 ProductMapper接口路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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">
<!-- namespace:此处使用包名+文件名 的形式 -->
<mapper namespace="com.sl.mapper.ProductMapper">
    <!-- 返回自定义类型 注意 selectAllProduct返回的是集合,这种情况下resultType是集合包含的类型,而不能是集合本身 -->
    <select id="selectAllProduct" resultType="com.sl.po.Product">
        select * from products
    </select>
  <select id="selectProductsByVo" resultType="com.sl.po.Product">
        select * from products
        <where>
            <if test="product.cityCode!=null">
               and citycode = #{product.cityCode}
               <!-- citycode = #{cityCode} -->
            </if>
            <if test="product.Name!=null">
                and name like #{product.Name}
            </if>
            <if test="product.Description!=null">
                and description like #{product.Description}
            </if>
        </where>
  </select>  
</mapper>

编写Mapper.java接口

接口定义注意点:

1.  Mapper接口方法名和Mapper.xml中定义的statement的id相同

2.  Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同

3.  Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同

1
2
3
4
5
6
7
8
9
10
11
12
package com.sl.mapper;
import java.util.List;
import com.sl.po.Product;
import com.sl.po.ProductVo;
 
public interface ProductMapper {
 
    List<Product> selectAllProduct();
 
    List<Product> selectProductsByVo(ProductVo vo);
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.sl.po;
 
public class ProductVo {
 
    private int category;
 
    private Product product;
 
 
    public int getCategory() {
        return category;
    }
 
    public void setCategory(int category) {
        this.category = category;
    }
 
    public Product getProduct() {
        return product;
    }
 
    public void setProduct(Product product) {
        this.product = product;
    }
 
 
}

注册Mapper.xml配置文件(或者Mapper.java接口)

修改SqlMapConfig.xml文件:

1
2
3
4
5
6
7
8
9
10
<mappers>
        <!-- 注册productMapper.xml文件 -->
        <mapper resource="mapper/productMapper.xml"></mapper> 
        <!-- mapper.xml文件和mapper接口可以不在一个包下  -->
 
        <!-- 注册mapper接口 -->
        <!-- <mapper class="com.sl.mapper.ProductMapper"></mapper>  --> 
        <!--通过注册mapper接口方式: Mapper接口和mapper.xml必须在同一个包下 -->
 
</mappers>

测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//Mapper接口动态代理方式
public class TestProductMapperClient {
 
    // 定义会话SqlSession
    SqlSession session = null;
 
    @Before
    public void init() throws IOException {
        // 定义mabatis全局配置文件
        String resource = "SqlMapConfig.xml";
 
        // 加载mybatis全局配置文件
        // InputStream inputStream =
        // TestClient.class.getClassLoader().getResourceAsStream(resource);
 
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(inputStream);
        // 根据sqlSessionFactory产生会话sqlsession
        session = factory.openSession();
    }
 
    // select by id
    //@Test
    public void testSelectProduct() {
 
        // 获取mapper接口的代理对象
        ProductMapper productMapper = session.getMapper(ProductMapper.class);
 
        List<Product> listProduct = productMapper.selectAllProduct();
 
        for (Product product : listProduct) {
            System.out.println(product);
        }
        // 关闭会话
        session.close();
    }
 
        @Test
        public void testwhereTest() {
            Product product = new Product();
            product.setCityCode("A01");
            product.setName("%国际%");
            //product.setDescription("%xx%");
            //product.setUnitPrice(new BigDecimal(100));
            ProductVo vo = new ProductVo();
            vo.setProduct(product);
            ProductMapper productMapper = session.getMapper(ProductMapper.class);
            List<Product> listProduct = productMapper.selectProductsByVo(vo);
            for (Product pro : listProduct) {
                System.out.println(pro);
            }
 
            // 关闭会话
            session.close();
        }
 
}

动态代理对象内部调用sqlSession.selectOne()和sqlSession.selectList()实现数据库操作,具体调用哪一个是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。

由于参数类型在mapper.xml配置文件中ParameterType配置,所以Mapper.java中接口方法只有一个参数,且类型与mapper.xml中配置的相同(mapper.xml可省略参数类型配置)。

 

原文链接:http://www.cnblogs.com/ashleyboy/p/9277048.html