基本整合方式
Spring框架整合其他框架的本质其实就是把其他框架交给Spring框架管理。Spring框架通过IOC,AOP等机制实现与其他框架的连接,最终建立一个低耦合的一应用架构,大大增强了系统的灵活性,便于功能扩展。
Spring整合MyBatis:
MyBatis功能/操作: 配置文件[实体类别名,数据源,映射文件等等],映射文件[业务标签],MyBatis代码[SqlSessionFactory,SqlSession等对象操作]
Spring功能/操作: IoC,DI,AOP,事务管理。
整合目标:
1.Spring替代MyBatis中的数据源,提供SqlSessionFactory,SqlSession等对象,管理事务
2.MyBatis整合中要做的内容: 配置文件[实体类别名,映射文件等等],映射文件[业务标签],MyBatis代码[业务代码]。
整合步骤:
第1步: 整合jar包
MyBatis相关jar: mybatis-3.5.1.jar,log4j-1.2.17.jar
数据库驱动器: mysql-connector-java-5.1.22-bin.jar
Spring相关jar:
commons-logging-1.2.jar
spring-aop-5.1.2.RELEASE.jar
spring-beans-5.1.2.RELEASE.jar
spring-context-5.1.2.RELEASE.jar
spring-core-5.1.2.RELEASE.jar
spring-expression-5.1.2.RELEASE.jar
spring-jdbc-5.1.2.RELEASE.jar
spring-tx-5.1.2.RELEASE.jar
aopalliance-.jar
aspectjrt.jar
aspectjweaver.jar
cglib-nodep-2.1_3.jar
额外jar:
连接池: commons-dbcp-1.4.jar,commons-pool-1.6.jar
MyBatis与Spring整合: mybatis-spring-2.0.3.jar
第2步: 整合配置文件
MyBatis配置文件: mybatis-conf.xml[实体类别名,环境(数据源),加载映射],log4j.xml[控制日志输出],映射文件[业务标签]
Spring配置文件: application.xml[控制反转]
整合后:
MyBatis配置文件中: 去掉环境配置(数据源),实体类别名,加载映射
log4j.xml[控制日志输出]: 无需操作
映射文件[业务标签]: 无需操作
Spring配置文件中: 添加数据源,提供SqlSessionFactory,提供事务管理。
Spring配置文件:
1.开启自动扫描: 扫描service,action,mapper等等,实现控制反转[管理相关对象]---->注解方式实现控制反转
2.提供数据源
3.提供SqlSessionFactoryBean
4.提供事务管理
5.注册其他必须的对象
第3步: 整合代码
MyBatis代码正常编写即可,若需要SqlSessionFactory对象可以从Spring容器中获得.
示例:查询用户为例:
添加所需要的jar:
整合配置文件:
MyBatis配置文件
<?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>
<typeAliases>
<package name="cn.pojo"/>
</typeAliases>
<!--数据源交给Spring添加-->
<mappers>
<mapper resource="cn/pojo/UserMapper.xml"/>
</mappers>
</configuration>
Spring配置文件:
<?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" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--开启自动扫描 注解方法实现控制反转-->
<context:component-scan base-package="cn.dao,cn.pojo,cn.service"/>
<!--配置数据源,引用外部文件-->
<context:property-placeholder location="classpath:database.properties"/>
<bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource" destroy-method="close">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<!--提供SqlSessionFactorybean:加载MyBatis配置文件,加载数据源-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="mybatis-config.xml"/>
</bean>
<!--定义事务管理对象-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启事务-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
创建一个Bean:User
public class User {
private int id;
private String name;
private char sex;
private int age;
private String address;
@Override
public String toString() {
return "\nUser{" +
"id=" + id +
", name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
", address='" + address + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public User(){}
public User(int id, String name, char sex, int age, String address) {
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
this.address = address;
}
}
创建SQL映射文件:
<?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="mybatis">
<select id="getUser" resultType="user">
select * from user
</select>
</mapper>
创建dao接口及接口的实现类
public interface UserDao {
public List<User> getUser();
}
@Service("userDao")
public class UserDaoImpl implements UserDao {
@Resource(name = "sqlSessionFactory") //注入SqlSessionFactory对象
private SqlSessionFactory factory;
@Override
public List<User> getUser() {
SqlSession session = factory.openSession();
List<User> list =session.selectList("mybatis.getUser");
return list;
}
}
编写Service业务接口及实现类
public interface UserService {
public List<User> getUser();
}
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService {
@Resource(name = "userDao")//注入UserDaoImpl实现类对象
private UserDao dao;
@Override
public List<User> getUser() {
List<User> list = dao.getUser();
return list;
}
}
测试类
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
UserService userService = (UserService) context.getBean("userService");
List<User> listuser =userService.getUser();
System.out.println(listuser);
}
}
映射器整合方式
上面的操作不仅需要编写Dao接口的实现类,还需要使用字符串定义方法的位置,代码繁多,容易出错,不宜维护。
在MyBatis框架中可以使用SqlSession的getMapper(Class type)方法,根据指定的映射器和映射文件直接生成实现类,大大减少工作量,SqlSessionTemplate类实现了SqlSession接口,所以也具有同样的功能,且利用MyBatis-Spring提供的组件可以提供配置的方式直接为业务对象注入映射器的实现类,无须额外编码。
方式1:使用MapperFactoryBean注入映射器
MyBatis-Spring提供的MapperFactoryBean能够以配置的方式生成映射器的实现类,并注入给业务组件。
<!--配置dao-->
<bean class="org.mybatis.spring.mapper.MapperFactoryBean" id="userDao">
<property name="sqlSessionFactory" ref="factory" />
<property name="mapperInterface" value="cn.dao.UserDao" />
</bean>
1.配置dao组件,class属性不是某个实现类而是MapperFacrtoryBean。
2.通过mapperInterface属性指定映射器,并且其值只能是接口类型,不能是某个实现类。
3.MapperFactoryBean是SqlSessionDaoSupprt的子类,使用时需要通过setSqlSessionFactory()方法是注入SqlSessionFactory实例以创建SqlSessionTemplate实例。
4.SQL映射文件中的命名空间和映射器接口的名称需相同,映射元素的id和映射器接口方法名相同。
方式2:使用MapperScannerConfigurer注入映射器
使用MapperFactoryBran对映射器做配置,在很大程度上简化了Dao模块的编码,不过,如果映射器很多,则相应的配置项也会很多。为了简化配置工作量,MyBatis-Spring中提供了MapperScannerConfigurer,它可以扫描指定包中的接口并将他们直接注册为MapperFactoyBean。配置方法如下:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" >
<property name="basePackage" value="cn.dao" />
</bean>
basePackage属性指定了需要扫描的基准包,MapperScannerConfigurer将递归扫描基准包(包括各层级子包)下的所有接口。如果它们在SQL映射文件中定义过,则将它们动态注册为映射器是实现类,即可批量生成映射器的是实现类了。
MapperScannerCongfigurer会为所有由它创建的实现类是开启自动装配。也就是说,这些实现类会自动注入SqlSessionFactory实例。无须显示注入SqlSessionFactoy实例。
映射器被注册到Spring容器时,Spring框架会根据其接口名称为其命名,默认是首字母小写的非完全限定类名。
示例:查询用户为例:
第一步添加jar包,和上面一样
Mybatis配置文件也和上面一样:
Spring配置文件:
<?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" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--开启自动扫描 注解方法实现控制反转-->
<context:component-scan base-package="cn.pojo,cn.service"/>
<!--配置数据源,引用外部文件-->
<context:property-placeholder location="classpath:database.properties"/>
<bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource" destroy-method="close">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<!--提供SqlSessionFactorybean:加载MyBatis配置文件,加载数据源-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="mybatis-config.xml"/>
</bean>
<!--扫描所有接口动态生成实现类-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.dao"/>
</bean>
<!--定义事务管理对象-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启事务-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
创建一个Bean:User
public class User {
private int id;
private String name;
private char sex;
private int age;
private String address;
@Override
public String toString() {
return "\nUser{" +
"id=" + id +
", name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
", address='" + address + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public User(){}
public User(int id, String name, char sex, int age, String address) {
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
this.address = address;
}
}
创建Dao接口无需实现类
public interface UserDao {
public List<User> getUser();
创建Service业务接口及实现类
public interface UserService {
public List<User> getUser();
@Service("userService")//使用注释事先控制反转
@Transactional
public class UserServiceImpl implements UserService {
@Resource(name = "userDao")//使用注释注入UserDao实现类对象
private UserDao dao;
@Override
public List<User> getUser() {
List<User> list = dao.getUser();
return list;
}
测试类:
public static void main(String[] args) {
UserService userService = (UserService) context.getBean("userService");
List<User> list =userService.getUser();
System.out.println(list);
}
事务
配置声明式事务
步骤1导入命名空间,
xmlns:tx=“http://www.springframework.org/schema/tx”
还需要两个依赖包
spring-tx-5.2.2.RELEASE.jar
spring-aop-5.2.2.RELEASE.jar
步骤2:定义事务管理器
<!--定义事务管理对象-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<!--注入定义好的数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
3:设置事务属性
事务管理器可以通过设定事务的属性为不同业务方法指定具体的事务规则。
<!--设置事务属性-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" propagation="SUPPORTS" read-only="true "/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
transaction-manager属性引用定义好的事务Bean
还可以在tx:method标签中配置事务的传播机制,隔离级别等属性,
Spring框架支持对不同的方法设置不同的事务属性,tx:method标签中的name属性时必须的,用于指定相匹配的方法,可以使用(*)通配符对方法名进行设置。除name属性外,
tx:method标签提供的其他属性均为可选配置。如下:
4:定义事务切面:
<!--定义切面-->
<aop:config>
<!--定义切入点-->
<aop:pointcut id="pointcut" expression="execution(* cn.service..*.*(..))"/>
<!--advice-ref引用设定好的事务属性的组件 pointcut-ref引用定好的切入点-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
使用注解实现事务
1.定义事务
<!--定义事务管理对象-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启注解处理事务事务-->
<tx:annotation-driven transaction-manager="transactionManager"/>
配置文件编写完成就可以在代码中使用@Transactional注解处理事务。
比如:
@Transactional//为类中的所有方法添加事务
public class UserServiceImpl implements UserService {
@Resource(name = "userDao")
private UserDao dao;
@Override
public List<User> getUser() {
List<User> list = dao.getUser();
return list;
}
如某个业务需要采用不同的事务处理规则,可以在该业务方法上添加@Transactional注解进行单独设置事务处理规则。
@Transactional也可以设置事务属性的值,默认的@Transactional设置如下:
- 事务传播特性是REQURED。
- 事务的隔离级别是DEFAULT。
- 事务是读/写。
- 事务超时规则默认是依赖于事务系统的。
- 所有的RuntimeException都会触发事务回滚,但是所有的checkel Exception都不会触发事务回滚。
当这些默认的设置无法满足需求时,也可以对其进行修改。@Transactional注解的属性如下表: