MyBatis-Spring(四)--MapperFactoryBean实现增删改查

上一篇文章中提到,使用SqlSessionTemplat时需要输入一长串字符串来获取mapper,这种方式IDE不会检查程序的准确性并且很容易出错,所以这篇文章介绍另一种可以避免这种问题,并且也可以使用SqlSessionTemplate的配置方式,那就是MyBatis-Spring团队提供的MapperFactryBean类,通过这个类我们可以配置我们需要的mapper,并通过mapper的类型来获取好,而不需要输入一长串容易出错的字符串。还是使用MyBatis-Spring项目的流程进行介绍:

第一步:创建spring-mybatis.xml文件并配置数据源

 1 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
 2         <property name="driverClassName" value="org.postgresql.Driver" />
 3         <property name="url" value="jdbc:postgresql://localhost:5433/postgres" />
 4         <property name="username" value="postgres" />
 5         <property name="password" value="postgres" />
 6         <!-- 最大数据库连接数 -->
 7         <property name="maxActive" value="100" />
 8         <!-- 最大空闲数,即等待连接数 -->
 9         <property name="maxIdle" value="5" />
10         <!-- 最大等待连接时间 -->
11         <property name="maxWait" value="10000" />
12 </bean>

第二步:配置SqlSessionFactory

1 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
2         <!-- 配置数据源 -->
3         <property name="dataSource" ref="dataSource" />
4         <!-- 配置mybatis -->
5         <property name="configLocation" value="classpath:mybatis-config2.xml" />
6 </bean>

上面的配置中,数据源属性指向第一步中配置的dataSource,mybatis配置文件mybatis-config2.xml的内容如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE configuration
 3   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4   "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <!-- mybatis的基本配置文件:主要配置基本的上下文参数和运行环境 -->
 6 <configuration>
 7     <!--设置 -->
 8     <settings>
 9         <!--缓存配置的全局开关:如果这里设置成false,那么即便在映射器中配置开启也无济于事 -->
10         <setting name="cacheEnabled" value="true" />
11         <!--延时加载的全局开关 -->
12         <setting name="lazyLoadingEnabled" value="false" />
13         <!-- 是否允许单一语句返回多结果集 -->
14         <setting name="multipleResultSetsEnabled" value="false" />
15         <!-- 使用列标签代替列名,需要兼容驱动 -->
16         <setting name="useColumnLabel" value="true" />
17         <!-- 允许JDBC自动生成主键,需要驱动兼容。如果设置为true,则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍能正常工作 -->
18         <setting name="useGeneratedKeys" value="false" />
19         <!-- 指定MyBatis该如何自动映射列到字段或属性:NONE表示取消自动映射;PARTIAL表示只会自动映射,没有定义嵌套结果集和映射结果集;FULL会自动映射任意复杂的结果集,无论是否嵌套 -->
20         <setting name="autoMappingBehavior" value="PARTIAL" />
21         <!-- 配置默认的执行器:SIMPLE是普通的执行器;REUSE会重用预处理语句;BATCH会重用语句并执行批量更新 -->
22         <setting name="defaultExecutorType" value="SIMPLE" />
23         <!--设置超时时间:它决定驱动等待数据库响应的秒数,任何正整数 -->
24         <!-- <setting name="defaultStatementTimeout" value="25"/> -->
25         <!--设置数据库驱动程序默认返回的条数限制,此参数可以重新设置,任何正整数 -->
26         <!-- <setting name="defaultFetchSize" value="100" /> -->
27         <!-- 允许在嵌套语句中使用分页(RowBounds) -->
28         <setting name="safeRowBoundsEnabled" value="false" />
29         <!-- 是否开启自动驼峰命名规则,即从a_example到aExample的映射 -->
30         <setting name="mapUnderscoreToCamelCase" value="true" />
31         <!-- 本地缓存机制,防止循环引用和加速重复嵌套循环 -->
32         <setting name="localCacheScope" value="SESSION" />
33         <!-- 当没有为参数提供特定JDBC类型时,为空值指定JDBC类型。某些驱动需要指定列的JDBC类型,多数情况直接用一般类型即可,如NULL/VARCHAR/OTHER -->
34         <setting name="jdbcTypeForNull" value="OTHER" />
35         <!-- 指定触发延迟加载的方法,如equals/clone/hashCode/toString -->
36         <setting name="lazyLoadTriggerMethods" value="equals" />
37     </settings>
38     <!--类型命名 -->
39     <!--别名:pojo对象的别名 -->
40     <typeAliases>
41         <!-- 对包进行扫描,可以批量进行别名设置,设置规则是:获取类名称,将其第一个字母变为小写 -->
42         <package name="com.hyc.pojo" />
43         <package name="com.hyc.objectfactory" />
44         <package name="com.hyc.bean" />
45         <package name="com.hyc.dao" />
46     </typeAliases>
47     <!--插件 -->
48     <!-- <plugins /> -->
49     <!-- 映射器 -->
50     <mappers>
51         <mapper resource="com/hyc/mapper/ProductMapper.xml" />
52     </mappers>
53 
54 </configuration>

第三步:配置MapperFactoryBean

因为要使用MapperFactoryBean,这里的第三步为配置MapperFactoryBean,跟上一篇中介绍的配置SqlSessionTemplate是同一个步骤,不过上一篇中把它合并到第二步,这里觉得分开会比较清晰些:

1 <!-- 通过MapperFactoryBean配置SqlSessionFactory -->
2     <bean id="productMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
3         <!-- 配置mapper接口 -->
4         <property name="mapperInterface" value="com.hyc.dao.ProductMapper" />
5         <!-- 配置SqlSessionFactory -->
6         <property name="sqlSessionFactory" ref="sqlSessionFactory" />
7         <!-- 如果同时配置sqlSessionTemplate和SqlSessionFactory,将优先使用sqlSessionTemplate -->
8         <property name="sqlSessionTemplate" ref="sqlSessionTemplate" />
9 </bean>

