mybatis和spring整合,也就是通过spring管理SqlSessionFactory、mapper接口。
一.导入架包
除了spring的包和mybatis的包,还需要导入两者的整合包,目前这个包由mybatis提供
mybatis-spring-1.2.0.jar
二.一些必要的配置文件
1.log4j配置
需要先导入log4j的架包,然后建立log4j.properties
# Global logging configuration
#在开发环境中要设置为DEBUG,不然不会打印出信息
log4j.rootLogger=DEBUG, stdout
# 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
2.数据库连接参数配置
由于使用druid连接池,所以配置参数也在里面一起配置
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/shopdemo?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
jdbc.username=root
jdbc.password=123456
filters:stat
maxActive:20
initialSize:1
maxWait:60000
minIdle:10
timeBetweenEvictionRunsMillis:60000
minEvictableIdleTimeMillis:300000
validationQuery:SELECT ‘x‘
testWhileIdle:true
testOnBorrow:false
testOnReturn:false
maxOpenPreparedStatements:20
removeAbandoned:true
removeAbandonedTimeout:1800
logAbandoned:true
3.applicationContext配置
在这个里面我们主要把mybatis的数据库源和SqlSessionFactory来交给spring管理.这里的连接池使用阿里的druid连接池.
<?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"
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">
<!-- 加载数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置数据库连接池Druid-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<!-- 数据库基本信息配置 -->
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driver}" />
<property name="filters" value="${filters}" />
<!-- 最大并发连接数 -->
<property name="maxActive" value="${maxActive}" />
<!-- 初始化连接数量 -->
<property name="initialSize" value="${initialSize}" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${maxWait}" />
<!-- 最小空闲连接数 -->
<property name="minIdle" value="${minIdle}" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
<property name="validationQuery" value="${validationQuery}" />
<property name="testWhileIdle" value="${testWhileIdle}" />
<property name="testOnBorrow" value="${testOnBorrow}" />
<property name="testOnReturn" value="${testOnReturn}" />
<property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="${removeAbandoned}" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="${logAbandoned}" />
</bean>
<!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 加载mybatis的全局配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
</bean>
</beans>
到此基本配置就完成了
三.整合后开发DAO方法
首先, 通过翻阅源码,我们来整理一下mybatis进行持久化操作时重要的几个类:
- SqlSessionFactoryBuilder:build方法创建SqlSessionFactory实例。
- SqlSessionFactory:创建SqlSession实例的工厂。
- SqlSession:用于执行持久化操作的对象,类似于jdbc中的Connection。
- SqlSessionTemplate:MyBatis提供的持久层访问模板化的工具,线程安全,可通过构造参数或依赖注入SqlSessionFactory实例。
1.原始dao方法
原始方法就是写好mapper.xml映射,然后写dao接口,再写dao实现类,最后测试.
1.mapper映射
UserMapper.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">
<!--命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用。-->
<mapper namespace="UserMapper">
<!--根据id查询出用户信息(查询一条数据)-->
<select id="findUserById" parameterType="int" resultType="com.aust.model.User">
SELECT * FROM user WHERE id=#{id}
</select>
</mapper>
其次在sqlMapConfig.xml中配置映射
<mappers>
<mapper resource="mybatis/mapper/UserMapper.xml"/>
</mappers>
2.dao接口
UserDao.java
public interface UserDao {
public User findUserById(int id);
}
3.dao实现类
这里需要注意的就是在实现类中我们需要使用sqlSession这个变量,因此需要spring提前注入进去,整合包中帮我们提供了SqlSessionDaoSupport这个类,集成他之后,再在spring配置文件中配置下就可以实现注入了,省去了自己写注入代码的烦恼.
UserDaoImp.java
public class UserDaoImp extends SqlSessionDaoSupport implements UserDao {
@Override
public User findUserById(int id) {
SqlSession session = this.getSqlSession();
User user = session.selectOne("UserMapper.findUserById",id);
return user;
}
}
需要在spring中配置注入
<!--显示注入sqlsessionFactory-->
<bean class="com.aust.dao.UserDaoImp" id="userDao">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
4.junit测试
ApplicationContext context = null;
@Before
public void init(){
//得到spring容器
context = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
}
@Test
public void findUserByIdTest(){
//从spring容器中获取bean
UserDaoImp daoImp = (UserDaoImp) context.getBean("userDao");
//执行查询
User user = daoImp.findUserById(18);
System.out.println(user.toString());
}
2.mapper代理方法
代理方法和之前一样,不需要写实现类,现在是有spring自动创建实现类.
1.mapper.xml文件
需要注意的就是namespace需要写上mapper接口的类路径名
<?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">
<!--命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用。-->
<mapper namespace="com.aust.dao.UserMapper">
<!--根据id查询出用户信息(查询一条数据)-->
<select id="findUserById" parameterType="int" resultType="com.aust.model.User">
SELECT * FROM user WHERE id=#{id}
</select>
</mapper>
2.UserMapper.java
mapper接口,用于spring来创建管理
public interface UserMapper {
public User findUserById(int id);
}
3.spring配置管理mapper
<!--配置mapper方式-->
<!--MapperFactoryBean用于根据mapper接口创建动态代理对象的工厂-->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!--mapperInterface要创建代理的接口对象-->
<property name="mapperInterface" value="com.aust.dao.UserMapper"/>
<!--sqlSessionFactory配置-->
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
4.junit测试类
ApplicationContext context = null;
@Before
public void init(){
//得到spring容器
context = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
}
@Test
public void findUserByIdTest(){
UserMapper userMapper = (UserMapper) context.getBean("userMapper");
User user = userMapper.findUserById(18);
System.out.println(user.toString());
}
5.带来的问题
此方法问题需要针对每一个mapper来配置,这样的话,如果很多mapper则配置相当繁琐.因此就可以用扫描器来配置mapper,不过需要遵循一些约定.
<!--mapper批量扫描,扫描出来的mapper会自动创建代理对象,并在spring容器中注册
遵循约定:需要将mapper.java和mapper.xml放在同一个包中,且名称一致
自动扫描注册的bean名称为mapper接口类名(首字母小写)
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--配置要扫描的包,如果有多个包需要用逗号隔开-->
<property name="basePackage" value="com.aust.dao"/>
<!--使用beanname来配置,防止提前加载而加载不到相应的bean-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
3.基于sqlSessionTemplate开发
1.UserDao
public class UserDao {
//使用SqlSessionTemplate
private SqlSessionTemplate sessionFactory;
//这里实现set方法,用于spring的注入
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sessionFactory = sqlSessionTemplate;
}
public User findUserById(int id){
User user = sessionFactory.selectOne("userMapper.findUserById",id);
return user;
}
}
2.spring配置
<!--sqlSession模板,本身线程安全-->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory" />
</bean>
<bean class="com.aust.dao.userDao" id="userDao">
<property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
</bean>
3.junit测试
ApplicationContext context = null;
@Before
public void init(){
//得到spring容器
context = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
}
@Test
public void findUserByIdTest(){
UserDao userDao = (userDao) context.getBean("userDao");
User user = userDao.findUserById(18);
System.out.println(user.toString());
}
这种方式和第一种方式差不多,不同的就是sqlSession获得的方式.