java-Spring+MyBatis整合
Posted Lazy的笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java-Spring+MyBatis整合相关的知识,希望对你有一定的参考价值。
Spring整合MyBatis的思路:
在mybatis中,通过创建一个mybatisUtil类,来连接数据库,创建一个SqlSessionFactory,通过这个工厂来创建SqlSession对象。
在Spring的IoC中,可以将所有的类放在IoC容器中进行管理,所以Spring整合MyBatis就是将这个工厂类放在IoC进行管理。
所需要的jar包
commons-logging-1.1.1.jar
log4j-1.2.17.jar
spring-beans-3.2.13.RELEASE.jar
spring-context-3.2.13.RELEASE.jar
spring-core-3.2.13.RELEASE.jar
spring-expression-3.2.13.RELEASE.jar
aopalliance-1.0.jar
aspectjweaver-1.6.9.jar
spring-aop-3.2.13.RELEASE.jar
mybatis-3.2.2.jar
mybatis-spring-1.2.0.jar
mysql-connector-java-5.1.7-bin.jar
spring-jdbc-3.2.13.RELEASE.jar
spring-tx-3.2.13.RELEASE.jar
commons-dbcp-1.4.jar
commons-pool-1.6.jar
要使用Spring中使用MyBatis,需要在spring的配置文件中定义一些类
sqlSessionFactoryBean
为整合应用提供SqlSession对象资源
SqlSessionTemplate
负责管理MyBatis的SqlSession,调用SQL映射语句,实现对数据库的访问
MapperFactoryBean
根据指定Mapper接口生存Bean实例
MapperScannerConfigurer
根据指定包批量扫描Mapper接口并生存实例
Spring和MyBatis的整合步骤
1、加入Spring和MyBatis的有关jar包
2、建立开发目录结构,创建实体类
3、创建数据访问接口
4、创建数据访问接口的实现类
5、配置SQL映射语句文件
6、配置MyBatis应用配置文件
7、配置Spring应用配置文件
ApplicationContext配置文件
<?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: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.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置数据源,连接数据库 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/smbms?useUnicode=true&charaterEncoding=utf-8"></property>
<property name="username" value="root"></property>
<property name="password" value="@lazy"></property>
</bean>
<!-- sqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 使用数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 引入mybatis-config.xml配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 引入映射文件 ,可以引入多个-->
<property name="mapperLocations">
<list>
<value>classpath:cn/smbms/dao/user/UserMapper.xml</value>
</list>
</property>
</bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 使用构造注入SqlSessionFactory工厂 -->
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
<!-- DAO -->
<bean id="userMapperImpl" class="cn.smbms.dao.user.UserMapperImpl">
<property name="sqlSession" ref="sqlSessionTemplate"></property>
</bean>
</beans>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 使用构造注入SqlSessionFactory工厂 -->
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
<!-- DAO -->
<bean id="userMapperImpl" class="cn.smbms.dao.user.UserMapperImpl">
<!-- 将SqlSessionTemplate对象传入到业务层实现类中 -->
<!-- <property name="sqlSession" ref="sqlSessionTemplate"></property> -->
<!-- 这个是 UserMapperImpl继承了SqlSessionDaoSupport,无需再将SqlSessionTemplate传入进去-->
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
/*这个是构造方法获取SqlSessionTemplate;
private SqlSessionTemplate sqlSession;
public SqlSessionTemplate getSqlSession() {
return sqlSession;
}
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}*/
public int cout(){
int count = 0;
count = this.getSqlSession().selectOne("count");
return count;
}
手动编写映射器实现存在的问题
SqlSession.selectList()等方法需要采用字符串指定映射项
sqlSession.selectOne("cn.smbms.dao.user.UserMapper.count")
SqlSession.getMapper()方法需要在每次调用时都实现一次映射器接口
sqlSession.getMapper(UserMapper.class)
能否在IoC容器中始终存在一个映射器接口的实现呢?
采用数据映射器(MpperFactoryBean)的方式完成对数据库操作
1、更加Mapper接口获取Mapper对象,它封装了原有的SqlSession.getMapper()功能的实现
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="cn.smbms.dao.user.UserMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<property name="mapperInterface" value="cn.smbms.dao.user.UserMapper"/>指定映射器,只能是接口类型
<property name="sqlSessionFactory" ref="sqlSessionFactory" />注入SqlSessionFactory以提供SqlSessionTemplate实例
映射器对应的SQL映射文件与映射器的路径相同,该映射文件可以自动被MapperFactoryBean解析
若映射很多的话,相应配置项会很多,如何简化配置工作量
MapperScannerConfigurer
自动扫描指定包下的Mapper接口,并将它们直接注册为MapperFactoryBean
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.smbms.dao" />
</bean>
<?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: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.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置数据源,连接数据库 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/smbms?useUnicode=true&charaterEncoding=utf-8"></property>
<property name="username" value="root"></property>
<property name="password" value="@lazy"></property>
</bean>
<!-- sqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 使用数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 引入mybatis-config.xml配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 引入映射文件 ,可以引入多个-->
<property name="mapperLocations">
<list>
<value>classpath:cn/smbms/dao/user/UserMapper.xml</value>
</list>
</property>
</bean>
<!--<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
使用构造注入SqlSessionFactory工厂
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean> -->注释掉
<!-- <bean id="userMapperImpl" class="cn.smbms.dao.user.UserMapperImpl">
<!-- 将SqlSessionTemplate对象传入到业务层实现类中 -->
<!-- <property name="sqlSession" ref="sqlSessionTemplate"></property> -->
<!-- 这个是 UserMapperImpl继承了SqlSessionDaoSupport,无需再将SqlSessionTemplate传入进去-->
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean> -->注释掉
<!-- DAO -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 可以调用了dao这个包以及子包下的所有接口文件 -->
<property name="basePackage" value="cn.smbms.dao"></property>
</bean>
</beans>
当采用了org.mybatis.spring.mapper.MapperScannerConfigurer这个时就不需要注入将sqlSessionTemplate注入到UserMapperImpl类中,这类直接UserMapperImpl继承SqlSessionDaoSupport就可获得SqlSession对象
<扫描注解定义>
<!-- DAO -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 可以调用了dao这个包以及子包下的所有接口文件 -->
<property name="basePackage" value="cn.smbms.dao"></property>
</bean>
上面接口使用这个,可以使所有的DAO层接口都能装到IoC容器中,使用少量的代码量。
<!-- Service -->
<context:component-scan base-package="cn.smbms.service"></context:component-scan>
业务层使用注解,可以引入DAO层,这样可以简化代码量
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userMapper")
private UserMapper userMapper;
@Override
public int findUsers() {
return userMapper.count();
}
public UserMapper getUserMapper() {
return userMapper;
}
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
}
<!-- 事务管理,利用AOP编程管理 -->
<!-- 事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事务增强处理类 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- 利用通配符来寻找 -->
<tx:method name="find*" timeout="1000"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!-- * cn.smbms.service..*.*(..)表示在service包下的类或子包的类,参数任意,定义切入点 -->
<aop:pointcut expression="execution(* cn.smbms.service..*.*(..))" id="pointcut"/>
<!-- 增强 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
声明式事务关注的核心问题是:
对那些方法,采取什么样的事务策略
配置步骤
导入tx和aop命名空间
定义事务管理器Bean,并为其注入数据源Bean
通过<tx:advice>配置事务增强,绑定事务管理器并针对不同方法定义事务规则
配置切面,将事务增强与方法切入点组合
propagation:事务传播机制
timeout:事务超时时间,运行事务运行时间,以秒为单位
read-only:事务是否为只读,默认值为false
rollback-for:设定能够触发回滚的异常类型
1、Spring默认只在抛出runtime exception时才标识事务回滚
2、可以通过全限定类名指定需要回滚事务异常,多个类名用逗号分隔
no-rollback-for:设定不触发回滚的异常类型
1、Spring默认checked Exception不会触发事务回滚
2、可以通过全限定类名指定不需要回滚事务异常,多个类名用逗号分隔
no-rollback-for:设定不触发回滚的异常类型
在Spring中配置事务管理类,使用注解实现
在增强的方法上使用注解实现事务管理器
//注释整个方法采取事务控制
@Transactional(propagation=Propagation.REQUIRED)
@Service("userService")
public class UserServiceImpl implements UserService {...;}
使用引用将数据库连接信息引用到Sring配置文件中
数据库连接信息写在属性文件中
采用PropertPlaceholderConfigurer可以引入属性文件,在Spring配置文件中采用诸如${url}方式引用属性值
原始方法是直接在配置文件中配置
<!-- 配置数据源,连接数据库 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/smbms?useUnicode=true&charaterEncoding=utf-8"></property>
<property name="username" value="root"></property>
<property name="password" value="@lazy"></property>
</bean>
使用引用文件
<!-- 使用PropertyPlaceholderConfigurer引入数据库配置文件 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:database.properties</value>
</property>
</bean>
<!-- 配置数据源,连接数据库 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${user}"></property>
<property name="password" value="${password}"></property>
</bean>
通过JNDI从服务器容器中获取DataSource资源
1、在服务器环境配置JNDI数据源
在Tomcat的context.xml文件配置
<Resource name="jndi/smbms" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="10" maxWait="10000" driverClassName="com.mysql.jdbc.Driver" username="root" password="@lazy" url="jdbc:mysql://localhost:3306/smbms?useUnicode=true&charaterEncoding=utf-8" />
2、在Spring配置文件引用JNDI资源
<!-- 使用JNDI连接数据源 -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jndi/smbms</value>
</property>
</bean>
Spring Bean的作用域及其使用方法
singleton 默认值。Spring以单例模式创建Bean的实例,即容器中该Bean的实例只有一个
prototype 每次从容器中获取Bean时,都会创建一个新的实例
request 用于Web应用环境,针对每次HTTP请求都会创建一个实例
session 用于Web应用环境,同一个会话共享同一个实例,不同的会话使用不同的实例
global session 仅在Portlet的Web应用中使用,同一个全局会话共享一个实例。对于非Portlet环境等同于session。
<!-- 指定Bean的作用域为prototype-->scope="prototype"
<bean id="" class=".." scope="prototype">
...
</bean>
使用@Scope注解指定Bean的作用域
@Scope("prototype")
@Service("userService")
public class UserServiceImpl implements UserService{
...}
Spring自动装配
<!--配置业务Bean并注入DAO实例-->
<bean id="userService" class="cn.user.UserServiceImpl">
<property name="userMapper" ref="userMapper" />
</bean>
Spring可以根据属性类型、名称等自动进行注入
设置<bean>元素的autowire属性
<!--配置业务Bean,根据属性名称自动装配-->
<bean id="userService" class="cn.user.UserServiceImpl" aotowire="byName" />
aotowire="byName"
Spring提供的4种自动装配类型
no
byName 根据属性名自动装配。Spring自动查找与属性名相同的id.
byType 根据类型自动装配
constructor 针对构造方法
每个Bean都需要设置aotowire属性,较繁琐
可以为<beans>元素设置default-autowire属性,影响全局
但<bean>节点上aotowire的设置可以覆盖全局设置
<beans default-autowire="byName">
...
</beans>
一般不推荐使用
拆分Spring配置文件
为什么需要拆分配置文件
1、项目规模变大,配置文件可读性、可维护性差
2、团队开发时,多人修改同一配置文件,易发生冲突
拆分策略
1、公用配置+每个系统模块一个单独配置文件(包含DAO、Service、Web控制器)
(适合多人开发,多模块场合)
2、公用配置+DAO Bean配置+业务逻辑Bean配置+Web控制器配置
两种策略各有特色,适用于不同场合
将多个文件合起来
两种方法:
利用ClassPathXmlApplicationContext的重载方法可以配置多个配置文件,用逗号隔开或者使用通配符
public ClassPathXmlApplicationContext(String configLocation);
public ClassPathXmlApplicationContext(String... configLocations);在创建ApplicationContext对象时引入
使用<import resource="xxx.xml" />方式在公共配置文件中引入其他配置文件
以上是关于java-Spring+MyBatis整合的主要内容,如果未能解决你的问题,请参考以下文章
Java-Spring-获取Request,Response对象