Mybatis 学习笔记(十)——Mybatis 整合 Spring

版权声明:转载请注明来源 https://blog.csdn.net/qq_24598601/article/details/84066196

一、环境搭建

  对 Mybatis 整合 Spring 首先需要准备好 Mybatis 和 Spring 的包,在各自的官网都有下载,Mybatis 下载Spring 下载
  因为 Mybatis 可以通过 dao 的形式开发和 Mapper 的形式开发,所以搭建下图所示的项目及结构,对两种开发方式进行介绍和测试。
项目结构

  在 src 下,包 com.po 包含的是 POJO 类;包 com.dao 中包含的是 dao 方式开发相关代码;包 com.mapper 中包含的是 mapper 方式开发相关代码;
  在 test 下,包 com.dao 中包含的是对 dao 方式开发的代码进行测试的测试类;包 com.mapper 中包含的是对 mapper 方式开发的代码进行测试的测试类;
  在 config 下,mapper 中的 UserMapper.xml 是 dao 方式开发的 statement;mybatis 下的SqlMapConfig.xml 是 Mybatis 相关的配置文件;spring 下的applicationContext.xml 是 Spring 相关的配置文件;db.properties 文件是数据库配置文件;
  lib 是包含 Mybatis 和 Spring jar包的集合;
  log4j.properties 是日志配置文件(不做介绍);

二、整合内容

1. 需要 Spring 通过单例方式管理 SqlSessionFactory;
2. 持久层的 mapper 都需要由 Spring 进行管理;
3. Spring 和 Mybatis 整合生成代理对象(applicationContext),使用SqlSessionFactory 创建 SqlSession。(Spring 和 Mybatis 整合自动完成);

三、进行整合

1. applicationContext.xml

  在 Mybatis 与 Spring 整合之前,数据源由 Mybatis 自己管理,但是整合后需要 Spring 进行管理,所以在 applicationContext.xml 中需要对数据源进行配置,看下详细配置:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-3.2.xsd 
		http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:db.properties" />

<!-- 数据源,使用dbcp -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
	destroy-method="close">
	<property name="driverClassName" value="${jdbc.driver}" />
	<property name="url" value="${jdbc.url}" />
	<property name="username" value="${jdbc.username}" />
	<property name="password" value="${jdbc.password}" />
	<property name="maxActive" value="100" />
	<property name="maxIdle" value="10" />
</bean>


<!-- sqlSessinFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<!-- 加载 Mybatis 的配置文件 -->
	<property name="configLocation" value="mybatis/SqlMapConfig.xml" />
	<!-- 加载数据源 -->
	<property name="dataSource" ref="dataSource" />
</bean>

<!-- dao接口 开发 -->
<bean id="userDao" class="com.dao.UserDaoImpl">
	<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

<!-- mapper 开发 -->
<!-- 单个mapper配置  MapperFactoryBean:根据mapper接口生成代理对象 -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
	<!-- mapperInterface指定mapper接口 -->
	<property name="mapperInterface" value="com.mapper.UserMapper"/>
	<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>


<!-- mapper批量扫描
从mapper包中扫描出mapper接口,自动创建代理对象并且在spring容器中注册 
遵循规范:将mapper.java和mapper.xml映射文件名称保持一致,且在一个目录中
自动扫描出来的mapper的bean的id为首字母小写的mapper类名
-->
<!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	指定扫描的包名 ,如果扫描多个包,每个包中间使用半角逗号分隔
	<property name="basePackage" value="com.mapper"/>
	<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean> -->
	
</beans>
	

  和 Mybatis 一样,数据库信息是通过 properties 文件进行加载,目的是为了更好的维护和管理。

2. SqlMapConfig.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>
	
	<!-- 全局配置参数 -->
	<!-- <settings>
		全局性设置懒加载
		<setting name="lazyLoadingEnabled" value="true"/>
		
			当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。
			否则,每个属性都按需加载。
		
		<setting name="aggressiveLazyLoading" value="false"/>
	</settings> -->
	
	<!-- 定义别名 -->
	<typeAliases>
		<!-- 针对单个别名定义 -->
		<!-- <typeAlias type="com.po.User" alias="user"/> -->
		<!-- 针对批量别名定义,别名就是类名(首字母大小写都可以) -->
		<package name="com.po"/>
	</typeAliases>
	
	<!-- 类型处理器 ,通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义-->
