目录 :
- 一、配置环境
- 1. 整合环境需导入的JAR :
- Spring框架所需JAR
- Mybatis框架所需JAR
- MyBatis与Spring整合的中间JAR
- 数据库驱动JAR包
- 数据源所需JAR包 (下面的例子中 : 用的不是这个数据源)
- 2. 编写“配置文件” 和 “.properties文件” ( 只是概述,详细配置在例子中有展示 )
- 二、整合开发 :
- 1. 传统 “Dao方式” 的开发整合 ( 通过操作“XxxDao.java 接口”的方式 :来经过“实体类 -- Spring -- mybatis – 映射文件层面 ( 要“手动”将接口加入到IOC容器 )等”来操作数据库 )
- 2. “Mapper接口方式” 的整合开发 :
- 2.1 基于“MapperFactoryBean”的整合( 通过操作“XxxMapper.java 接口”的方式 来经过“Spring -- mybatis – 映射文件层面等”来操作数据库 )
- 2.2 基于 “MapperScannerConfigurer” 的整合( 通过操作“XxxDao.java 接口”方式 : 来经过 Spring -- mybatis – 映射文件层面( 不用“手动”接口加入到IOC容器 )等”来操作数据库 )
- 三、测试事务
作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!
该文章参考学习教材为:
《Java EE企业级应用开发教程 (Spring + Spring MVC +MyBatis)》 黑马程序员 / 编著
文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章文章用于本人学习使用 , 同时希望能帮助大家。
欢迎大家点赞👍 收藏⭐ 关注💖哦!!!(侵权可联系我,进行删除,如果雷同,纯属巧合)
一、配置环境
1. 整合环境需导入的JAR :
要实现MyBatis与Spring的整合,很明显需要这两个框架的JAR包,但是只使用这两个框架中所提供的JAR包是不够的,还需要其他的JAR包来配合使用,整合需要的JAR包如下 :
Spring框架所需JAR
Spring 框架所需的JAR包 : Spring框架需要 10个JAR : 分别是
① Spring的 “四个”基本核心JAR :
spring-core.jar、 spring-beans.jar、 spring-context.jar、 spring-expression.jar。② AOP开发所需“四个”JAR :
aopalliance.jar、aspectjweave.jar、spring-aop.jar、spring-aspects.jar。
③ Spring JDBC所需“一个”JAR :
spring-jdbc.jar
④ Spring 事务所需“一个”JAR :
spring-tx.jar。Spring框架所需JAR ( Mybatis 和 Spring整合 )
Mybatis框架所需JAR
Mybatis 框架所需的 JAR包 : ① Mybatis核心包 ( mybatis.jar ) ② Mybatis的依赖包 (压缩文件夹中lib目录下的所有JAR )
具体如下 :
Mybatis框架所需JAR ( Mybatis 和 Spring整合 )
MyBatis与Spring整合的中间JAR
由于MyBatis3在发布之前,Spring3就已经开发完成,而Spring 团队既不想发布基于MyBatis3的非发布版本的代码,也不想长时间的等待,所以 Spring3以后,就没有对MyBatis3进行支持。为了满足MyBatis用户对Spring框架的需求,MyBatis社区自己开发了一个用于整合这两个框架的中间件 MyBatis-Spring。
Mybatis与Spring整合的中间JAR (百度网盘) )
该JAR下载链接 :
https://repo1.maven.org/maven2/org/mybatis/mybatis-spring/1.3.1/mybatis-spring-1.3.1.jar
数据库驱动JAR包
本整合所使用的数据库驱动包为mysal-connector-java–5…40.bin.jar
数据库驱动JAR包
数据源所需JAR包 (下面的例子中 : 用的不是这个数据源)
整合时所使用的是DBCP数据源,所以需要准备 DBCP和连接池的JAR包 : commons- dbcp2.jar
commons-pool2.jar
DBCP数据源和连接池的JAR
2. 编写“配置文件” 和 “.properties文件” ( 只是概述,详细配置在例子中有展示 )
编写 :applicationContext.xml 、mybatis-config.xml、log4j.properties
applicationContext.xml :
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 读取 db.properties文件 , 此时db.properties文件放在src目录下 --> <context:property-placeholder location="classpath:db.properties"/> <!-- Spring JDBC的知识点 : 配置数据源 : DriverManagerDataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- Spring事务管理的知识点 --> <!-- 基于Annotation (注解) 方式的声明式事务 (常用) : ①配置“平台事务管理器” + ②开始“事务注解” --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 开启“事务注解” (Srping “事务管理”中的知识点),让在类中通过@Trasactional注解的方式来开始"事务管理" --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- 配置Mybatis的内容 : 配置SqlSessionFactory : SqlSession工厂 --> <!-- 在applicationContext.xml通过SqlSessionFactoryBean来获得SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入数据源 --> <property name="dataSource" ref="dataSource"/> <!-- 指定“配置文件”的位置 --> <property name="configLocation" value="classpath:applicationContext.xml"/> </bean> </beans>
在上面的applicationContext.xml文件中,首先定义了读取properties文件的配置,然后配置了数据源,接下来配置了事务管理器,并开启了事务注解,最后配置了MyBatis 工厂来与Spring 整合。其中,MyBatis工厂的作用就是构建SqlSessionFactory, 它是通过mybatis-spring 包中提供org.mybati.spring.SqlSessionFactoryBean类来配置的。通常,在配置时需要提供两个参数:一个是数据源,另一个是MyBatis的配置文件路径。这样Spring的loC容器就会在初始化id为sqlSessionFactoy的Bean时解析MyBatis的配置文件,并与数据源一同保存Spring的Bean中。
mybatis-config.xml :
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 配置别名,不用写全限定类名,写类名对应的小写类名即可 --> <!-- 为持久化类设置“别名” --> <typeAliases> <package name="com.myh.po"/> </typeAliases> <!-- 配置mapper文件的位置 --> <mappers> ..... </mappers> </configuration>
由于在Spring中已经配置了数据源信息,所以在MyBatis的配置文件中就不再需要配置数据源信息。这里只需要使用 <typeAliases>和<mappers>元素来配置文件别名以及指定Mapper文件位置即可。
log4j.properties :
# 因为Mybatis默认使用功能log4j来输出日志信息,所以如果要查看控制处输出sql语句 # 就要在classpath路径下配置log4g的配置文件 : log4j.properties (log4j要配置的"日志文件") : # 即在src目录下配置 log4j.properties配置文件,然后将以下的配置信息复制到配置文件中 # Global logging configuration log4j.rootLogger=ERROR, stdout # MyBatis logging configuration... #将com.myh包下所有类的日志记录设计为DEBUG log4j.logger.com.myh=DEBUG # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
二、整合开发 :
整合开发 分为 :
① 传统DAO方式的整合开发 ② Mapper接口方式的整合开发
1. 传统 “Dao方式” 的开发整合 ( 通过操作“XxxDao.java 接口”的方式 :来经过“实体类 – Spring – mybatis – 映射文件层面 ( 要“手动”将接口加入到IOC容器 )等”来操作数据库 )
通过上面的环境配置完成了对MyBails与Sping整合环境的措建工作,可以说完成了这些配置后,
就已经完成了这两个框架大部分的整合工作。下面将通过传统DAO层开发的方式,来演示这两个框架实际的整合使用。采用 传统DAO开发方式 进行MyBatis与Spring框架的整合时,我们需要编写 DAO接口 以及 接口的实现类,并且需要向DAO实现类中注入 SqlSessionFactory , 然后在 方法体内 通过SalSessionFactory创建 SqlSession 。为此,我们可以使用mybatis-spring包中所提供的 SqlSessionTemplate类 或 SqlSessionDaoSupport类 来实现此功能。
类 描述 SqlSessionTemplate SqlSessionTemplate 是 mybatis-spring的核心类,它负责管理MyBatis的 SqlSession,调用MyBatis的SQL方法。当调用SQL方法时, SqlSessionTemplate 将会保证使用的 SqlSession 和当前Spring的事务是相关的。
它还管理SqlSession的生命周期,包含必要的关闭、提交和回滚操作。SqlSessionDaoSupport 是一个 抽象支持类,它继承了 DaoSupport类,主要是作为 DAO的基类 来使用。可以通过SqlSessionDaoSupport 类的 getSqlSession( )方法来获取所需的 SqlSession。
ps :
开发中“接口”的“实现类”要继承SqlSessionDaoSupport类,通过该类带来的getSqlSession( )方法 获得SqlSession。下面的传统“DAO方式”的开发整合中,将使用 SqlSessionDaoSupport 来获取 SqlSession。
传统“DAO方式”的开发整合 例子如:
创建 tb_customer表 和 其对应的 “持久化类” :
Customer.java :
public class Customer { private Integer id; //主键id private String username; //名称 private String jobs; //职业 private String phone; //电话 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getJobs() { return jobs; } public void setJobs(String jobs) { this.jobs = jobs; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { return "Customer{" + "id=" + id + ", username='" + username + '\'' + ", jobs='" + jobs + '\'' + ", phone='" + phone + '\'' + '}'; } }
创建 applicationContext.xml 、mybatis-config.xml 、CustomerMapper.xml
applicationContext.xml :
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 读取 db.properties文件 , 此时db.properties文件放在src目录下 --> <context:property-placeholder location="classpath:db.properties"/> <!-- Spring JDBC的知识点 : 配置数据源 : DriverManagerDataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- Spring事务管理的知识点 --> <!-- 基于Annotation (注解) 方式的声明式事务 (常用) : ①配置“平台事务管理器” + ②开始“事务注解” --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 开启“事务注解” (Srping “事务管理”中的知识点),让在类中通过@Trasactional注解的方式来开始"事务管理" --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- 配置Mybatis的内容 : 配置SqlSessionFactory : SqlSession工厂 --> <!-- 在applicationContext.xml通过SqlSessionFactoryBean来获得SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入数据源 --> <property name="dataSource" ref="dataSource"/> <!-- 指定“Mybatis配置文件”的位置 --> <!-- 此处是Mybatis有关的配置,引入的当然是Mybatis的配置文件: mybatis-config.xml --> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> <!-- 在此处为将SqlSessionFactory 或 SqlSessionTemplate注入到 SqlSessionDaoSupport(即CustomerDaoImpl)中 帮助其通过getSession()方法来获得SqlSession来进行操作数据库 --> <!-- 注入SqlSessionFactory对象实例 --> <bean id="CustomerDao" class="com.myh.传统DAO方式的开发整合.dao.impl.CustomerDaoImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> </beans>
mybatis-config.xml :
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 配置别名,不用写全限定类名,写类名对应的小写类名即可 --> <!-- 为持久化类设置“别名” --> <typeAliases> <package name="com.myh.po"/> </typeAliases> <!-- 配置mapper文件的位置 --> <mappers> <mapper resource="com/myh/传统DAO方式的开发整合/mapper/CustomerMapper.xml"/> </mappers> </configuration>
CustomerMapper.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"> <!-- namespace的命名空间 --> <!-- 多对多中的“嵌套结果”--> <mapper namespace="CustomerMapper"> <!--根据id查询客户信息--> <!--#{ } : 相当于“占位符”--> <select id="findCustomerById" parameterType="Integer" resultMap="resultMap" > select * from tb_customer where t_id = #{id} </select> <!-- 使用resultMap元素进行映射 : 能解决属性名和字段名不一致导致的数据映射失败问题 --> <resultMap id="resultMap" type="com.myh.传统DAO方式的开发整合.po.Customer"> <id property="id" column="t_id"/> <result property="username" column="t_username"/> <result property="jobs" column="t_jobs"/> <result property="phone" column="t_phone"/> </resultMap> </mapper>
创建 CustomerDao 接口 和 其 实现类 :CustomerDaoImpl :
CustomerDao.java :
public interface CustomerDao { //通过id查询客户 public Customer findCustomerById(Integer id); }
CustomerDaoImpl.java :
//该实现类要继承: SqlSessionDaoSupport,通过该类来获得 SqlSession对象来操作数据库 public class CustomerDaoImpl extends SqlSessionDaoSupport implements CustomerDao { /** * 1.为该SqlSession操作添加一个接口和实现类是有好处的 : 可以让具体的业务来决定id的实际值是多少。 * 2.通过继承SqlSessionDaoSupport类即可获得SqlSession对象,不用自己一步一步地获得SqlSession对象,这就是封装起来的好处,使用起来 * 更方便 */ @Override public Customer findCustomerById(Integer id) { //通过id查询客户 /** * 通过SqlSessionDaoSupport类来获得SqlSession的话是有一个前提条件的 : * 在applicationContext.xml文件中要向SqlSessionDaoSupport类 注入一个“SqlSessionFactory” 或 “SqlSessionTemplate”, * 来帮助SqlSessionDaoSupport类 来创建 “SqlSession” * (因为“CustomerDaoImpl”继承了 “SqlSessionDaoSupport” ,所以注入到“该实现类”中即可。) */ SqlSession sqlSession = this.getSqlSession(); //通过SqlSession来操作数据库 Customer customer = sqlSession.selectOne("CustomerMapper.findCustomerById", id); return customer; } }
在上述代码中,CustomerDaolmpl 类继承了SqlSessionDaoSupport类,并实现了CustomerDao 接口。其中,SqlSessionDaoSupport类 (CustomerDaolmpl 类 )在使用时需要一个SqlSessionFactory 或一个SqlSessionTemplate对象,所以 需要 通过 (在) applicationContext.xml文件 中 给SqlSessionDaoSupport类的子类对象 : CustomerDaolmpl 类 注入一个SqlSessionFactory或SqlSessionTemplate。这样,在子类中就能通过调用 SqlSessionDaoSupport 类的 getSqlSession( )方法来获取SqlSession对象,并使用SqlSession对象中的方法来操作数据库了。
创建 测试类 : DaoTest.java :
DaoTest.java :
//Dao测试类 public class DaoTest { @Test public void findCustomerByDaoTest() { //通过操作Dao接口及其实现类来一步一步地操作到数据库 //通过ApplicationContext.xml来获取ioc容器,进而获得CustomerDao来调用操作数据库的方法 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); //获取IOC中的Bean CustomerDao customerDao = (CustomerDao) applicationContext.getBean("CustomerDao"); Customer customer = customerDao.findCustomerById(1); System.out.println(customer); //这种方式也能从IOC容器中获得Bean,且不用进行"强制类型装换"。 //CustomerDao customerDao = applicationContext.getBean(CustomerDao.class); } }
2. “Mapper接口方式” 的整合开发 :
- 在MyBatis+Spring 的项目中,虽然使用传统的dao 开发方式可以实现所需功能,但是采用这种方式 (传统“Dao方式”)在实现类中会出现大量的重复代码,在方法中也需要指定映射文件中执行语句的id,并且 不能保证编写时id的正确性 (运行时才能知道)。此时,我们可以使用MyBatis 提供的另外一种编程方式 :即使用 “”Mapper接口编程 (“Mapper接口方式” 的整合开发)。
2.1 基于“MapperFactoryBean”的整合( 通过操作“XxxMapper.java 接口”的方式 来经过“Spring – mybatis – 映射文件层面等”来操作数据库 )
基于“MapperFactoryBean”的整合 的方式来操作数据库,比通过 传统 “Dao方式” 的开发整合的方式操作数据库,可以少写一个 ”实现类“可以少写一些重复的代码。
(这种方式解决了“传统的DAO方式的整合”)ps :
容易忘记的操作是 : 要在applicationContext.xml 中 创建MapperFactoryBean类的bean,同时为其设置 mapperInterface属性 ( 指定XxxMapper.java 接口) 和 SqlSessionFactory属性 ) ,同时也只有在applicationContext.xml 中 添加这个bean, 才能 在测试类中获得XxxMapper.java 接口,通过其中的方法来操作数据库。MapperFactoryBean 是MyBatis-Spring团队提供的一个根据Mapper接口生成Mapper对象的类,该类在Spring配置文件 ( applicationContext.xml ) 中使用时可以 配置以下参数:
参数 描述 mapperInterface 用于 指定接口。
如 :用于指定XxxMapper.java 接口文件。
例子在下面的applicationContext.xml文件中可看。sqlSessionFactory 用于 指定SqlSessionFactory。 sqlSessionFactory 用于 指定SqlSessionTemplate。如果和sqlSessionFactory同时设定,则只会启动sqlSessionFactory。 例子如下 :
数据库中表为 :
Customer.java
public class Customer { private Integer id; //主键id private String username; //名称 private String jobs; //职业 private String phone; //电话 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getJobs() { return jobs; } public void setJobs(String jobs) { this.jobs = jobs; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { return "Customer{" + "id=" + id + ", username='" + username + '\'' + ", jobs='" + jobs + '\'' + ", phone='" + phone + '\'' + '}'; } }
CustomerMapper.java (接口) :
/** * 基于MapperFactoryBean的整合 (通过操作XxxMapper.java接口的方式来经过spring--mybatis--最后操作上“映射文件”中的代码来操作数据库) */ public interface CustomerMapper { //通过id查询用户 public Customer findCustomerById(Integer id); }
CustomerMapper.xml (Mapper映射文件) :
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 读取 db.properties文件 , 此时db.properties文件放在src目录下 --> <context:property-placeholder location="classpath:db.properties"/> <!-- Spring JDBC的知识点 : 配置数据源 : DriverManagerDataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- Spring事务管理的知识点 --> <!-- 基于Annotation (注解) 方式的声明式事务 (常用) : ①配置“平台事务管理器” + ②开始“事务注解” --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 开启“事务注解” (Srping “事务管理”中的知识点),让在类中通过@Trasactional注解的方式来开始"事务管理" --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- 配置Mybatis的内容 : 配置SqlSessionFactory : SqlSession工厂 --> <!-- 在applicationContext.xml通过SqlSessionFactoryBean来获得SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入数据源 --> <property name="dataSource" ref="dataSource"/> <!-- 指定“Mybatis配置文件”的位置 --> <!-- 此处是Mybatis有关的配置,引入的当然是Mybatis的配置文件: mybatis-config.xml --> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> <!-- Mapper代理开发 --> <!-- 此处要将MapperFactoryBean添加到IOC容器中,同时要为其添加mapperInterface属性 和 sqlSessionFacory属性--> <bean id="mapperFactoryBean" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.myh.Mapper接口方式的整合开发.基于MapperFactoryBean的整合.mapper.CustomerMapper"/> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> </beans>
applicationContext.xml : ( Spring的配置文件 )
<?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.myh.Mapper接口方式的整合开发.基于MapperFactoryBean的整合.mapper.CustomerMapper"> <!--根据id查询客户信息--> <!-- 基于MapperFactoryBean的整合 (通过操作XxxMapper.java接口的方式来经过spring - mybatis -最后操作上“映射文件”中的代码来操作数据库) --> <select id="findCustomerById" parameterType="Integer" resultMap="resultMap" > select * from tb_customer where t_id = #{id} </select> <!-- 使用resultMap元素进行映射 : 能解决属性名和字段名不一致导致的数据映射失败问题 --> <resultMap id="resultMap" type="com.myh.Mapper接口方式的整合开发.基于MapperFactoryBean的整合.po.Customer"> <id property="id" column="t_id"/> <result property="username" column="t_username"/> <result property="jobs" column="t_jobs"/> <result property="phone" column="t_phone"/> </resultMap> </mapper>
mybatis-config.xml (Mybatis的配置文件) :
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 配置别名,不用写全限定类名,写类名对应的小写类名即可 --> <!-- 为持久化类设置“别名” --> <typeAliases> <package name="com.myh.po"/> </typeAliases> <!-- 配置mapper文件的位置 --> <mappers> <mapper resource="com/myh/Mapper接口方式的整合开发/基于MapperFactoryBean的整合/mapper/CustomerMapper.xml"/> </mappers> </configuration>
DaoTest.java (测试类) :
//Dao测试类 public class DaoTest { /** * 基于MapperFactoryBean的方式操作数据库的方式(基于Mapper接口的方式) */ @Test public void findCustomerByMapperTest() { //通过操作Mapper接口来一步一步地操作到数据库 //通过ApplicationContext.xml来获取ioc容器,进而获得CustomerDao来调用操作数据库的方法 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); //获取IOC中的Bean(XxxMapper.java 这个接口) CustomerMapper customerMapper = applicationContext.getBean(CustomerMapper.class); Customer customer = customerMapper.findCustomerById(1); System.out.println("通过MapperFactoryBean的方式来操作数据库获得的对象信息为: \n" + customer); } }
运行效果 :
注意点 :
Mapper 接口编程方式只需要程序员编写Mapper接口 (相当于DAO接口) (Mapper接口的方式是可以不用写接口的实现类的),然后由MyBatis框架根据接口的定义创建接口的动态代理对象。虽然使用 Mapper 接口编程的方式很简单,但是在具体使用时还是需要遵循以下规范。
(1) Mapper接口的名称和对应的Mapper.xml 映射文件的名称必须一致。
(2) Mapper.xml 文件中的namespace 与 Mapper接口的类路径相同 ( 即 接口文件和映射文件
需要放在同一个包中)。
(3) Mapper 接口中的 方法名和 Mapper.xml 中定义的每个执行语句的 id相同。
(4) Mapper 接口中方法的 输入参数类型 要和Mapper.xml 中定义的每个sql 的 parameterType
的类型相同。
(5) Mapper 接口方法的 输出参数类型 要和Mapper.xml 中定义的每个sql的 resultType 的
类型相同。
只要遵循了这些开发规范,MyBatis就可以自动生成 Mapper接口实现类的代理对象,从而
简化我们的开发。
2.2 基于 “MapperScannerConfigurer” 的整合( 通过操作“XxxDao.java 接口”方式 : 来经过 Spring – mybatis – 映射文件层面( 不用“手动”接口加入到IOC容器 )等”来操作数据库 )
( 基于 “MapperScannerConfigurer” 的整合 是 对“传统DAO方式开发整合” 的一种“优化方案”)
基于 “MapperScannerConfigurer” 的 整合 :对“传统DAO方式开发整合” 的一种“优化方案” :
① 前者的方式优化了后者的要编写“实现类”的问题
② 前者的方式优化了后者的“要在applicationContext.xml中”将手动XxxDao接口加入IOC容器的问题,前者可通过MapperScannerConfigurer的basePackage自动将XxxDao接口加入到IOC容器中。
在实际的项目中,DAO层会包含很多接口,如果每一个接口都像“传统DAO方式开发整合”中那样在 Spring配置文件中配置 (就是将接口文件放入到IOC容器中的这一个过程),那么 不但会增加工作量,还会使得Spring 配置文件非常臃肿 ( 因为要配置很多个bean标签来将接口放入到IOC容器中 )。为此,MyBatis-Spring 团队提供了一种 自动扫描的形式 来配置MyBatis 中的 映射器 — 采用 MapperScannerConfigurer 类。
MapperScannerConfigurer类 在 Spring 配置文件 ( applicationContext.xml )中使用时可以配置以下几个属性 :
属性 描述 basePackage 指定 映射接口文件 (XxxDao.java接口文件 ) 所在的包路径,当需要扫描多个包时可以使用分号或逗号作为分隔符。指定包路径后,会扫描该包及其子包中的所有文件。 annotationClass 指定了要扫描的注解名称,只有被注解标识的类才会被配置为映射器。 sqlSessionFactoryBeanName 指定在Spring 中定义的 SqlSessionFactory 的 Bean 名称。 sqlSessionTemplateBeanName 指定在 Spring 中定义的 SqlSessionTemplate的Bean名称 。如果定义此属性,则sqlSessionFactoryBeanName 将不起作用。 markerInterface 指定创建 映射器 的 接口。 MapperScannerConfigurer的使用非常简单,只需要在Spring 的配置文件中 编写如下代码 :
<!-- Mapper代理开发,基于MapperScannerConfigurer的整合 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.myh.传统DAO方式的开发整合.dao"/> </bean>
在通常情况下,MapperScannerConfigurer 在使用时只需通过 basePackage属性指定需要扫描的包即可,Spring会自动地通过包中的接口来生成映射器。这使得开发人员可以在编写很少代码的情况下,完成对映射器的配置,从而提高开发效率。
例子如 ::
CustomerDao.java :
public interface CustomerDao { //通过id查询客户 public Customer findCustomerById(Integer id); /* 用基于MapperScannerConfigurer的整合,不用为其设置“实现类” 和 不用在applicationContext.xml 中一个一个将XxxDao接口加入到IOC容器中 */ }
CustomerMapper.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"> <!-- namespace的命名空间 --> <mapper namespace="com.myh.Mapper接口方式的整合开发.基于MapperScannerConfigurer的整合.dao.CustomerDao"> <!--根据id查询客户信息--> <select id="findCustomerById" parameterType="Integer" resultMap="resultMap" > select * from tb_customer where t_id = #{id} </select> <!-- 使用resultMap元素进行映射 : 能解决属性名和字段名不一致导致的数据映射失败问题 --> <resultMap id="resultMap" type="com.myh.Mapper接口方式的整合开发.基于MapperScannerConfigurer的整合.po.Customer"> <id property="id" column="t_id"/> <result property="username" column="t_username"/> <result property="jobs" column="t_jobs"/> <result property="phone" column="t_phone"/> </resultMap> </mapper>
applicationContext.xml :
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 读取 db.properties文件 , 此时db.properties文件放在src目录下 --> <context:property-placeholder location="classpath:db.properties"/> <!-- Spring JDBC的知识点 : 配置数据源 : DriverManagerDataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- Spring事务管理的知识点 --> <!-- 基于Annotation (注解) 方式的声明式事务 (常用) : ①配置“平台事务管理器” + ②开始“事务注解” --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 开启“事务注解” (Srping “事务管理”中的知识点),让在类中通过@Trasactional注解的方式来开始"事务管理" --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- 配置Mybatis的内容 : 配置SqlSessionFactory : SqlSession工厂 --> <!-- 在applicationContext.xml通过SqlSessionFactoryBean来获得SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入数据源 --> <property name="dataSource" ref="dataSource"/> <!-- 指定“Mybatis配置文件”的位置 --> <!-- 此处是Mybatis有关的配置,引入的当然是Mybatis的配置文件: mybatis-config.xml --> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> <!-- Mapper代理开发,基于MapperScannerConfigurer的整合,自动扫描将指定包下的“接口“加入到IOC容器中 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.myh.Mapper接口方式的整合开发.基于MapperScannerConfigurer的整合.dao"/> </bean> </beans>
mybatis-config.xml :
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 配置别名,不用写全限定类名,写类名对应的小写类名即可 --> <!-- 为持久化类设置“别名” --> <typeAliases> <package name="com.myh.po"/> </typeAliases> <!-- 配置mapper文件的位置 --> <mappers> <!-- <mapper resource="com/myh/传统DAO方式的开发整合/mapper/CustomerMapper.xml"/>--> <!-- <mapper resource="com/myh/Mapper接口方式的整合开发/基于MapperFactoryBean的整合/mapper/CustomerMapper.xml"/>--> <mapper resource="com/myh/Mapper接口方式的整合开发/基于MapperScannerConfigurer的整合/mapper/CustomerMapper.xml"/> </mappers> </configuration>
DaoTest.java (测试类) :
//Dao测试类 --通过MapperScannerConfigurer的方式来操作数据库 public class DaoTest { @Test public void findCustomerByDaoTest() { //通过操作Dao接口及其实现类来一步一步地操作到数据库 //通过ApplicationContext.xml来获取ioc容器,进而获得CustomerDao来调用操作数据库的方法 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); //获取IOC中的Bean (此处是通过Mapper代理开发,基于MapperScannerConfigurer的整合,自动扫描将指定包下的“接口“加入到IOC容器中) CustomerDao customerDao = applicationContext.getBean(CustomerDao.class); Customer customer = customerDao.findCustomerById(1); System.out.println("通过(MapperScannerConfigurer)的方式来操作数据库获得的对象信息为: \n" + customer); } }
三、测试事务
在MyBatis+Spring的项目中,事务是由Spring 来管理的。上面的代码中已经配置了事务管理器,并开启了事务注解,但是现在还不能够确定事务的配置是否正确,以及事务管理能否生效。
在项目中,业务层(Service层)既是处理业务的地方,又是管理数据库事务的地方。要对事务进行测试,首先需要创建业务层,并在业务层编写添加客户操作的代码;同时有意地添加一段异常代码(如inti= 1/0;)
来模拟现实中的意外情况;最后编写测试方法,调用业务层的添加方法。通过上面的操作来判断业务代码是否生效。例子如下 :
在 基于 “MapperScannerConfigurer” 的整合 的代码上 加入“关于事务”的代码 即可。CustomerDao.java 类 中添加如下代码 :
//添加客户public void addCustomer(Customer customer);
CustomerMapper.xml 类 中添加如下代码 :
<!-- 添加客户信息 --> <insert id="addCustomer" parameterType="com.myh.Mapper接口方式的整合开发.基于MapperScannerConfigurer的整合.po.Customer"> insert into tb_customer(t_username,t_jobs,t_phone) values(#{username},#{jobs},#{phone}) </insert>
创建一个service包,service包下还有一个Impl包,分别存放 CustomerService.java (接口) 和 CustomerServiceImple.java (实现类) :
CustomerService.java :(接口)
public interface CustomerService { public void addCustomer(Customer customer); }
CustomerServiceImpl.java :(实现类)
@Service @Transactional //开始事务 public class CustomerServiceImpl implements CustomerService { @Autowired //自动注入 private CustomerDao customerDao; //添加客户 public void addCustomer(Customer customer) { customerDao.addCustomer(customer); //因为加了“事务管理”,上面操作数据库已经成功了,但这里的报错会触发“事务管理”,让数据回滚 int i = 1 / 0; } }
TransactionTest.java (测试类) :
/** * 测试事务 */ public class TransactionTest { //事务测试类 public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); CustomerService customerService = applicationContext.getBean(CustomerService.class); Customer customer = new Customer(); customer.setUsername("张三"); customer.setJobs("经理"); customer.setPhone("112233"); customerService.addCustomer(customer); } }