当前位置: 首页 > news >正文

贵阳美容网站建设1有免费建网站

贵阳美容网站建设,1有免费建网站,展板模板网站,wordpress页面视频Spring整合Junit4和JdbcTemplater如下所示#xff1a; 我们所使用的junit的jar包不同#xff0c;可以整合不同版本的junit。 我们导入的依赖如下所示#xff1a; ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.a…Spring整合Junit4和JdbcTemplater如下所示 我们所使用的junit的jar包不同可以整合不同版本的junit。 我们导入的依赖如下所示 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.rgf.spring/groupIdartifactIdspring-transaction/artifactIdversion1.0-SNAPSHOT/versionpackagingjar/packagingpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependencies!--基于Maven依赖传递性导入spring-context依赖即可导入当前所需所有jar包--!-- https://mvnrepository.com/artifact/org.springframework/spring-context --dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.1/version/dependency!--Spring持久化层支持jar包--!--Spring在执行持久化层操作与持久层技术进行整合过程中需要使用orm,jdbc.trx这三个jar包--dependency!--对象关系映射--groupIdorg.springframework/groupIdartifactIdspring-orm/artifactIdversion5.3.1/version/dependency!--spring测试相关--dependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion5.3.1/version/dependency!--junit测试--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency!--MySQL驱动--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.22/version/dependency!--数据源--dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.0.31/version/dependency/dependencies /project  其中的事务管理如下所示 我们的配置文件编写如下所示 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd !--引入jdbc.properties--context:property-placeholder locationclasspath:jdbc.properties/context:property-placeholderbean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName value${jdbc.driver}/propertyproperty nameurl value${jdbc.url}/propertyproperty nameusername value${jdbc.username}/propertyproperty namepassword value${jdbc.password}/property/beanbean classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/property/bean/beans 我们选定一个数据库表来进行测试如下所示 package com.rgf.spring.test;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; //指定当前测试类在spring的测试环境中执行此时就可以通过注入的方式直接来获取IOC容器中的bean RunWith(SpringJUnit4ClassRunner.class) //设置spring测试环境的配置文件 //classpath:类路径 ContextConfiguration(classpath:spring-jdbc.xml) public class JdbcTemplateTest {Autowiredprivate JdbcTemplate jdbcTemplate;Testpublic void testInsert(){String sqlinsert into t_user values(null,?,?,?,?,?);jdbcTemplate.update(sql,root,123,23,男,123qq.com);} }我们运行之后如下所示  我们在数据库表进行刷新之后如下所示  我们完成添加功能之后我们进行查看查询功能我们进行测试如下 Testpublic void testGetUserById(){String sqlselect * from t_user where id?;User user jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper(User.class), 1);System.out.println(user);} 测试完成之后如下所示 我们发现成功的查询出来了  我们进行查询多条数据 Testpublic void testGetAllUser(){String sqlselect * from t_user;ListUser list jdbcTemplate.query(sql, new BeanPropertyRowMapper(User.class));list.forEach(System.out::println);} 运行之后如下所示  我们查询总记录数如下所示 Testpublic void testGetCount(){String sqlselect count(*) from t_user;Integer count jdbcTemplate.queryForObject(sql, Integer.class);System.out.println(count);} 运行之后如下所示 声明式事务概念 编程式事务 事务功能的相关操作全部通过自己编写代码来实现 Connection conn...;try{//开启事务关闭事务的自动提交conn.setAutoCommit(false);//核心操作//提交事务conn.commit();}catch(Exception e){//回滚事务conn.rollback();}finally {//释放数据库连接conn.close();} 编程式的方式存在缺陷 细节没有被屏蔽具体操作过程中所以细节都需要程序员自己来完成比较繁琐。 代码复用性不高如果没有有效抽取出来每次实现功能都需要自己编写代码代码就没有得到复用。 声明式事务 既然事务控制的代码有规律可循代码的结构基本是确定的所以框架就可以将固定模式的代码抽取出来进行相关的封装。 封装起来后我们只需要在配置文件中进行简单的配置即可完成操作。 好处1提高开发效率 好处2消除了冗余的代码 好处3框架会综合考虑相关领域中在实际开发环境下有可能遇到的各种问题进行了健壮性、性能等各个方面的优化 所以我们可以总结下面两个概念 编程式自己写代码实现功能 声明式通过配置让框架实现功能 基于注解的声明式事务 我们所导入的依赖如下所示 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.rgf.spring/groupIdartifactIdspring-transaction/artifactIdversion1.0-SNAPSHOT/versionpackagingjar/packagingpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependencies!--基于Maven依赖传递性导入spring-context依赖即可导入当前所需所有jar包--!-- https://mvnrepository.com/artifact/org.springframework/spring-context --dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.1/version/dependency!--Spring持久化层支持jar包--!--Spring在执行持久化层操作与持久层技术进行整合过程中需要使用orm,jdbc.trx这三个jar包--dependency!--对象关系映射--groupIdorg.springframework/groupIdartifactIdspring-orm/artifactIdversion5.3.1/version/dependency!--spring测试相关--dependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion5.3.1/version/dependency!--junit测试--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency!--MySQL驱动--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.22/version/dependency!--数据源--dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.0.31/version/dependency/dependencies /project 接下来我们创建jdbc.properties: jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/ssm?serverTimezoneUTC jdbc.usernameroot jdbc.password123456 接下来我们进行配置spring的配置文件 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd !--引入jdbc.properties--context:property-placeholder locationclasspath:jdbc.properties/context:property-placeholderbean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName value${jdbc.driver}/propertyproperty nameurl value${jdbc.url}/propertyproperty nameusername value${jdbc.username}/propertyproperty namepassword value${jdbc.password}/property/beanbean classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/property/bean/beans 我们再创建一个tx-annotation配置文件如下所示 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://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!--引入jdbc.properties--context:property-placeholder locationclasspath:jdbc.properties/context:property-placeholderbean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName value${jdbc.driver}/propertyproperty nameurl value${jdbc.url}/propertyproperty nameusername value${jdbc.username}/propertyproperty namepassword value${jdbc.password}/property/beanbean classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/property/bean /beans 之后我们进行创建表 CREATE TABLE ‘t_book’ (’book_id‘ INT(11) NOT NULL AUTO_INCREMENT COMMENT 主键,‘book_name’ VARCHAR(20) DEFAULT NULL COMMENT 图书名称,’price‘ INT(11) DEFAULT NULL COMMENT 价格,‘stock’ INT(10) UNSIGNED DEFAULT NULL COMMENT 库存无符号,PRIMARY KEY (’book_id‘) ) ENGINEINNODB AUTO_INCREMENT3 DEFAULT CHARSETutf8; INSERT INTO ‘t_book’ (’book_id‘,‘book_name’,’price‘,‘stock’) VALUES (1,斗破苍穹,80,100),(2,斗罗大陆,50,100); CREATE TABLE ’t_user‘ (’user_id‘ INT(11) NOT NULL AUTO_INCREMENT COMMENT 主键,‘username’ VARCHAR(20) DEFAULT NULL COMMENT 用户名,’balance‘ INT(10) UNSIGNED DEFAULT NULL COMMENT 余额无符号,PRIMARY KEY(’user_id‘) ) ENGINEINNODB AUTO_INCREMENT2 DEFAULT CHARSETutf8; insert into ’t_user‘ (’user_id‘,‘username’,’balance‘) VALUES (1,admin,50); 我们进行运行之后如下所示 我们成功创建表之后,我们通过用户购买书的过程中通过余额不足来测试声明式事务。通过表可以看到余额为balance:50 完成表的创建之后我们进行示例如下所示 我们现进行创建service层controller层dao层 我们创建controller层如下所示 package com.rgf.spring.controller;import com.rgf.spring.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;Controller public class BookController {Autowiredprivate BookService bookService;public void buyBook(Integer userId,Integer bookId){bookService.buyBook(userId,bookId);} }之后我们进行创建service层首先创建接口如下 package com.rgf.spring.service;public interface BookService {void buyBook(Integer userId,Integer bookId); }我们创建service层的实现类如下所示 package com.rgf.spring.service;import com.rgf.spring.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; Transactional Service public class BookServiceImpl implements BookService{/*** 买书* param userId* param bookId**/Autowiredprivate BookDao bookDao;Overridepublic void buyBook(Integer userId, Integer bookId){//查询图书的价格Integer pricebookDao.getPriceByBookId(bookId);//更新图书的库存bookDao.updateStock(bookId);//更新用户的余额bookDao.updateBalance(userId,price);}}之后我们创建dao层 package com.rgf.spring.dao;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository;Repository public class BookDaoImpl implements BookDao{Autowiredprivate JdbcTemplate jdbcTemplate;Overridepublic Integer getPriceByBookId(Integer bookId) {String sqlSELECT price from t_book where book_id?;return jdbcTemplate.queryForObject(sql, Integer.class,bookId);}Overridepublic void updateStock(Integer bookId) {String sqlupdate t_book set stock-1 where book_id?;jdbcTemplate.update(sql,bookId);}Overridepublic void updateBalance(Integer userId, Integer price) {String sqlupdate t_user set balancebalance-? where user_id?;jdbcTemplate.update(sql,price,userId);} }package com.rgf.spring.dao;public interface BookDao {/*** 根据图书的id查询图书的价格* param bookId* return*/Integer getPriceByBookId(Integer bookId);/*** 更新图书的库存* param bookId*/void updateStock(Integer bookId);/*** 更新用户的余额* param userId* param price*/void updateBalance(Integer userId,Integer price); }我们在接口里面定义方法之后需要在实现类进行重写。 我们的自动装配如下所示 我们利用事务进行查看 package com.rgf.spring.dao;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository;Repository public class BookDaoImpl implements BookDao{Autowiredprivate JdbcTemplate jdbcTemplate;Overridepublic Integer getPriceByBookId(Integer bookId) {String sqlSELECT price from t_book where book_id?;return jdbcTemplate.queryForObject(sql, Integer.class,bookId);}Overridepublic void updateStock(Integer bookId) {String sqlupdate t_book set stock-1 where book_id?;jdbcTemplate.update(sql,bookId);}Overridepublic void updateBalance(Integer userId, Integer price) {String sqlupdate t_user set balancebalance-? where user_id?;jdbcTemplate.update(sql,price,userId);} }我们查看表的价格 我们进行测试如下用户1买一号位的书。 package com.rgf.spring.test;import com.rgf.spring.controller.BookController; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(classpath:tx-annotation.xml) public class TxByAnnotationTest {Autowiredprivate BookController bookController;Testpublic void testBuyBook(){bookController.buyBook(1,1);}}我们进行运行之后发现如下所示 在没有事务的情况下当我们进行测试的时候一个sql语句独占一个事务且自动提交。所以前两条SQL语句成功最后一条SQL语句失败的话失败的不会影响上面运行成功的。我们只有·将他们放在同一事务里面通过事务的代码去操作如果有异常则将整个事务都进行回滚出现要么都成功要么都失败的情况。 我们进行测试事务如下所示 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/context xmlns:txhttp://www.springframework.org/schema/txxsi:schemaLocationhttp://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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd!--扫描组件--context:component-scan base-packagecom.rgf.spring/context:component-scan!--引入jdbc.properties--context:property-placeholder locationclasspath:jdbc.properties/context:property-placeholderbean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName value${jdbc.driver}/propertyproperty nameurl value${jdbc.url}/propertyproperty nameusername value${jdbc.username}/propertyproperty namepassword value${jdbc.password}/property/beanbean classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/property/bean!--配置事务管理器--bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property/bean!--开启事务的注解驱动--!--为环绕通知--!--在Spring配置文件里面如果某一个属性的值为环绕型当前这个属性值就会变为灰色--!--将事务管理器里面的环绕通知作用于他的连接点--!--开启事务的注解驱动将使用Transactional注解所标识的方法或类中所有的方法使用事务进行管理transaction-manager属性设置事务管理器的id若事务管理器的bean的id默认为transactionManager,则该属性可以不写。--tx:annotation-driven transaction-managertransactionManager//beans 我们在service层的实现类里面进行设置事务管理器 package com.rgf.spring.service;import com.rgf.spring.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; Transactional Service public class BookServiceImpl implements BookService{/*** 买书* param userId* param bookId**/Autowiredprivate BookDao bookDao;Overridepublic void buyBook(Integer userId, Integer bookId){//查询图书的价格Integer pricebookDao.getPriceByBookId(bookId);//更新图书的库存bookDao.updateStock(bookId);//更新用户的余额bookDao.updateBalance(userId,price);}}我们进行测试如下所示 package com.rgf.spring.test;import com.rgf.spring.controller.BookController; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/*** 声明式事务的配置步骤* 1.在spring的配置文件中来配置事务管理器* 2.开启事务的注解驱动* 3.在需要被事务管理的方法上添加Transactional注解该方法就会被事务管理* Transactional注解标识的位置* 1.标识在方法上* 2.标识在类上则类中所有的方法都会被事务管理*/ RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(classpath:tx-annotation.xml) public class TxByAnnotationTest {Autowiredprivate BookController bookController;Testpublic void testBuyBook(){bookController.buyBook(1,1);}}事务属性 事务属性只读 介绍对一个查询操作来说如果我们把它设置成只读就能够明确告诉数据库这个操作不涉及写操作。这样数据库就能够针对查询操作来进行优化。 只有当前的事务中只有查询操作时才可以将事务进行设置为只读否则则会直接报错。 package com.rgf.spring.service;import com.rgf.spring.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; Service public class BookServiceImpl implements BookService{/*** 买书* param userId* param bookId**/Autowiredprivate BookDao bookDao;OverrideTransactional(readOnly true)public void buyBook(Integer userId, Integer bookId){//查询图书的价格Integer pricebookDao.getPriceByBookId(bookId);//更新图书的库存bookDao.updateStock(bookId);//更新用户的余额bookDao.updateBalance(userId,price);}}报错信息如下所示 事务属性超时 事务在执行过程中有可能因为遇到某些问题导致程序卡住从而长时间占用数据库资源而长时间占用资源大概率是因为程序运行出现了问题此时这个很可能出问题的程序应该被回滚撤销它已做的操作事务结束把资源让出来让其他正常程序可以执行。 我们进行测试如下所示 package com.rgf.spring.service;import com.rgf.spring.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;import java.util.concurrent.TimeUnit;Service public class BookServiceImpl implements BookService{/*** 买书* param userId* param bookId**/Autowiredprivate BookDao bookDao;OverrideTransactional(//readOnlytruetimeout 3)public void buyBook(Integer userId, Integer bookId){try{TimeUnit.SECONDS.sleep(5);}catch (InterruptedException e){e.printStackTrace();}//查询图书的价格Integer pricebookDao.getPriceByBookId(bookId);//更新图书的库存bookDao.updateStock(bookId);//更新用户的余额bookDao.updateBalance(userId,price);}}我们发现报错如下所示 即事务超时异常 。TransactionTimedOutException. 事务属性回滚策略 声明式事务默认只针对运行时异常回滚编译时异常不回滚 可以通过Transactional中相关属性设置回滚策略 rollbackFor属性需要设置一个Class类型的对象 rollbackForClassName属性需要设置一个字符串类型的全类名 noRollbackFor属性需要设置一个Class类型的对象 noRollbackForClassName属性需要设置一个字符串类型的全类名 package com.rgf.spring.service;import com.rgf.spring.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;import java.sql.SQLSyntaxErrorException; import java.util.concurrent.TimeUnit;Service public class BookServiceImpl implements BookService{/*** 买书* param userId* param bookId**/Autowiredprivate BookDao bookDao;OverrideTransactional(//readOnlytrue// timeout 3//noRollbackFor SQLSyntaxErrorException.classnoRollbackForClassNamejava.sql.SQLSyntaxErrorException.class)public void buyBook(Integer userId, Integer bookId){try{TimeUnit.SECONDS.sleep(5);}catch (InterruptedException e){e.printStackTrace();}//查询图书的价格Integer pricebookDao.getPriceByBookId(bookId);//更新图书的库存bookDao.updateStock(bookId);//更新用户的余额bookDao.updateBalance(userId,price);System.out.println(1/0);}}我们进行测试之后即会发现不会造成回滚。但是报错信息仍然会有。 事务属性事务隔离级别 数据库系统必须具有隔离并发运行各个事务的能力使他们不会相互影响避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别不同隔离级别对应不同的干扰程度隔离级别越高数据一致性就越好但并发性越弱。 隔离级别一共有四种 读未提交   READ UNCOMMITEDTransaction01读取Transaction02未提交的修改 读已提交  READ COMMITTED要求Transaction01只能读取Transaction02已提交的修改 可重复读   REPEAABLE READ确保Transaction01可以多次从一个字段中读取到相同的值即Transaction01执行期间禁止其他事务对这个字段进行更新 串行化  SERIALZABLE确保Transaction01可以多次从一个表中读取到相同的行在Transaction01执行期间禁止其他事务对这个表进行添加、更新、删除操作。可以避免任何并发问题。但性能十分低下。  各个隔离级别解决并发问题的能力见下表 隔离级别脏读不可重复读幻读READ UNCOMMITED读未提交有有有READ COMMITTED 读已提交无有有REPEAABLE READ可重复读无无有SERIALZABLE串行化无无无 各种数据库产品对事务隔离级别的支持程度 隔离级别OracleMySQLREAD UNCOMMITED读未提交noyesREAD COMMITTED 读已提交yes(默认yesREPEAABLE READ可重复读noyes(默认SERIALZABLE串行化yes(默认yes 我们设置隔离程度如下所示 package com.rgf.spring.service;import com.rgf.spring.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional;import java.sql.SQLSyntaxErrorException; import java.util.concurrent.TimeUnit;Service public class BookServiceImpl implements BookService{/*** 买书* param userId* param bookId**/Autowiredprivate BookDao bookDao;OverrideTransactional(//readOnlytrue// timeout 3//noRollbackFor SQLSyntaxErrorException.class//noRollbackForClassNamejava.sql.SQLSyntaxErrorException.classisolation Isolation.DEFAULT)public void buyBook(Integer userId, Integer bookId){try{TimeUnit.SECONDS.sleep(5);}catch (InterruptedException e){e.printStackTrace();}//查询图书的价格Integer pricebookDao.getPriceByBookId(bookId);//更新图书的库存bookDao.updateStock(bookId);//更新用户的余额bookDao.updateBalance(userId,price);System.out.println(1/0);}}事务的传播行为 我们在controller层里面进行调用如下所示 package com.rgf.spring.controller;import com.rgf.spring.service.BookService; import com.rgf.spring.service.CheckoutService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;Controller public class BookController {Autowiredprivate BookService bookService;private CheckoutService checkoutService;public void buyBook(Integer userId,Integer bookId){bookService.buyBook(userId,bookId);}public void checkout(Integer userId,Integer[] bookIds){checkoutService.checkout(userId,bookIds);} }我们在service层里面调用如下所示 先写接口 package com.rgf.spring.service;public interface CheckoutService {/*** 结账* param userId* param bookIds*/void checkout(Integer userId, Integer[] bookIds);}然后写接口调用的方法即为实现类 package com.rgf.spring.service;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;Service public class CheckoutServiceImpl implements CheckoutService{Autowiredprivate BookService bookService;OverrideTransactionalpublic void checkout(Integer userId, Integer[] bookIds) {for (Integer bookId:bookIds){bookService.buyBook(userId,bookId);}} }我们进行测试如下所示 package com.rgf.spring.test;import com.rgf.spring.controller.BookController; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/*** 声明式事务的配置步骤* 1.在spring的配置文件中来配置事务管理器* 2.开启事务的注解驱动* 3.在需要被事务管理的方法上添加Transactional注解该方法就会被事务管理* Transactional注解标识的位置* 1.标识在方法上* 2.标识在类上则类中所有的方法都会被事务管理*/ RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(classpath:tx-annotation.xml) public class TxByAnnotationTest {Autowiredprivate BookController bookController;Testpublic void testBuyBook(){bookController.buyBook(1,1);}Testpublic void testCheckoutBook(){bookController.checkout(1,new Integer[]{1,2});}}测试之后出现报错信息SQLStateSQLExceptionTranslator.java 我们进行刷新之后发现书的数量没有发生变化。此即为第二本书买不了的话当前的所有书都无法进行购买。当数据出错的时候回滚的是整个结账的操作。 我们将买书操作的事务的属性设置如下所示 package com.rgf.spring.service;import com.rgf.spring.dao.BookDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional;import java.sql.SQLSyntaxErrorException; import java.util.concurrent.TimeUnit;Service public class BookServiceImpl implements BookService{/*** 买书* param userId* param bookId**/Autowiredprivate BookDao bookDao;OverrideTransactional(//readOnlytrue// timeout 3//noRollbackFor SQLSyntaxErrorException.class//noRollbackForClassNamejava.sql.SQLSyntaxErrorException.class// isolation Isolation.DEFAULTpropagation Propagation.REQUIRES_NEW)public void buyBook(Integer userId, Integer bookId){try{TimeUnit.SECONDS.sleep(5);}catch (InterruptedException e){e.printStackTrace();}//查询图书的价格Integer pricebookDao.getPriceByBookId(bookId);//更新图书的库存bookDao.updateStock(bookId);//更新用户的余额bookDao.updateBalance(userId,price);System.out.println(1/0);}}此时用的是买书自身的事务即会将第一本书购买成功第二本购买不成功。可以通过Transaction中的propagation属性设置事务传播行为。 Transactional(propagation Propagation.REQUIRED)默认情况。使用调用者的事务 Transactional(propagation Propagation.REQUIRES_NEW)被调用者被调用的方法本身的事务 基于XML的声明式事务  我们的配置文件如下所示 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/context xmlns:txhttp://www.springframework.org/schema/txxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd!--扫描组件--context:component-scan base-packagecom.rgf.spring/context:component-scan!--引入jdbc.properties--context:property-placeholder locationclasspath:jdbc.properties/context:property-placeholderbean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName value${jdbc.driver}/propertyproperty nameurl value${jdbc.url}/propertyproperty nameusername value${jdbc.username}/propertyproperty namepassword value${jdbc.password}/property/beanbean classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/property/bean!--配置事务管理器--bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property/bean!--配置事务通知--tx:advice idtx transaction-managertransactionManagertx:attributestx:method namebuyBook //tx:attributes/tx:adviceaop:configaop:advisor advice-reftx pointcutexecution(* com.rgf.spring.service.*.*(..))/aop:advisor/aop:config/beans 我们的测试代码如下所示 package com.rgf.spring.test;import com.rgf.spring.controller.BookController; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/*** 声明式事务的配置步骤* 1.在spring的配置文件中来配置事务管理器* 2.开启事务的注解驱动* 3.在需要被事务管理的方法上添加Transactional注解该方法就会被事务管理* Transactional注解标识的位置* 1.标识在方法上* 2.标识在类上则类中所有的方法都会被事务管理*/ RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(classpath:tx-xml.xml) public class TxByXMLTest {Autowiredprivate BookController bookController;Testpublic void testBuyBook(){bookController.buyBook(1,1);}Testpublic void testCheckoutBook(){bookController.checkout(1,new Integer[]{1,2});}}我们进行测试的时候发现出现如下问题 我们发现缺少jar包。我们来进行添加 !--spring-aspects会帮我们传递过来aspectjweaver--dependencygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactIdversion5.3.1/version/dependency 我们进行导入依赖。 完成之后我们继续测试即可。 注意基于xml实现的声明式事务必须引入aspectj的依赖 我们可以用*默认为全部方法 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/context xmlns:txhttp://www.springframework.org/schema/txxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd!--扫描组件--context:component-scan base-packagecom.rgf.spring/context:component-scan!--引入jdbc.properties--context:property-placeholder locationclasspath:jdbc.properties/context:property-placeholderbean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName value${jdbc.driver}/propertyproperty nameurl value${jdbc.url}/propertyproperty nameusername value${jdbc.username}/propertyproperty namepassword value${jdbc.password}/property/beanbean classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/property/bean!--配置事务管理器--bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property/bean!--配置事务通知--tx:advice idtx transaction-managertransactionManagertx:attributestx:method namebuyBook /tx:method name*/tx:method nameget* read-onlytrue/tx:method namequery* read-onlytrue/tx:method namefind* read-onlytrue/!--read-only属性设置只读属性--!--rollback-for属性设置回滚的异常--!--no-rollback-for属性设置不回滚的异常--!--isolation属性设置事务的隔离级别--!--timeout属性设置事务的超时属性--!--propagation属性设置事务的传播行为--tx:method namesave* read-onlyfalse rollback-forjava.lang.Exception propagationREQUIRES_NEW/tx:method nameupdate* read-onlyfalse rollback-forjava.lang.Exception propagationREQUIRES_NEW/tx:method namedelete read-onlyfalse rollback-forjava.lang.Exception propagationREQUIRES_NEW//tx:attributes/tx:adviceaop:configaop:advisor advice-reftx pointcutexecution(* com.rgf.spring.service.*.*(..))/aop:advisor/aop:config/beans
http://www.dnsts.com.cn/news/39001.html