<!-- 	<typeHandlers>
		<typeHandler handler="" javaType="" jdbcType=""/>
	</typeHandlers> -->

	<!-- 加载映射文件 -->
	<mappers>
		<!-- 通过resource加载 -->
		<mapper resource="mapper/UserMapper.xml" />
		
		<!-- 通过mapper接口加载,但需要将接口名和映射文件名保存一致,且在同一目录 -->
		<!-- <mapper class=""/> -->
		<!-- 批量加载 -->
		<!-- <package name="com.mapper"/> -->
	</mappers>
</configuration>
3. db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456

四、Dao 开发

  到这一步,整合的配置文件已经基本上完成了,现在开始 Dao 开发的代码编写

1. 编写 Mapper.xml 文件

  下面我将以查询用户信息为例。在我们这个项目中,我们需要编写 UserMapper.xml 文件,因为我们的目的是整合,所以写一个 statement 足矣,接下来我们一起来看看代码:

<?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:命名空间,作用是对sql进行分类化管理, 
	注意:在mapper代理方法开发, namespace有特殊作用 -->
<mapper namespace="test">
	
	<select id="findUserById" parameterType="int" 
		resultType="com.po.User">
		SELECT * FROM USER WHERE ID = #{id}
	</select>
	
</mapper>

2. 编写 Dao.java 接口及其实现类

  紧接着,我们需要编写 Mapper.xml 的 Dao 接口及其实现类,在我们项目中 Mapper.xml 的 Dao 接口是 UserDao.java,其实现是 UserDaoImpl.java,代码如下:

package com.dao;

import com.po.User;

/**
 * 描述:原生dao接口,管理用户
 * @author 欧阳
 * @since 2018年10月9日
 */
public interface UserDao {
	
	//根据id查询用户信息
	public User findUserById(int id) throws Exception;
	
}

  在 Dao 的实现类中,需要继承 SqlSessionDaoSupport 类,原因一是 Spring 的配置文件 applicationContext.xml 中对 sqlSessionFactory 进行注入,进而继承了 SqlSessionDaoSupport 后就可以获得 sqlSession;原因二是因为该类中有获得 SqlSession 的方法。

package com.dao;

import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import com.po.User;

/**
 * 描述:原生dao开发实现类
 * @author 欧阳
 * @since 2018年10月9日
 */
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
	
	@Override
	public User findUserById(int id) throws Exception {
		SqlSession sqlSession = this.getSqlSession();
		User user = sqlSession.selectOne("test.findUserById", id);
		return user;
	}
	
}

3. sqlSessionFactory 注入

  在 applicationContext.xml 对刚才写的 Dao 进行 sqlSessionFactory 注入,这块的代码在上面的 applicationContext.xml 中已经有了,但是需要在这重点说明一下,不然有些人可能会忘记这块。

<!-- 原始dao接口 开发 -->
<bean id="userDao" class="com.dao.UserDaoImpl">
	<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
4. Mapper.xml 加载

  同上,在 SqlMapConfig.xml 中已经配置。

<!-- 通过resource加载,还可通过包扫描,批量加载 <package name=""/> -->
<mapper resource="mapper/UserMapper.xml" />
5. Dao 开发测试

  这块直接上代码,及运行结果

package com.dao;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.po.User;

public class UserDaoImplTest {
	
	private ApplicationContext applicationContext;
	//此方法是在执行testFindUserById之前执行
	@Before
	public void setUp() throws Exception {
		//获得 applicationContext 对象
		this.applicationContext = 
				new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
	}
	
