1.环境搭建总目标:
2.环境配置:
集成开发IDE:IntelliJ IDEA 2021.3.1
开发工具:JDK.1.8.0
管理项目:Maven,版本采用3.6.3,采用多模块开发
数据库:MySql-5.7.23
本地服务器:Tomcat-8.5.20
3.创建工程:
3.1.工程架构图
3.2.工程创建计划
-
-
- atcrowdfunding01-admin-parent
- groupId:com.atguigu.crowd
- artifactI:atcrowdfunding01-admin-parent
- packaging:pom
-
-
-
- atcrowdfunding02-admin-webui
- groupId:com.atguigu.crowd
- artifactI:atcrowdfunding02-admin-webui
- packaging:war
-
-
-
- atcrowdfunding03-admin-component
- groupId:com.atguigu.crowd
- artifact:atcrowdfunding03-admin-component
- packaging:jar
-
-
-
- atcrowdfunding04-admin-entity
- groupId:com.atguigu.crowd
- artifactI:atcrowdfunding04-admin-entity
- packaging:jar
-
-
-
- atcrowdfunding05-common-util
- groupId:com.atguigu.crowd
- artifactId:atcrowdfunding05-common-util
- packaging:jar
-
-
-
- atcrowdfunding06-common-reverse
- groupId:com.atguigu.crowd
- artifactId:atcrowdfunding06-common-reverse
- packaging:jar
-
4.工程之前的依赖关系:
父工程信息:
atcrowdfunding02-admin-webui 依赖于
atcrowdfunding03-admin-component 依赖于
5.创建管理员数据库表:
CREATE DATABASE `project_crowd` CHARACTER SET utf8; use project_crowd; drop table if exists t_admin; create table t_admin ( id int not null auto_increment, # 主键 login_acct varchar(255) not null, # 登录账号 user_pswd char(32) not null, # 登录密码 user_name varchar(255) not null, # 昵称 email varchar(255) not null, # 邮件地址 create_time char(19), # 创建时间 primary key (id) );
6.基于 Maven 的 MyBatis 逆向工程
6.1.pom.xml文件配置
<!-- 依赖 MyBatis 核心包 --> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> </dependencies> <!-- 控制 Maven 在构建过程中相关配置 --> <build> <!-- 构建过程中用到的插件 --> <plugins> <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 --> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.0</version> <!-- 插件的依赖 --> <dependencies> <!-- 逆向工程的核心依赖 --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.2</version> </dependency> <!-- 数据库连接池 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.2</version> </dependency> <!-- MySQL 驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.8</version> </dependency> </dependencies> </plugin> </plugins> </build>
6.2 generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- mybatis-generator:generate --> <context id="atguiguTables" targetRuntime="MyBatis3"> <commentGenerator> <!-- 是否去除自动生成的注释 true:是;false:否 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/project_crowd" userId="root" password="123"> </jdbcConnection> <!-- 默认 false,把 JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true 时把 JDBC DECIMAL 和 NUMERIC 类型解析为 java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- targetProject:生成 Entity 类的路径 --> <javaModelGenerator targetProject=".\src\main\java" targetPackage="com.atguigu.crowd.entity"> <!-- enableSubPackages:是否让 schema 作为包的后缀 --> <property name="enableSubPackages" value="false" /> <!-- 从数据库返回的值被清理前后的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:XxxMapper.xml 映射文件生成的路径 --> <sqlMapGenerator targetProject=".\src\main\java" targetPackage="com.atguigu.crowd.mapper"> <!-- enableSubPackages:是否让 schema 作为包的后缀 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:Mapper 接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetProject=".\src\main\java" targetPackage="com.atguigu.crowd.mapper"> <!-- enableSubPackages:是否让 schema 作为包的后缀 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 数据库表名字和我们的 entity 类对应的映射指定 --> <table tableName="t_admin" domainObjectName="Admin" /> </context> </generatorConfiguration>
6.3 执行逆向生成操作的 Maven 命令
mybatis-generator:generate
6.4 逆向工程生成的资源各归各位
WebUI 工程将来在 Tomcat 上运行时,现在 resources 目录下的资源会直接放在 WEB-INF/classes 目录(也就是类路径)下,所以放在 resources 目录下运行的时候更容易找到。
逆向工程生成的实体类放在admin-entity
生成的Mapper接口放在admin-component
生成的Mapeer映射文件放在admin-webui
7.父工程依赖管理
7.1 版本声明
<!--版本指定--> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <!-- 声明属性,对 Spring 的版本进行统一管理 --> <atguigu.spring.version>4.3.20.RELEASE</atguigu.spring.version> <!-- 声明属性,对 SpringSecurity 的版本进行统一管理 --> <atguigu.spring.security.version>4.2.10.RELEASE</atguigu.spring.security.version> <jsp-api.version>2.3.0</jsp-api.version> </properties> <dependencyManagement> <dependencies> <!-- Spring 依赖 --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${atguigu.spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${atguigu.spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${atguigu.spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.2</version> </dependency> <!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency> <!-- 数据库依赖 --> <!-- MySQL 驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.3</version> </dependency> <!-- 数据源 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.31</version> </dependency> <!-- MyBatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> <!-- MyBatis 与 Spring 整合 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.2</version> </dependency> <!-- MyBatis 分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>4.0.0</version> </dependency> <!-- 日志 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.36</version> </dependency> <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.11</version> </dependency> <!-- 其他日志框架的中间转换包 --> <!-- https://mvnrepository.com/artifact/org.slf4j/jul-to-slf4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.36</version> </dependency> <!-- Spring 进行 JSON 数据转换依赖 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.8</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.8</version> </dependency> <!-- JSTL 标签库 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- junit 测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- 引入 Servlet 容器中相关依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <!-- JSP 页面使用的依赖 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>${jsp-api.version}</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency> <!-- SpringSecurity 对 Web 应用进行权限管理 --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>4.2.10.RELEASE</version> </dependency> <!-- SpringSecurity 配置 --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.2.10.RELEASE</version> </dependency> <!-- SpringSecurity 标签库 --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>4.2.10.RELEASE</version> </dependency> </dependencies> </dependencyManagement>
7.2 依赖信息来源
到专门网站搜索
调试
SpringMVC 需要 jackson 的支持,来处理 JSON 数据。但是 SpringMVC 并没有依赖jackson。所以需要我们自己保证 jar 包之间的兼容性。
8 Spring 整合 MyBatis
8.1 目标
adminMapper 通过 IOC 容器装配到当前组件中后,就可以直接调用它的方法,享受到框架给我们提供的方便
8.2 思路
8.3 操作清单
在子工程中加入搭建环境所需要的具体依赖
准备 jdbc.properties
创建 Spring 配置文件专门配置 Spring 和 MyBatis 整合相关
在 Spring 的配置文件中加载 jdbc.properties 属性文件
配置数据源测试从数据源中获取数据库连接
配置 SqlSessionFactoryBean
装配数据源
指定 XxxMapper.xml 配置文件的位置指定 MyBatis 全局配置文件的位置(可选)
配置 MapperScannerConfigurer
测试是否可以装配 XxxMapper 接口并通过这个接口操作数据库
8.4 操作步骤详解
8.4.1在子工程中加入搭建环境所需的具体依赖子工程:
选择 component 工程。原因是具体依赖和 component 工程相关。
<!-- Spring 依赖 --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <!--移除--> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> </dependency> <!-- MySQL 驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 数据源 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <!-- MyBatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> </dependency> <!-- MyBatis 与 Spring 整合 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> </dependency> <!-- MyBatis 分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> </dependency> <!-- Spring 进行 JSON 数据转换依赖 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- JSTL 标签库 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> </dependency> </dependencies>
8.4.2 数据库连接信息
jdbc.properties
jdbc.user=root jdbc.password=123 jdbc.url=jdbc:mysql://localhost:3306/project_crowd?useUnicode=true&characterEncoding=UTF-8 jdbc.driver=com.mysql.jdbc.Driver
8.4.3 mybatis-config.xml
<?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> </configuration>
8.4.4 创建 spring-persist-mybatis.xml
8.4.5 Spring 具体配置:第一步配置数据源
在 spring-persist-mybatis.xml 配置文件进行配置
<!-- 加载 jdbc.properties --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 配置数据源 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <!-- 连接数据库的用户名 --> <property name="username" value="${jdbc.user}"/> <!-- 连接数据库的密码 --> <property name="password" value="${jdbc.password}"/> <!-- 目标数据库的 URL 地址 --> <property name="url" value="${jdbc.url}"/> <!-- 数据库驱动全类名 --> <property name="driverClassName" value="${jdbc.driver}"/> </bean>
在做测试之前先在atcrowdfunding02-admin-webui模块的pom.xml
添加依赖包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> </dependency> <!-- junit 测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency>
创建 Spring 的 Junit 测试类
// 指定 Spring 给 Junit 提供的运行器类 @RunWith(SpringJUnit4ClassRunner.class) // 加载 Spring 配置文件的注解 @ContextConfiguration(locations = {"classpath:spring-persist-mybatis.xml"}) public class CrowdSpringTest { @Autowired private DataSource dataSource; @Test public void testDataSource() throws SQLException { // 1.通过数据源对象获取数据源连接 Connection connection = dataSource.getConnection(); // 2.打印数据库连接 System.out.println(connection); } }
8.4.6 Spring 具体配置:第二步配置 SqlSessionFactoryBean
<!-- 配置 配置SqlSessionFactoryBean整合Mybatis--> <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 装配数据源 --> <property name="dataSource" ref="dataSource"/> <!-- 指定 MyBatis 全局配置文件位置 --> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!-- 指定 Mapper 配置文件位置 --> <property name="mapperLocations" value="classpath:mybatis/mapper/*Mapper.xml"/> </bean>
8.4.7 Spring 具体配置:第三步配置 MapperScannerConfigurer
<!-- 配置 MapperScannerConfigurer --> <!-- 把 MyBatis 创建的 Mapper 接口类型的代理对象扫描到 IOC 容器中 --> <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 使用 basePackage 属性指定 Mapper 接口所在包 --> <property name="basePackage" value="com.atguigu.crowd.mapper"/> </bean>
测试
@Autowired private AdminMapper adminMapper; @Test public void addAdmintest(){ Admin admin = new Admin(null,"admin","123","叶书文","299@qq.com",null); int count = adminMapper.insert(admin); System.out.println("受影响的行数"+count); }
8.4.8 总结
9 日志系统
9.1 重要意义
系统在运行过程中出了问题就需要通过日志来进行排查,所以我们在上手任何新技术的时候,都要习惯性的关注一下它是如何打印日志的。
9.2 技术选型
9.2.1 总体介绍
9.2.3不同日志系统的整合
9.3 具体操作
9.3.1 初始状态
Spring 使用 commons-logging 日志包。打印的日志是下面这样的。不用细看,截图放在这是为了和后面日志打印的情况对比。
9.3.2 加入 slf4j+logback 依赖信息是:
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency>
代码不变,日志情况是:
9.3.3 我们主动打印的日志把查询到的 Admin 对象以日志的方式打印出来,代码如下:
Admin admin = adminMapper.selectByPrimaryKey(1); / 获取日志记录对象 Logger logger = LoggerFactory.getLogger(CrowdTest.class); // 按照 Debug 级别打印日志 logger.debug(admin.toString());
※使用日志打印信息和使用 sysout 打印信息的区别:sysout 如果不删除,那么执行到这里必然会打印;如果使用日志方式打印,可以通过日志级别控制信息是否打印。效果
这里我们看到除了 Druid 数据源打印了两条日志,Spring 和 MyBatis 并没有通过 slf4j 打印日志。所以下一步我们要考虑的就是如何将框架所使用的日志系统统一到 slf4j。
9.3.4 在atcrowdfunding03-admin-component模块 pom.xml
更换框架的日志系统
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <!--移除--> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency>
在atcrowdfunding02-admin-webui模块 pom.xml
同样的
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <!--移除--> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency>
这个时候如果运行程序会抛异常,因为我们把 Spring 依赖的 commons-logging 排除了,而这个依赖是必须有的,不是可选的。
第二步:在atcrowdfunding03-admin-component模块 pom.xml
加入转换包
<dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.25</version> </dependency>
打印效果局部:
9.3.5 logback 配置文件 logback
工作时的具体细节可以通过 logback.xml 来配置。
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="true"> <!-- 指定日志输出的位置 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <!-- 日志输出的格式 --> <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 --> <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern> </encoder> </appender> <!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR --> <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 --> <root level="DEBUG"> <!-- 指定打印日志的 appender,这里通过“STDOUT”引用了前面配置的 appender --> <appender-ref ref="STDOUT" /> </root> <!-- 根据特殊需求指定局部日志级别 --> <logger name="com.atguigu.crowd.mapper" level="DEBUG"/> </configuration>
10 声明式事务
10.1 目标
从事务角度:一个事务方法中包含的多个数据库操作,要么一起提交、要么一起回 滚。也就是说事务方法中的多个数据库操作,有任何一个失败,整个事务全部回滚。从声明式角度:由 Spring 来全面接管数据库事务。用声明式代替编程式。
try { // 核心操作前:开启事务(关闭自动提交) // 对应 AOP 的前置通知 connection.setAutoCommit(false); // 核心操作 adminService.updateXxx(xxx, xxx); // 核心操作成功:提交事务 // 对应 AOP 的返回通知 connection.commit(); }catch(Exception e){ // 核心操作失败:回滚事务 // 对应 AOP 的异常通知 connection.rollBack(); }finally{ // 不论成功还是失败,核心操作终归是结束了 // 核心操作不管是怎么结束的,都需要释放数据库连接 // 对应 AOP 的后置通知 if(connection != null){ connection.close(); }
10.2 思路
10.3 操作
10.3.1 加入 AOP 依赖包
<!-- AOP 所需依赖 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> <!-- AOP 所需依赖 --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> </dependency>
10.3.2 第一步:创建 spring-persist-tx配置文件
10.3.3 第二步:配置事物管理
<!--配置自动扫描的包:主要是为了把Service扫描到Ioc容器里面--> <context:component-scan base-package="com.atguigu.crowd.service"/> <!--配置事物管理器--> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--装配数据源--> <property name="dataSource" ref="dataSource"></property> </bean>
10.3.4 第三步:配置 AOP
<!-- 配置 AOP 事务切面--> <aop:config> <!-- 配置切入点表达式 --> <!-- public String com.atguigu.crowd.service.AdminService.getXxx(Integer id) --> <!--考虑到后面我们整合SpringSecurity,避免UserDetailsService加入事务控制,让切入点表达式定位到ServiceImpl--> <aop:pointcut expression="execution(* *..*ServiceImpl.*(..))" id="txPointCut"/> <!-- 将事务通知和切入点表达式关联到一起 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config>
10.3.5 第四步:配置事务属性
<!-- 配置事务通知 --> <!-- id 属性用于在 aop:advisor 中引用事务通知 --> <!-- transaction-manager 属性用于引用事务管理器,如果事务管理器的 bean 的 id 正好是 transactionManager,可以省略这个属性 --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <!-- name 属性指定当前要配置的事务方法的方法名 --> <!-- 查询的方法通常设置为只读,便于数据库根据只读属性进行相关性能优化 --> <tx:method name="get*" read-only="true"/> <tx:method name="query*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="count*" read-only="true"/> <!-- 增删改方法另外配置 --> <!-- propagation 属性配置事务方法的传播行为 --> <!-- 默认值:REQUIRED 表示:当前方法必须运行在事务中,如果没有事务,则开启事务,在自己的事务中运行。如果已经有了已开启的事务,则在当前事务中运行。有可能和其他方法共用同一个事务。 --> <!-- 建议值:REQUIRES_NEW 表示:当前方法必须运行在事务中,如果没有事务,则开启事务,在自己的事务中运行。和 REQUIRED 的区别是就算现在已经有了已开启的事务,也一定要开启自己的事务,避免和其他方法共用同一个事务。 --> <!-- rollback-for 属性配置回滚的异常 --> <!-- 默认值:运行时异常 --> <!-- 建议值:编译时异常+运行时异常 --> <tx:method name="save*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception" /> <tx:method name="remove*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception" /> <tx:method name="update*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception" /> </tx:attributes> </tx:advice>
测试
@Service public class AdminServiceImpl implements AdminService { @Autowired private AdminMapper adminMapper; @Override public void saveAdmin(Admin admin) { adminMapper.insert(admin); } }
package com.crowd; @RunWith(SpringJUnit4ClassRunner.class) // 加载 Spring 配置文件的注解 @ContextConfiguration(locations = {"classpath:spring-persist-mybatis.xml","classpath:spring-persist-tx.xml"}) public class CrowdSpringTest { @Autowired private AdminMapper adminMapper; @Autowired private AdminService adminService; @Test public void testTx(){ Admin admin = new Admin(null, "jakc", "123", "萧枫", "422@qq.com", null); adminService.saveAdmin(admin); } @Test public void testLog(){ //1.获取Logger对象,这里传入的Class对象就是当前打印日志的类 Logger logger = LoggerFactory.getLogger(CrowdSpringTest.class); //2.根据不同的日志级别打印日志 logger.debug("Hello I am Debug level!!!"); logger.info("Info level!!!"); logger.warn("Warn leven!!!"); logger.error("Error level!!!"); } }