相关文章:

  • 深圳有没有可以做家教的网站环球军事最新消息
  • discuz 做视频网站学会网站建设目的
  • app应用网站html5模板下载北海 做网站 英文
  • 做网站意义制作网页一般需要兼容哪些软件
  • 如何给网站配色公众号开发公司排行榜
  • 怎么让自己做的网站让别人看到深圳华鑫峰网站建设
  • 青岛鑫隆建设集团网站wordpress comments 时间为什么是utc时间
  • asp.net网站不能上传图片移动端是指手机吗
  • 平谷微网站建设东胜做网站
  • 怎么建立一个自己的网站泉州专业网站建设费用
  • 网站建设的完整流程图中国有几大网站
  • 一个公司如何把网站做好seo168小视频
  • 贵州安顺住房城乡建设网站公司网站模板设计
  • 找人做效果图去什么网站装企网站建设
  • 湖南响应式网站方案外贸型网站的特点
  • 网站制作学习自己怎么创建免费网站吗
  • wordpress的页面布局seo优化几个关键词
  • 雄安优秀网站建设公司淘宝宝贝排名查询
  • 广东民航机场建设有限公司网站帝国做的网站怎么上传
  • 打开网站弹出qq江苏省城乡和建设厅网站首页
  • 网站数据库要多大专业的深圳网站建设
  • 网站站点的建立成都芯片设计公司
  • 源码网站排行好看英文网站
  • 如何做班级网站网站改版方案ppt
  • 谷歌网站推广销售我的世界做墙纸网站
  • 郑州做网站找绝唯科技房产信息网510
  • 益阳网站开发公司各大网站做推广广告
  • 成县建设局网站企业信用信息公示系统年报怎么填
  • 安徽省住房城乡建设厅网站选择适合的配色方案和风格
  • 手机网站费用网站开发环境搭建