	@Test
	public void testFindUserById() {
		UserDao userDao = (UserDao) applicationContext.getBean("userDao");
		
		try {
			//调用userDao的方法
			User user = userDao.findUserById(2);
			System.out.println(user);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
}

  控制台输出结果如下:

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
User [id=2, username=李四, sex=null, birthday=null, address=null]

五、Mapper 开发

1. 编写Mapper.xml

  在前面三步的基础上,编写 Mapper.xml 文件,在我们的项目中 Mapper.xml 是 /SpringAndMybatis/src/com/mapper/UserMapper.xml,一定要注意,namespace 为你 Mapper 接口的路径(com.mapper.UserMapper)。

<?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:命名空间,作用是对sql进行分类化管理, 
	注意:在mapper代理方法开发, namespace有特殊作用 -->
<mapper namespace="com.mapper.UserMapper">
	
	<select id="findUserById" parameterType="int" 
		resultType="com.po.User">
		SELECT * FROM USER WHERE ID = #{id}
	</select>
	
</mapper>

2. 编写 Mapper 接口

  这个接口编写规范需要遵循 Mybatis 的 Mapper 开发规范。并且建议将 Mapper.xml 和 Mapper 接口放在同一目录下,这样可以避免一些问题。

package com.mapper;

import com.po.User;

/**
 * 描述:mapper代理接口,管理用户
 * @author 欧阳
 * @since 2018年10月9日
 */
public interface UserMapper {
	/*
	 * 程序员编写mapper接口需要遵循一些开发规范,
	 * 		mybatis可以自动生成mapper接口实现类代理对象。
	 * 开发规范:
	 * 1、在mapper.xml中namespace等于mapper接口地址
	 * 2、mapper.java接口中的方法名和mapper.xml中statement的id一致
	 * 3、mapper.java接口中的方法输入参数类型和mapper.xml
	 * 		中statement的parameterType指定的类型一致。
	 * 4、mapper.java接口中的方法返回值类型和mapper.xml
	 * 		中statement的resultType指定的类型一致。
	 */
	//根据id查询用户信息
	public User findUserById(int id) throws Exception;
	
}

3. sqlSessionFactory 注入

  这部分代码在上面的 applicationContext.xml 中已经配置编写了,代码如下:

<!-- mapper 开发 -->
<!-- 单个mapper配置  MapperFactoryBean:根据mapper接口生成代理对象 -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
	<!-- mapperInterface指定mapper接口 -->
	<property name="mapperInterface" value="com.mapper.UserMapper"/>
	<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

  需要注意这是单个 Mapper 接口进行注入,那么对于我们程序员来说,一个项目中不止一个,两个的,而是很多很多,这样单个配置实在是太麻烦。因此,在 Spring 中也想到了这个问题,可以对指定包进行扫描自动注入,代码如下:

<!-- mapper批量扫描
从mapper包中扫描出mapper接口,自动创建代理对象并且在spring容器中注册 
遵循规范:将mapper.java和mapper.xml映射文件名称保持一致,且在一个目录中
自动扫描出来的mapper的bean的id为首字母小写的mapper类名
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<!-- 指定扫描的包名 ,如果扫描多个包,每个包中间使用半角逗号分隔 -->
	<property name="basePackage" value="com.mapper"/>
	<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

  在指定包扫描时,需要注意如果扫描多个包,每个包中间使用半角逗号分隔;然后是对 sqlSessionFactoryBeanName 注入 sqlSessionFactory。这种方式建议使用。
  提醒一下,在指定某个包扫描时,如果都将 Mapper.xml 和其对应的 Mapper 接口放在同一个目录下,将节省很多工作量。

  注意:在指定某个包扫描时,MapperScannerConfigurer 类不兼容 JDK 1.8,需要1.8以下版本的 JDK 。

4. Mapper.xml 加载

  如果在第一步和第二步编写的 Mapper.xml 和其对应的 Mapper 接口放在同一个目录下,这里就不需要配置了。
  不然就得加载对应的 Mapper.xml。加载方式和 Dao 开发一样,也支持对包批量加载。代码如下:

<!-- 加载映射文件 -->
<mappers>
	<mapper resource="Mapper.xml 的路径" />
</mappers>
5. Mapper 开发测试

  这块直接上代码,及运行结果

package com.mapper;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.po.User;

public class UserMapperTest {

	private ApplicationContext  applicationContext;
	//此方法是在执行testFindUserById之前执行
	@Before
	public void setUp() throws Exception {
		this.applicationContext = 
				new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
	}
	
	@Test
	public void testFindUserById() {
		UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
		try {
			User user = userMapper.findUserById(3);
			System.out.println(user);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
}

  控制台输出结果:

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
User [id=3, username=欧阳, sex=null, birthday=null, address=山东]

猜你喜欢

转载自blog.csdn.net/qq_24598601/article/details/84066196