Spring与Mybatis整合
配置文件整合
1、引入jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!-- Spring整合mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!-- mysql驱动 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
<scope>runtime</scope>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<build>
<!-- 更改maven编译规则 -->
<resources>
<resource>
<!-- 资源目录 -->
<directory>src/main/java</directory>
<includes>
<include>*.xml</include><!-- 默认(新添加自定义则失效) -->
<include>**/*.xml</include><!-- 新添加 */代表1级目录 **/代表多级目录 -->
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
2、编写数据库文件 database.properties
url=jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=utf-8
driverClassName=com.mysql.jdbc.Driver
username=root
password=715442603
initialSize=5
maxActive=20
maxWait=60000
minIdle=10
removeAbandoned=true
removeAbandonedTimeout=300
logAbandoned=true
validationQuery=select
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
3、配置文件都在spring-context.xml中
头文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 数据库配置信息文件位置-->
<context:property-placeholder location="classpath:database.properties"></context:property-placeholder>
<!--配置数据源(连接池)-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!--基本配置-->
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<!-- 配置初始化大小 最小最大-->
<property name="initialSize" value="${initialSize}"/>
<property name="minIdle" value="${minIdle}"/>
<property name="maxActive" value="${maxActive}"/>
<!-- 配置获取链接等待超时时间-->
<property name="maxWait" value="${maxWait}"/>
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<property name="minEvictableIdleTimeMillis" value="300000"/>
</bean>
<!--创建mybatis操作数据库是需要的SqlSeesionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--为其注入属性值-->
<property name="dataSource" ref="dataSource"></property>
<!--告知Mybatis接口对应的映射文件的位置-->
<property name="mapperLocations">
<list>
<value>classpath:com/qf/sam/dao/*.xml</value>
</list>
</property>
<!--配置实体类的别名-->
<property name="typeAliasesPackage" value="com.qf.sam.entity"></property>
</bean>
<!--配置MapperCannerConfigurer 在dao中通过此配置就可以得到sqlSession-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--dao接口所在的包:如果接口在多个包中,可以使用逗号进行分割-->
<!-- <property name="basePackage" value="com.qf.sam.dao,com.qf.sam.entity"></property>-->
<property name="basePackage" value="com.qf.sam.dao"></property>
<!--配置得到sqlSession需要的sqlSessionFactory
【说明】引入另一个对象时,需要使用ref进行引入,但是此处通过value引入
-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<bean id="us" class="com.qf.sam.service.Impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!--配置事务管理-->
<!--首先创建事务管理器-->
<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入datasourse属性-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务通知 xml方式-->
<tx:advice id="txManage" transaction-manager="tx">
<!--相当于织入-->
<tx:attributes>
<tx:method name="*Users" rollback-for="Exception" isolation="DEFAULT"
propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="trPointCut" expression="execution(public boolean insertUsers(..))"></aop:pointcut>
<aop:advisor advice-ref="txManage" pointcut-ref="trPointCut"></aop:advisor>
</aop:config>
4、dao和mapper.xml如以往一样
5、service类
//利用springIoC实现了解耦
private DeptDao deptDao;
public void setDeptDao(DeptDao deptDao) {
this.deptDao = deptDao;
}
public boolean insertDept(Dept dept) {
int result=deptDao.insertByBach(dept);
if (result==1){
return true;
}else{
return false;
}
}
测试
public static void main(String[] args) {
ApplicationContext applicationContext=new
ClassPathXmlApplicationContext("spring-context.xml");
DeptService ds=(DeptService)applicationContext.getBean("ds");
Dept dept=new Dept();
dept.setDeptName("软件开发超级俱乐部");
dept.setDeptLoc("软件园15号楼");
boolean result=ds.insertDept(dept);
if (result){
System.out.println("添加成功!");
}else {
System.out.println("添加失败!");
}
}
事务
1、事务的特性 ACID
2、事务的隔离级别 4个
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 |
不可重复读(read-committed) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
3、传播行为 7个
事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播。
事务传播行为类型 | 说明 |
---|---|
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
4、Spring事务的处理机制
1)、编程式事务
单独编码 去开启 提交 回滚事务,事务的控制代码散落在service中
2)、声明式事务
统一对事务进行管理,无需自行编写事务的管理代码 推荐
5、Spring事务配置的实现
<!--创建事务管理器-->
<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入datasourc属性-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置事务通知:xml文件配置
用事务管理器,管理 哪些方法采用何种 事务的隔离级别 及 传播行为
-->
<tx:advice id="txManager" transaction-manager="tx">
<!--相当于给方法织入事务-->
<tx:attributes>
<tx:method name="insertDepts"
isolation="DEFAULT" propagation="REQUIRED"
rollback-for="Exception" read-only="false"/>
<tx:method name="*Depts" isolation="DEFAULT"
propagation="REQUIRED" rollback-for="Exception"></tx:method>
</tx:attributes>
</tx:advice>
<!--aop配置-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="trPointCut" expression="execution(public boolean insertDepts(..))"/>
<!--织入-->
<aop:advisor advice-ref="txManager" pointcut-ref="trPointCut"></aop:advisor>
</aop:config>
4、事务回滚:
1)如果发生异常并且try-catch捕获了,将不会发生回滚
2)如果发生异常并且try-catch捕获了,在catch中再次抛出/引发异常,事务将回滚
3)不捕获异常,事务回顾
4)自己根据业务抛出异常,让事务捕获,事务回滚
5)spring事务默认捕获的是runtimeException 如果抛出check异常,事务还会提交
解决方法: 把check异常转换为runtime异常 rollback-for=“Exception”
注解方式整合
@Service 应用于service对应的类,放在类的上方 创建该类的对象,对象名是类名首字母小写
@Autowired 应用于属性的上方,按类型自动注入值
【注意】 如果使用注解,需要在配置文件中告知spring去扫描指定的包
事务注解方式
<!--创建事务管理器-->
<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入datasourc属性-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 设置类中的Transactional注解,使用何种事务管理器-->
<tx:annotation-driven transaction-manager="tx"></tx:annotation-driven>
1、注解实现事务
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
2、注解方式实现Ioc
-
@Service 业务类专用
@Repository dao实现类专用
@Controller web层专用 -
@Component 通用
-
@Scope 用户控制bean的创建模式
属性注入
- @Autowired 基于类型自动注入
- @Resource 基于名称自动注入
- @Qualifier(“userDAO”) 限定要自动注入的bean的id,一般和@Autowired联用
- @Value 注入简单类型数据 (jdk8种+String)
service中:
@Service("dsi") //创建DeptServiceImpl对象的名字为dsi
@Scope("prototype") //指明bean的作用域
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
public class DeptServiceImpl implements DeptService {
//利用springIoC实现了解耦
//注入值
@Autowired
// @Qualifier("dd")
// @Resource(name = "dd") //按照名称注入,到bean容器中找名字是dd的对象,赋值给deptDao
private DeptDao deptDao;
public boolean insertDept(Dept dept) {
int result=deptDao.insertByBach(dept);
if (result==1){
return true;
}else{
return false;
}
}
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT)
public boolean insertDepts(List<Dept> depts){
int count=0;
// try {
for (Dept dept:depts
) {
count=count+deptDao.insertByBach(dept);
}
// }catch (Exception ex){
// System.out.println(ex.getMessage());
// int result=1/0;
// }
if(count==depts.size()){
return true;
}else {
return false;
}
}
}
3、注解实现Aop
@Aspect //身份:切面
@Component //创建好Bean对象加入到bean工厂中
public class MyAdvice {
//声明切入点
@Pointcut("execution(public * com.qf.sam.service.impl.*.*(..))")
public void p1(){}
//编写前置增强方法
@Before("p1()")
public void doBefore(JoinPoint joinPoint){
System.out.println(joinPoint.getTarget()+
"里的"+joinPoint.getSignature()+"方法将被执行");
}
@AfterReturning(value = "p1()", returning = "result")
public void doAfter(JoinPoint joinPoint,Object result){
System.out.println(joinPoint.getSignature()+"方法被执行,返回值:"+result);
}
//异常处理增强
@AfterThrowing(value = "p1()", throwing = "ex")
public void doThrowing(JoinPoint joinPoint,Exception ex){
System.out.println(joinPoint.getSignature()+"方法发生异常,异常信息如下:"+ex.getMessage());
}
//最终增强
@After("p1()")
public void doFinally(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature()+"方法执行了finally");
}
}
配置文件启动Aop
<!--启动Aop-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
完整的spring-context.xml文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 数据库配置信息文件位置-->
<context:property-placeholder location="classpath:database.properties"></context:property-placeholder>
<!--配置数据源(连接池)-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!--基本配置-->
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<!-- 配置初始化大小 最小最大-->
<property name="initialSize" value="${initialSize}"/>
<property name="minIdle" value="${minIdle}"/>
<property name="maxActive" value="${maxActive}"/>
<!-- 配置获取链接等待超时时间-->
<property name="maxWait" value="${maxWait}"/>
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<property name="minEvictableIdleTimeMillis" value="300000"/>
</bean>
<!--创建mybatis操作数据库是需要的SqlSeesionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--为其注入属性值-->
<property name="dataSource" ref="dataSource"></property>
<!--告知Mybatis接口对应的映射文件的位置-->
<property name="mapperLocations">
<list>
<value>classpath:com/qf/sam/dao/*.xml</value>
</list>
</property>
<!--配置实体类的别名-->
<property name="typeAliasesPackage" value="com.qf.sam.entity"></property>
</bean>
<!--配置MapperCannerConfigurer 在dao中通过此配置就可以得到sqlSession-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--dao接口所在的包:如果接口在多个包中,可以使用逗号进行分割-->
<!-- <property name="basePackage" value="com.qf.sam.dao,com.qf.sam.entity"></property>-->
<property name="basePackage" value="com.qf.sam.dao"></property>
<!--配置得到sqlSession需要的sqlSessionFactory
【说明】引入另一个对象时,需要使用ref进行引入,但是此处通过value引入
-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!--开启注解扫描-->
<context:component-scan base-package="com.qf.sam"/>
<!--首先创建事务管理器-->
<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入datasourse属性-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:annotation-driven transaction-manager="tx"></tx:annotation-driven>
<aop:aspectj-autoproxy/>
</beans>