實現原理及規范
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接口路徑
<?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的類型相同

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); }

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文件:
<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>
測試方法

//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可省略參數類型配置)。