Spring对MyBatis的整合思路
作为Bean容器,Spring框架提供了IoC机制,可以接管所有组件的创建工作并进行依赖管理,因而整合的主要工作就是把MyBatis框架使用中所涉及的核心组件配置到Spring容器中,交给Spring来创建和管理。
业务逻辑对象依赖基于MyBatis技术实现的Dao对象,核心是获取SqlSession实例。把创建实例的工作交给Spring来处理。
整合的步骤:
1.在项目中加入Spring、MyBatis及整合相关的JAR文件
2.建立开发目录,创建实体类
package cn.smbms.pojo;
import java.util.Date;
/**
* @author Bryce
*
*/
public class User {
/*字段*/
private Integer id; //id
private String userCode; //用户编码
private String userName; //用户名称
private String userPassword;//用户密码
private Integer gender; //性别
private Date birthday; //出生日期
private String phone; //电话
private String address; //地址
private Integer userRole; //用户角色
private Integer createBy; //创建者
private Date creationDate; //创建时间
private Integer modifyBy; //更新者
private Date modifyDate; //更新时间
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getUserRole() {
return userRole;
}
public void setUserRole(Integer userRole) {
this.userRole = userRole;
}
public Integer getCreateBy() {
return createBy;
}
public void setCreateBy(Integer createBy) {
this.createBy = createBy;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public Integer getModifyBy() {
return modifyBy;
}
public void setModifyBy(Integer modifyBy) {
this.modifyBy = modifyBy;
}
public Date getModifyDate() {
return modifyDate;
}
public void setModifyDate(Date modifyDate) {
this.modifyDate = modifyDate;
}
}
3.创建数据访问接口
package cn.smbms.dao.user;
import java.util.List;
import cn.smbms.pojo.User;
public interface UserMapper {
/**
* 查询用户列表
*/
public List getUserList(User user);
}
4.配置SQL映射文件(Mapper)
<mapper namespace = "cn.smbms.dao.user.UserMapper">
<select id="count" resultType="int">
select count(1) as count from smbms_user
select>
<select id="getUserList" resultType="cn.smbms.pojo.User">
select * from smbms_user
select>
mapper>
5.配置MyBatis配置文件(mybatis-config.xml)
<configuration>
<typeAliases>
<package name="cn.smbms.pojo"/>
typeAliases>
configuration>
6.创建Spring配置文件applicationContext-mybatis.xml
7.配置数据源
添加dbcp数据源所需的JAR文件
在applicationContext-mybatis.xml文件中添加配置信息
id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"> property>
8.配置SqlSessionFactoryBean(applicationContext-mybatis.xml)
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml" />
<property name="mapperLocations">
<list>
<value>classpath:cn/smbms/dao/**/*.xmlvalue>
list>
property>
bean>
9.使用SqlSessionTemplate实现数据库的操作(dao接口实现类)
package cn.smbms.dao.user;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import cn.smbms.pojo.User;
public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSession;
@Override
public List getUserList(User user) {
return sqlSession.selectList(
"cn.smbms.dao.user.UserMapper.getUserList", user);
}
public SqlSessionTemplate getSqlSession() {
return sqlSession;
}
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
}
Spring配置文件中配置SqlSessionTemplate
<bean id="sqlSessionTemplate"class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
bean>
<bean id="userMapper" class="cn.smbms.dao.user.UserMapperImpl">
<property name="sqlSession" ref="sqlSessionTemplate" />
bean>
10.编写业务逻辑代码并测试
业务接口的关键代码:
package cn.smbms.service.user;
import java.util.List;
import cn.smbms.pojo.User;
public interface UserService {
public List findUsersWithConditions(User user);
}
业务实现类的关键代码:
package cn.smbms.service.user;
import java.util.List;
import cn.smbms.dao.user.UserMapper;
import cn.smbms.pojo.User;
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
@Override
public List findUsersWithConditions(User user) {
try {
return userMapper.getUserList(user);
} catch (RuntimeException e) {
e.printStackTrace();
throw e;
}
}
public UserMapper getUserMapper() {
return userMapper;
}
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
}
Spring配置文件中的关键代码:
<bean id="userService" class="cn.smbms.service.user.UserServiceImpl">
<property name="userMapper" ref="userMapper" />
bean>
使用MapperFactoryBean注入映射器
1.配置实现Dao(applicationContext-mybatis.xml)
<bean id="billMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="cn.smbms.dao.bill.BillMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
bean>
业务组件的定义和配置及测试代码与之前相同。无须手工编码定义Mapper接口的实现类,通过配置MapperFactoryBean即可自动生成,减少了Dao模块的编码工作量。
使用MapperScannerConfigurer注入映射器
为了简化配置工作量,MyBatis-Spring中提供了MapperScannerConfigurer,它可以扫描指定包中的接口并将它们直接注册为MapperFactoryBean。
配置文件内容:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.smbms.dao"/>
bean>
basePackage属性指定了扫描的基准包,MapperScannerConfigurer将递归扫描基准包(包括各层级子包)下所有接口。如果它们在SQL映射文件中定义过,则将它们动态注册为MapperFactoryBean,如此即可批量产生映射器实现类。
使用MapperScannerConfigurer自动完成映射器注册后,使用@Autowired或者@Resource注解实现对业务组件的依赖注入,以简化业务组件的配置。
package cn.smbms.service.user;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.smbms.dao.user.UserMapper;
import cn.smbms.pojo.User;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired//依赖注入
private UserMapper userMapper; //声明BillMapper接口引用
@Override
public List getUserList() {
// TODO Auto-generated method stub
return userMapper.getUserList();
}
@Override
public boolean updateUser(User user) {
// TODO Auto-generated method stub
return userMapper.updateUser(user)>0;
}
@Override
public boolean deleteUser(int id) {
// TODO Auto-generated method stub
return userMapper.deleteUser(id)>0;
}
@Override
public boolean updateUserPassword(int id) {
// TODO Auto-generated method stub
return userMapper.updateUserPassword(id)>0;
}
}
Spring配置文件中的关键代码:
<context:component-scan base-package="cn.smbms.service" />
为业务层添加声明式事务
配置声明式事务的步骤
1.导入tx和aop命名空间
2.定义事务管理器Bean,并为其注入数据源Bean
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
3.通过
配置事务增强,绑定事务管理器并针对不同方法定义事务规则。
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="find*" propagation="SUPPORTS" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="*" propagation="REQUIRED" />
tx:attributes>
tx:advice>
在 标签内可以设置id属性和transaction-manager属性。其中transaction-manager属性引用一个事务管理器Bean。
子标签定制事务属性。事务属性通过
标签进行设置。
标签中的name属性是必需的,用于指定匹配的方法。这里需要对方法名进行约定,可以使用通配符(*)。其他属性可选
propagation:事务传播机制。
REQUIRED:默认值,表示如果存在一个事务,则支持当前事务;如果当前没有事务,则开启一个新的事务
REQUIRES_NEW:表示总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起,开启新事务执行该方法。
MANDATORY: 表示如果存在一个事务,则支持当前事务;如果当前没有一个活动的事务,则抛出异常。
NESTED:表示如果当前存在一个活动的事务,则创建一个事务作为当前事务的嵌套事务运行:如果没有当前事务,该取值与REQUIRED相同。
SUPPORTS:表示如果存在一个事务,则支持当前事务;如果当前没有事务,则按非事务方式执行。
NOT_SUPPORTED:表示总是以非事务方式执行。如果一个事务已经存在,则将这个存在的事务挂起,然后执行该方法。
NEVER:表示总是以非事务方式执行。如果当前存在一个活动事务,则抛出异常。
isolation:事务隔离等级。即当前事务和其他事务的隔离程度。
DEFAULT: 默认值,表示使用数据库默认的事务隔离级别。
READ_UNCOMMITTED:未提交读。
READ_COMMITTED:提交读。
REPEATABLE_READ:可重复读。
SERIALIZABLE:串行读。
timeout:事务超时时间。允许事务运行的最长时间,以秒为单位
read-only:事务是否为只读,默认值false
rollback-for:设定能触发回滚的异常类型。
no-rollback-for:设定不触发回滚的异常类型。
4.配置切面,将事务增强与方法切入点组合。
<aop:config>
<aop:pointcut id="serviceMethod"
expression="execution(* cn.smbms.service..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
aop:config>
使用注解实现声明式事务处理
首先需要在Spring配置文件中配置事务管理类,并添加对注解配置的事务的支持
id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
transaction-manager="transactionManager" />
使用@Transactional注解来配置事务
package cn.smbms.service.bill;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import cn.smbms.dao.bill.BillMapper;
import cn.smbms.pojo.Bill;
@Transactional
@Service("billService")
public class BillServiceImpl implements BillService {
private BillMapper billMapper; //声明BillMapper接口引用
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public List getBillList() {
// TODO Auto-generated method stub
try {
return billMapper.getBillList();
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
}
}
public BillMapper getBillMapper() {
return billMapper;
}
public void setBillMapper(BillMapper billMapper) {
this.billMapper = billMapper;
}
@Override
public List getBillList(Bill bill) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean updateBill(Bill bill) {
// TODO Auto-generated method stub
return billMapper.updateBill(bill)>0;
}
@Override
public boolean deleteBill(int id) {
// TODO Auto-generated method stub
return billMapper.deleteBill(id)>0;
}
}
@Transaction注解也可以设置事务属性的值,默认设置如下
事务传播设置是PROPAGATION_REQUIRED.
事务隔离级别是ISOLATION_DEFAULT.
事务是读/写。
事务超时默认是依赖于事务系统的,或者事务超时没有被支持。
任何RuntimeException将触发事务回滚,但是任何checked Exception将不触发事务回滚。
@Transactional注解的属性
属性 |
类型 |
说明 |
propagation |
枚举型:Propagation |
可选的传播性设置。使用举例: @Transactional( propagation=Propagation.REQUIRES_NEW) |
isolation |
枚举型:Isolation |
可选的隔离性级别。使用举例: @Transactional( isolation=Isolation.READ_COMMITTED) |
readOnly |
布尔型 |
是否为只读型事务。使用举例:@Transactional(readOnly=true) |
timeout |
int型(以秒为单位) |
事务超时。使用举例:Transactional(timeout=10) |
rollbackFor |
一组 Class 类的实例,必须是Throwable的子类 |
一组异常类,遇到时 必须 回滚。使用举例:@Transactional( rollbackFor={SQLException.class}),多个异常用逗号隔开 |
rollbackForClassName |
一组 Class 类的名字,必须是Throwable的子类 |
一组异常类名,遇到时 必须 回滚。使用举例:@Transactional( rollbackForClassName={ "SQLException"}),多个异常用逗号隔开 |
noRollbackFor |
一组 Class 类的实例,必须是Throwable的子类 |
一组异常类,遇到时 必须不 回滚 |
noRollbackForClassName |
一组 Class 类的名字,必须是Throwable的子类 |
一组异常类名,遇到时 必须不 回滚 |