整合Spring和MyBatis
主要是对Spring配置文件的修改
1,使用SqlSessionTemplate操纵数据库
SqlSessionTemplate类实际上实现了sqlSessionTemplate接口。
1> 在spring配置核心文件(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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- 1,首先配置数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 2,配置SQLSessionFactoryBean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 引用数据源组件-->
<property name="dataSource" ref="dataSource"/>
<!-- 配置Sql映射文件信息-->
<property name="mapperLocations" >
<list>
<value>classpath:com/demo/dao/**/*.xml</value>
</list>
</property>
</bean>
<!-- 3,注入SqlSessionTemplate-->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
<!-- 4,定义dao和service层的bean,并注入属性-->
<bean id="userDAOMapper" class="com.demo.dao.impl.UserDAOMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<bean id="userService" class="com.demo.service.impl.UserServiceImpl">
<property name="userDAOMapper" ref="userDAOMapper"/>
</bean>
</beans>
2> 在dao包里写相应的接口(userDAOMapper)和sql映射文件(userDAOMapper.xml),以及其子包中的实现类(userDAOMapperImpl)。
/**
* 用户数据访问接口
*/
public interface UserDAOMapper {
List<User> getAll();
List<User> getByName(@Param("name")String name);
}
/**
* 用户数据访问实现类
*/
public class UserDAOMapperImpl extends SqlSessionDaoSupport implements UserDAOMapper {
private SqlSessionTemplate sqlSession;
@Override
public List<User> getAll() {
UserDAOMapper userDAOMapper= this.getSqlSession().getMapper(UserDAOMapper.class);
return userDAOMapper.getAll();
}
@Override
public List<User> getByName(String name) {
UserDAOMapper userDAOMapper= this.getSqlSession().getMapper(UserDAOMapper.class);
return userDAOMapper.getByName(name);
}
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
}
<!-- sql映射文件(userDAOMapper.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">
<mapper namespace="com.demo.dao.UserDAOMapper">
<select id="getAll" resultType="com.demo.pojo.User">
select * from smbms_user
</select>
<select id="getByName" resultType="com.demo.pojo.User">
select * from smbms_user
<where>
<if test="name !=null and name !=''">
userName like CONCAT('%',#{name},'%')
</if>
</where>
</select>
</mapper>
3> 在service包,写好业务逻辑层的接口和实现类
/**
* 用户业务逻辑接口
*/
public interface UserService {
List<User> getAll();
List<User> getByName(String name);
}
/**
* 用户业务逻辑实现类
*/
public class UserServiceImpl implements UserService {
//声明属性
private UserDAOMapper userDAOMapper;
@Override
public List<User> getAll() {
return userDAOMapper.getAll();
}
@Override
public List<User> getByName(String name) {
return userDAOMapper.getByName(name);
}
//封装属性
public UserDAOMapper getUserDAOMapper() {
return userDAOMapper;
}
public void setUserDAOMapper(UserDAOMapper userDAOMapper) {
this.userDAOMapper = userDAOMapper;
}
}
4> 测试类
//测试类
class UserServiceImplTest {
@org.junit.jupiter.api.Test
void getAll() {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=context.getBean(UserService.class);
List<User> list=userService.getAll();
for (User user : list) {
System.out.println(user.getUserName()+"\t"+user.getPhone());
}
}
@org.junit.jupiter.api.Test
void getById(){
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=context.getBean(UserService.class);
List<User> list=userService.getByName("孙");
for (User user : list) {
System.out.println(user.getUserName()+"\t"+user.getPhone());
}
}
}
2,使用MapeprFactoryBean注入映射器
更改其上的核心配置文件,并且删除其dao层的impl子包
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- 数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- SQLSessionFactoryBean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 引用数据源组件-->
<property name="dataSource" ref="dataSource"/>
<!-- 引用myBatis配置文件中的配置-->
<!-- <property name="configLocation" value="classpath:mybatis-config.xml"/>-->
</bean>
<!--配置DAO,要指定属性mapperInterface和sqlSessionFactory-->
<bean id="userDAOMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!-- 指定映射器-->
<property name="mapperInterface" value="com.demo.dao.UserDAOMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!--配置DAO,要指定属性mapperInterface和sqlSessionFactory-->
<bean id="userDAOMapper2" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!-- 指定映射器-->
<property name="mapperInterface" value="com.demo.dao.UserDAOMapper2"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!-- 定义service层的bean,并注入属性-->
<bean id="userService" class="com.demo.service.impl.UserServiceImpl">
<property name="userDAOMapper" ref="userDAOMapper"/>
</bean>
</beans>
注意:
1)配置DAO组件,class属性不是某个是实现类,而是MapperFactoryBean.
2)通过mapperInterface属性指定映射器,且其值只能式接口类型,不能是某个是实现类。
3)MapperFactoryBean是SqlSessionDaoSupport的子类。使用是需要通过setSqlSessionFactory()方法注入sqlSessionFactory实例以创建sqlSessionTemplate实例。
4)如果映射器对应的sql映射文件与注射器的类路径相同,该映射文件可以自动被MapperFactoryBean解析。
如果路径不同,则仍需在配置SqlSessionFactoryBean时明确指定映射文件的位置。
5)SQl映射文件中的命名空间和映射器接口的名称需相同,映射元素的id和映射器接口的方法名称应相同。
3,使用MapperScannerConfigurer注入映射器
更改其上的核心配置文件,并且删除其dao层的impl子包
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd" default-autowire="byName">
<!-- 引入properties文件-->
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location" value="classpath:db.properties"/>
</bean>
<!-- 数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${uname}"/>
<property name="password" value="${password}"/>
</bean>
<!-- SQLSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置dao-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.demo.dao"/>
</bean>
<!-- 扫描service层的spring注解-->
<context:component-scan base-package="com.demo.service"/>
basePackage属性:指定需要扫描的基准包。
MapperScannerConfigurer将递归扫描基准包下的所有接口。如果他们在sql映射文件中定义过,则将他们动态注册为映射器实现类。MapperScannerConfigurer会为所有由她创建的映射器实现类开启自动装配。也就是这些实现类都会自动注入sqlSessionFactory实例。
4,声明式事务
1,配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- 导入命名空间,tx命名空间,aop命名空间-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd" default-autowire="byName">
<!-- 引入properties文件-->
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location" value="classpath:db.properties"/>
</bean>
<!-- 数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${uname}"/>
<property name="password" value="${password}"/>
</bean>
<!-- 注入SQLSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置dao-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.demo.dao"/>
</bean>
<!-- 扫描service层的spring注解-->
<context:component-scan base-package="com.demo.service"/>
<!--定义事务之前一定要配置好数据源-->
<!-- 1,定义事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 2,设置事务属性-->
<!-- transaction-manager属性需引用一个事务管理器bean,其默认值为transactionManager-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- <tx:attributes>标签配置事务的传播机制,隔离级别-->
<tx:attributes>
<!--<tx:method>中的name属性必须设置,用于指定相匹配的方法 -->
<tx:method name="get*" propagation="SUPPORTS"/>
<tx:method name="list*" propagation="SUPPORTS"/>
<tx:method name="ad*" propagation="REQUIRED"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 3,定义事务切面-->
<aop:config>
<aop:pointcut id="service1" expression="execution(* com.demo.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="service1"/>
</aop:config>
</beans>
<tx:method>标签中的propagation属性说明
属性值 | 说明 |
---|---|
required | 默认值。表示如果存在一个事务,则支持当前事务;否则开启新事务。 |
requires_new | 总是开启新事务。若已经存在一个事务,则先将其挂起,再开启新事务执行该方法。 |
mandatory | 表示如果存在一个事务,则支持当前事务;若当前没有一个活动的事务,则抛异常。 |
nested | 表示若当前存在一个活动的事务,则创建一个事务作为当前事务的嵌套事务运行;若没有当前事务,该取值与required相同。 |
supports | 表示如果存在一个事务,则支持当前事务;否则按非事务方式执行。 |
not_supported | 表示总是以非事务方式执行。如果一个事务已经存在,则先将这个存在的事务挂起,然后执行该方法。 |
never | 表示总是以非事务的方式执行。如果当前存在一个活动的事务,则抛异常。 |
<tx:method>标签中的isolation属性说明
事务隔离级别,即当前事务和其他食物的隔离程度,在并发事务处理的情况下需要考虑他的设置。
属性值 | 说明 |
---|---|
default | 默认值,表示使用数据库默认的事务隔离级别。 |
read_uncommitted | 读未提交 |
read_committed | 已读提交 |
repeatable_read | 可重复读 |
serializable | 串行读 |
tx:method>标签中的其他属性
属性 | 说明 |
---|---|
timeout | 事务超时时间。允许事务运行的最长时间,以秒(S)为单位,超过给定的时间自动回滚,防止事务执行时间过长而影响系统性能。该属性需要底层的实现支持。默认值为-1:不超时。 |
read-only | 事务是否为只读,默认为false。对于只执行查询功能的事务,把它设置为true能提高事务处理的性能。 |
rollback-for | 设定能够出发回滚的异常类型。Spring框架默认只在抛出RuntimeException时才标识事务回滚,可以通过全限定类名自行指定需要回滚事务的异常,多个类名用英文逗号隔开。 |
no-rollback-for | 设置不触发回滚的异常类型。Spring框架默认CheckedException不会出发事务回滚。可以通过全限定类名自行指定不需回滚事务的异常,多个类名用逗号隔开。 |
2,注解
1,配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- 导入命名空间,tx命名空间,aop命名空间-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd" default-autowire="byName">
<!-- 引入properties文件-->
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location" value="classpath:db.properties"/>
</bean>
<!-- 数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${uname}"/>
<property name="password" value="${password}"/>
</bean>
<!-- 注入SQLSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置dao-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.demo.dao"/>
</bean>
<!-- 扫描service层的spring注解-->
<context:component-scan base-package="com.demo.service"/>
<!--定义事务之前一定要配置好数据源-->
<!-- 1,定义事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:annotation-driven />
</beans>
2,使用@Transactional注解添加在业务实现类上。
@Transactional注解说明
其默认设置为:
1,事务传播特性:required ; 事务隔离级别:default ; 事务是读/写 ; 事务超时规则默认是依赖于事务系统的 ;所有的RuntimeException都会出发事务回滚。但是所有CheckedException都不会出发事务回滚。
@Transactional注解的属性
事务属性 | 类型 | 说明 |
---|---|---|
propagation | 枚举型:Propagation | 可选的传播性设置。 |
isolation | 枚举型 : Isolation | 可选的隔离性级别。 |
timeout | int型(s为单位) | 事务超时。 |
readOnly | boolean | 是否为只读型事务。 |
rollbackFor | 一组Class类的实例:必须是Throwable的子类 | 一组异常类,遇到时必须进行回滚。 |
rollbackForClassName | 一组Class类的名称:必须是Throwable的子类 | 一组异常类名,遇到时必须进行回滚。 |
noRollbackFor | 一组Class类的实例:必须是Throwable的子类 | 一组异常类,遇到时必须不回滚。 |
noRollbackForClassName | 一组Class类的名称:必须是Throwable的子类 | 一组异常类名,遇到时必须不回滚。 |