把mybatis数据源
交给Spring管理
把mybatis的核心对象SqlSessionFactory
交给Spring管理
把mapper代理对象
交给Spring管理,service的bean
交给Spring管理,在service层
基于AOP核心 Spring提供声明式事务管理器,进行事务控制,利用AOP把事务控制增强到业务层方法上
Spring与web整合:当web服务器启动的时候,帮我们创建Spring容器
Servlet不能交给Spring管理 只能手动getBean()
解决:SpringMVC替换servlet
创建maven的web项目
maven如何创建web项目 更多细节请看下一篇——Spring与web整合
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>spring-webDemoartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<name>spring-webDemo Maven Webappname>
<url>http://www.example.comurl>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<spring.version>5.2.15.RELEASEspring.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-ormartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.7version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>2.0.6version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.27version>
dependency>
<dependency>
<groupId>com.mchangegroupId>
<artifactId>c3p0artifactId>
<version>0.9.5.2version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>jsp-apiartifactId>
<version>2.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.4version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>2.0.0version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.36version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.24version>
dependency>
<dependency>
<groupId>javax.injectgroupId>
<artifactId>javax.injectartifactId>
<version>1version>
dependency>
dependencies>
<build>
<finalName>spring-webDemofinalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-pluginartifactId>
<version>3.1.0version>
plugin>
<plugin>
<artifactId>maven-resources-pluginartifactId>
<version>3.0.2version>
plugin>
<plugin>
<artifactId>maven-compiler-pluginartifactId>
<version>3.8.0version>
plugin>
<plugin>
<artifactId>maven-surefire-pluginartifactId>
<version>2.22.1version>
plugin>
<plugin>
<artifactId>maven-war-pluginartifactId>
<version>3.2.2version>
plugin>
<plugin>
<artifactId>maven-install-pluginartifactId>
<version>2.5.2version>
plugin>
<plugin>
<artifactId>maven-deploy-pluginartifactId>
<version>2.8.2version>
plugin>
plugins>
pluginManagement>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.xmlinclude>
<include>**/*.propertiesinclude>
includes>
<filtering>truefiltering>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.xmlinclude>
<include>**/*.propertiesinclude>
includes>
<filtering>truefiltering>
resource>
resources>
build>
project>
导入配置
spring的配置文件
mybatis的配置: 全局配置文件: mybatis-config.xml , sql映射文件
数据库四大参数文件: db.properties
日志配置文件: log4j.properties
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X0bQIjwy-1670499551776)(D:\PracticalTrainning3\note\第二十二周\assets\1670499089433.png)]
编写配置文件
Spring的配置文件
applicationContext.xml
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.fs"/>
<context:property-placeholder location="classpath:db.properties" file-encoding="UTF-8"/>
<import resource="beans-mapper.xml"/>
<import resource="beans-tx.xml"/>
beans>
bean-mapper.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<property name="initialPoolSize" value="${jdbc.initialPoolSize}"/>
<property name="acquireIncrement" value="${jdbc.acquireIncrement}"/>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"/>
<property name="minPoolSize" value="${jdbc.minPoolSize}"/>
bean>
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="typeAliasesPackage" value="com.fs.shop.pojo"/>
<property name="mapperLocations" value="classpath*:mapper/*Mapper.xml"/>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.fs.shop.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
bean>
beans>
bean-tx.xml
…
如果加了事务 有异常 就会回滚 不会对数据库进行操作
如果没加事务(在非事务下执行代码) 即使抛了异常 但还是会对数据库进行操作
Spring提供两种事务管理:
提供一个事务管理器: PlatformTransactionManager(接口类型,位于spring-tx的jar), 配置一个事务管理器
使用的实现类:
- 基于jdbc的事务管理器: DataSourceTransactionManager (类) 位于spring-jdbc的jar, Mybatis使用这个事务管理器
- 基于hibernate的事务管理器: HibernateTransactionManager(类),位于Hibernate的jar
TransactionDefinition 定义事务信息 事务可以配置什么
隔离级别 传播行为 超出时间 只读 事务策略
事务四大特征: ACID
原子性 隔离性 一致性 持久性
回滚点?事务是什么?为什么要开启事务?
假设A银行存钱,B同时去银行取钱,此时银行账户只有这100块钱,为了保证事务的原子性,不可能出现B取不到钱,而A却成功存了钱,开启事务,发生异常的时候就回滚,如果A存钱失败了,B也不能取钱(回到取多少钱的页面)。
A存钱,B取钱相当于两个sql语句,一起执行,有时候会失败,所以需要事务。
rollBack() 如果没有回滚点 从结束到开始 回滚一遍
isCompleted 事务是否完成 事务提交、回滚就结束
在bean-tx.xml配置
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
bean>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="query*" read-only="true" propagation="SUPPORTS" />
<tx:method name="select*" read-only="true" propagation="SUPPORTS" />
<tx:method name="find*" read-only="true" propagation="SUPPORTS" />
<tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
<tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
<tx:method name="del*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="pointcut1" expression="execution(* com.fs.shop..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
aop:config>
propagation事务传播机制: 默认: REQUIRED
在方法上提供事务注解: @Transactional
<tx:annotation-driven/>
@Override
@Transactional(rollbackFor = Exception.class)//表示该方法是在事务管理下执行
public void saveUser(User user) throws SQLException {
userMapper.insert(user);
if(true){
throw new SQLException("测试");
}
}
非事务方法调用事务方法 1. 注解 2. 得到代理对象来调用事务方法 但是要expose-proxy
在方法上提供事务注解: @Transactional
<tx:annotation-driven/>
@Override
@Transactional(rollbackFor = Exception.class)//表示该方法是在事务管理下执行
public void saveUser(User user) throws SQLException {
userMapper.insert(user);
if(true){
throw new SQLException("测试");
}
}
非事务方法调用事务方法
出现 Closing non transactional SqlSession 导致事务失败问题
解决:1. 在类上加全局注解 @Transactional
2. 得到当前类代理对象来调用事务方法 但是要在beans.xml配置exposeProxy=true 用于控制AOP框架公开代理,公开后才可以通过AopContext获取到当前代理类。
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
基于注解的配置
@EnableAspectJAutoProxy(proxyTargteClass = true, exposeProxy = true)
1.使用 ApplicationContext 上下文对象获取该对象;
2.使用 AopContext.currentProxy() 获取代理对象
UserMapper currentProxy =(UserMapper)AopContext.currentProxy();
currentProxy.queryById(1);