这个配置中有三个属性可以配置:

  • mapperInterface:它的值是*mapper.xml对应的接口,即映射器中的接口全限定名;
  • sqlSessionFactory:就是第二步配置的SqlSessionFactory,包含的是数据源和sql文件;
  • sqlSessionTemplate:上一篇文章中介绍过的配置,不再赘述;

注意⚠️:如果同时配置sqlSessionFactory和sqlSessionTemplate,那么前者会被作废,启用后者,所以为了测试,可以将sqlSessionTemplate注释掉。

第四步:创建mapper

其实就是创建映射器,分两步:

1⃣️创建接口

 1 public interface ProductMapper {
 2 
 3     int insertProduct(Product product);
 4 
 5     int deleteByPrimaryKey(String id);
 6 
 7     int updateByPrimaryKey(Product product);
 8 
 9     List<Product> selectProducts(String name);
10 
11 }

2⃣️创建对应的mapper.xml(sql脚本文件)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 3 <mapper namespace="com.hyc.dao.ProductMapper">
 4     <resultMap id="BaseResultMap" type="com.hyc.pojo.Product">
 5         <id column="id" jdbcType="VARCHAR" property="id" />
 6         <result column="product_name" jdbcType="VARCHAR" property="productName" />
 7         <result column="product_price" jdbcType="VARCHAR" property="productPrice" />
 8         <result column="product_type" jdbcType="VARCHAR" property="productType" />
 9     </resultMap>
10     <sql id="Base_Column_List">
11         id, product_name, product_price, product_type
12     </sql>
13 
14     <!-- 查询所有产品 -->
15     <select id="selectProducts" resultMap="BaseResultMap" parameterType="String">
16         select * from product where product_name like concat('%',#{name},'%')
17     </select>
18 
19     <!-- 插入产品 -->
20     <insert id="insertProduct" parameterType="com.hyc.pojo.Product">
21         insert into product
22         (id,
23         product_name, product_price,
24         product_type)
25         values
26         (#{id,jdbcType=VARCHAR}, #{productName,jdbcType=VARCHAR},
27         #{productPrice,jdbcType=VARCHAR},
28         #{productType,jdbcType=VARCHAR})
29     </insert>
30 
31     <!-- 根据ID删除产品 -->
32     <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
33         delete from
34         product
35         where id = #{id,jdbcType=VARCHAR}
36     </delete>
37 
38     <!--修改产品 -->
39     <update id="updateByPrimaryKey" parameterType="com.hyc.pojo.Product">
40         update product
41         set
42         product_name = #{productName,jdbcType=VARCHAR},
43         product_price =
44         #{productPrice,jdbcType=VARCHAR},
45         product_type =
46         #{productType,jdbcType=VARCHAR}
47         where id = #{id,jdbcType=VARCHAR}
48     </update>
49 </mapper>

它的命名空间就是对应接口的全限定名。

至此,所有的配置已经完成,下面来创建单元测试类。

第五步:单元测试

1⃣️创建一个基类,初始化spring配置

 1 public class BaseTest {
 2 
 3     public SqlSessionTemplate template = null;
 4     ClassPathXmlApplicationContext context = null;
 5     
 6 
 7     @Before
 8     public void before() {
 9         context = new ClassPathXmlApplicationContext("classpath:spring-mybatis.xml");
10         template = context.getBean(SqlSessionTemplate.class);
11     }
12 
13 }

跟上一篇文章中创建的完全一样

2⃣️编写测试方法

 1 public class TestMapperFactoryBean extends BaseTest {
 2 
 3     @Test
 4     public void testInsert() {
 5         ProductMapper pm = super.context.getBean(ProductMapper.class);
 6         Product product = super.context.getBean(Product.class);
 7         int add = pm.insertProduct(product);
 8         System.out.println(add > 0 ? "插入成功" : "插入失败");
 9     }
10 
11     @Test
12     public void testDelete() {
13         ProductMapper pm = super.context.getBean(ProductMapper.class);
14         int del = pm.deleteByPrimaryKey("9b08ea56-6d92-48fc-844f-190eb6272479");
15         System.out.println(del > 0 ? "删除成功" : "删除失败");
16     }
17 
18     @Test
19     public void testUpdate() {
20         ProductMapper pm = super.context.getBean(ProductMapper.class);
21         Product product = super.context.getBean(Product.class);
22         product.setProductName("测试修改");
23         product.setProductPrice("修改后价格");
24         product.setProductType("修改后分类");
25         int update = pm.updateByPrimaryKey(product);
26         System.out.println(update > 0 ? "修改成功" : "修改失败");
27     }
28 
29     @Test
30     public void testSelect() {
31         ProductMapper pm = super.context.getBean(ProductMapper.class);
32         List<Product> pl = pm.selectProducts("T");
33         System.out.println(pl.size());
34     }
35 }

一个一个执行,可进行测试,我的测试结果是都成功的,结果就不贴出来了。

这种方式有一个弊端,就是配置MapperFactoryBean时,mapper要一个一个进行配置,一个项目中的mapper肯定不止一个,所以这种配置难免会增加工作量,显然不利于开发,为此MyBatis提供了另一个类MapperScannerConfigurer,它可以通过扫描的形式去生成对应的mapper,而不需要我们一个一个配置。下一篇将介绍这种扫描配置方式的使用。

原文地址:https://www.cnblogs.com/hellowhy/p/9729181.html