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

丽水企业网站建设莲塘网站建设

丽水企业网站建设,莲塘网站建设,wordpress页面显示分类目录,给公司做个网站多少钱Spring整合MyBatis 搭建环境 我们知道使用MyBatis时需要写大量创建SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession等对象的代码#xff0c;而Spring的作用是帮助我们创建和管理对象#xff0c;所以我们可以使用Spring整合MyBatis#xff0c;简化MyBatis开发。 …Spring整合MyBatis 搭建环境 我们知道使用MyBatis时需要写大量创建SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession等对象的代码而Spring的作用是帮助我们创建和管理对象所以我们可以使用Spring整合MyBatis简化MyBatis开发。 创建maven项目引入依赖。 dependencies!-- mybatis --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.7/version/dependency!-- mysql驱动包 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.26/version/dependency!-- spring --dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.13/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-tx/artifactIdversion5.3.13/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion5.3.13/version/dependency!-- MyBatis与Spring的整合包该包可以让Spring创建MyBatis的对象 --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion2.0.6/version/dependency /dependencies编写配置文件 编写数据库配置文件db.properties jdbc.driverClassNamecom.mysql.jdbc.Driver jdbc.urljdbc:mysql:///student jdbc.usernameroot jdbc.passwordroot创建MyBatis配置文件SqlMapConfig.xml数据源、扫描接口都交由Spring管理不需要在MyBatis配置文件中设置。 ?xml version1.0 encodingUTF-8? !DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtd configuration/configuration创建Spring配置文件applicationContext.xml ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:contexthttp://www.springframework.org/schema/contextxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!--配置扫描包--context:component-scan base-packagecom.Spring/!--读取配置文件--context:property-placeholder locationclasspath:db.properties/!--创建druid数据源对象--bean namedataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName value${jdbc.driverClassName}/property nameurl value${jdbc.url}/property nameusername value${jdbc.username}/property namepassword value${jdbc.password}//bean!-- Spring创建封装过的SqlSessionFactory --bean namesqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBeanproperty namedataSource refdataSource//bean!-- Spring创建封装过的SqlSession --bean namesqlSession classorg.mybatis.spring.SqlSessionTemplateconstructor-arg namesqlSessionFactory refsqlSessionFactory//bean/beans准备数据库和实体类 准备数据库 CREATE DATABASE student; USE student; DROP TABLE IF EXISTS student; CREATE TABLE student (id int(11) NOT NULL AUTO_INCREMENT,name varchar(255) DEFAULT NULL,sex varchar(10) DEFAULT NULL,address varchar(255) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT3 DEFAULT CHARSETutf8;insert into student(id,name,sex,address) values (1,李四,男,北京),(2,张三,女,北京);准备实体类 public class Student {private int id;private String name;private String sex;private String address;// 省略构造方法/getter/setter/tostring }编写持久层接口和service类 编写持久层接口 Repository public interface StudentDao {//查询所有学生Select(select * from student)ListStudent findAll();//添加学生Insert(insert into student values (null,#{name},#{sex},#{address}))void add(Student student); }编写service类 Service public class StudentService {//SqlSession对象Autowiredprivate SqlSessionTemplate sqlSession;// 使用SqlSession获取代理对象public ListStudent findAllStudent(){StudentDao studentDao sqlSession.getMapper(StudentDao.class);return studentDao.findAll();} }Spring整合Junit进行单元测试 之前进行单元测试时都需要手动创建Spring容器能否在测试时让Spring自动创建容器呢 引入Junit和Spring整合Junit依赖 !-- junit,如果Spring5整合junit则junit版本至少在4.12以上 -- dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope /dependency !-- spring整合测试模块 -- dependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion5.3.13/version /dependency编写测试类 // JUnit使用Spring方式运行代码即自动创建spring容器。 RunWith(SpringJUnit4ClassRunner.class) // 告知创建spring容器时读取哪个配置类或配置文件 // 配置类写法ContextConfiguration(classes配置类.class) ContextConfiguration(locationsclasspath:applicationContext.xml) public class StudentServiceTest {Autowiredprivate StudentService studentService;Testpublic void testFindAll(){ListStudent allStudent studentService.findAllStudent();allStudent.forEach(System.out::println);} }注使用SqlSessionTemplate创建代理对象还是需要注册接口或者映射文件的。 在MyBatis配置文件注册接口 configurationmappersmapper classcom.Spring.dao.StudentDao/mapper/mappers /configuration创建sqlSessionFactory时指定MyBatis配置文件 !-- 创建Spring封装过的SqlSessionFactory -- bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBeanproperty namedataSource refdataSource/propertyproperty nameconfigLocation valueclasspath:SqlMapConfig.xml/property /bean自动创建代理对象 Spring提供了MapperScannerConfigurer对象该对象可以自动扫描包创建代理对象并将代理对象放入容器中此时不需要使用SqlSession手动创建代理对象。 创建MapperScannerConfigurer对象 !-- 该对象可以自动扫描持久层接口并为接口创建代理对象 -- bean idmapperScanner classorg.mybatis.spring.mapper.MapperScannerConfigurer!-- 配置扫描的接口包 --property namebasePackage valuecom.Spring.dao/property /beanService类直接使用代理对象即可 Service public class StudentService {// 直接注入代理对象Autowiredprivate StudentDao studentDao;// 直接使用代理对象public void addStudent(Student student){studentDao.add(student);} }测试 RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(locationsclasspath:applicationContext.xml) public class StudentServiceTest {Autowiredprivate StudentService studentService;Testpublic void testAddStudent(){Student student new Student(郭家旗,男,上海);studentService.addStudent(student);} }SpringAOP AOP简介 AOP的全称是Aspect Oriented Programming即面向切面编程。是实现功能统一维护的一种技术它将业务逻辑的各个部分进行隔离使开发人员在编写业务逻辑时可以专心于核心业务从而提高了开发效率。 作用在不修改源码的基础上对已有方法进行增强。实现原理动态代理技术。优势减少重复代码、提高开发效率、维护方便应用场景事务处理、日志管理、权限控制、异常处理等方面。 AOP相关术语 为了更好地理解AOP就需要对AOP的相关术语有一些了解 名称说明Joinpoint连接点指能被拦截到的点在Spring中只有方法能被拦截。Pointcut切点指要对哪些连接点进行拦截即被增强的方法。Advice通知指拦截后要做的事情即切点被拦截后执行的方法。Aspect切面切点通知称为切面Target目标被代理的对象Proxy代理代理对象Weaving织入生成代理对象的过程 AOP入门 AspectJ是一个基于Java语言的AOP框架在Spring框架中建议使用AspectJ实现AOP。 接下来我们写一个AOP入门案例dao层的每个方法结束后都可以打印一条日志 引入依赖 !-- spring -- dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.13/version /dependency !-- AspectJ -- dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.8.7/version /dependency !-- junit -- dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope /dependency编写连接点 Repository public class UserDao {public void add(){System.out.println(用户新增);}public void delete(){System.out.println(用户删除);}public void update(){System.out.println(用户修改);} }编写通知类 public class MyAspectJAdvice {// 后置通知public void myAfterReturning() {System.out.println(打印日志...);} }配置切面 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdcontext:component-scan base-packagecom.Spring/context:component-scan!-- 通知对象 --bean idmyAspectJAdvice classcom.Spring.advice.MyAspectAdvice/bean!-- 配置AOP --aop:config!-- 配置切面 --aop:aspect refmyAspectJAdvice!-- 配置切点 --aop:pointcut idmyPointcut expressionexecution(* com.Spring.dao.UserDao.*(..))/!-- 配置通知 --aop:after-returning methodmyAfterReturning pointcut-refmyPointcut//aop:aspect/aop:config /beans测试 public class UserDaoTest {Testpublic void testAdd(){ApplicationContext ac new ClassPathXmlApplicationContext(bean.xml);UserDao userDao (UserDao) ac.getBean(userDao);userDao.add();}Testpublic void testDelete(){ApplicationContext ac new ClassPathXmlApplicationContext(bean.xml);UserDao userDao (UserDao) ac.getBean(userDao);userDao.delete();}Testpublic void testUpdate(){ApplicationContext ac new ClassPathXmlApplicationContext(bean.xml);UserDao userDao (UserDao) ac.getBean(userDao);userDao.update();} }通知类型 AOP有以下几种常用的通知类型 通知类型描述前置通知在方法执行前添加功能后置通知在方法正常执行后添加功能异常通知在方法抛出异常后添加功能最终通知无论方法是否抛出异常都会执行该通知环绕通知在方法执行前后添加功能 编写通知方法 // 通知类 public class MyAspectAdvice {// 后置通知public void myAfterReturning(JoinPoint joinPoint) {System.out.println(切点方法名 joinPoint.getSignature().getName());System.out.println(目标对象 joinPoint.getTarget());System.out.println(打印日志 joinPoint.getSignature().getName() 方法被执行了);}// 前置通知public void myBefore() {System.out.println(前置通知...);}// 异常通知public void myAfterThrowing(Exception ex) {System.out.println(异常通知...);System.err.println(ex.getMessage());}// 最终通知public void myAfter() {System.out.println(最终通知);}// 环绕通知public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println(环绕前);Object obj proceedingJoinPoint.proceed(); // 执行方法System.out.println(环绕后);return obj;} } 配置切面 !-- 配置AOP -- aop:config!-- 配置切面 --aop:aspect refmyAspectJAdvice!-- 配置切点 --aop:pointcut idmyPointcut expressionexecution(* com.Spring.dao.UserDao.*(..))/!-- 前置通知 --aop:before methodmyBefore pointcut-refmyPointcut/aop:before!-- 后置通知 --aop:after-returning methodmyAfterReturning pointcut-refmyPointcut/!-- 异常通知 --aop:after-throwing methodmyAfterThrowing pointcut-refmyPointcut throwingex/!-- 最终通知 --aop:after methodmyAfter pointcut-refmyPointcut/aop:after!-- 环绕通知 --aop:around methodmyAround pointcut-refmyPointcut/aop:around/aop:aspect /aop:config 切点表达式 使用AspectJ需要使用切点表达式配置切点位置写法如下 标准写法访问修饰符 返回值 包名.类名.方法名(参数列表)访问修饰符可以省略。返回值使用*代表任意类型。包名使用*表示任意包多级包结构要写多个*使用*..表示任意包结构类名和方法名都可以用*实现通配。参数列表 基本数据类型直接写类型引用类型写包名.类名*表示匹配一个任意类型参数..表示匹配任意类型任意个数的参数 全通配* *..*.*(..) 多切面配置 我们可以为切点配置多个通知形成多切面比如希望dao层的每个方法结束后都可以打印日志并发送邮件 编写发送邮件的通知 public class MyAspectJAdvice2 {// 后置通知public void myAfterReturning(JoinPoint joinPoint) {System.out.println(发送邮件);} }配置切面 !-- 通知对象 -- bean idmyAspectJAdvice classcom.Spring.advice.MyAspectAdvice/bean bean idmyAspectJAdvice2 classcom.Spring.advice.MyAspectAdvice2/bean!-- 配置AOP -- aop:config!-- 配置切面 --aop:aspect refmyAspectJAdvice!-- 配置切点 --aop:pointcut idmyPointcut expressionexecution(* *..*.*(..))/!-- 后置通知 --aop:after-returning methodmyAfterReturning pointcut-refmyPointcut//aop:aspectaop:aspect refmyAspectJAdvice2aop:pointcut idmyPointcut2 expressionexecution(* com.Spring.dao.UserDao.*(..))/aop:after-returning methodmyAfterReturning pointcut-refmyPointcut2//aop:aspect /aop:config注解配置AOP Spring可以使用注解代替配置文件配置切面 在xml中开启AOP注解支持 !-- 开启注解配置Aop -- aop:aspectj-autoproxy/aop:aspectj-autoproxy在通知类上方加入注解Aspect 在通知方法上方加入注解Before/AfterReturning/AfterThrowing/After/Around Aspect Component public class MyAspectAdvice {// 后置通知AfterReturning(execution(* com.Spring.dao.UserDao.*(..)))public void myAfterReturning(JoinPoint joinPoint) {System.out.println(切点方法名 joinPoint.getSignature().getName());System.out.println(目标对象 joinPoint.getTarget());System.out.println(打印日志 joinPoint.getSignature().getName() 方法被执行了);}// 前置通知Before(execution(* com.Spring.dao.UserDao.*(..)))public void myBefore() {System.out.println(前置通知...);}// 异常通知AfterThrowing(value execution(* com.Spring.dao.UserDao.*(..)),throwing ex)public void myAfterThrowing(Exception ex) {System.out.println(异常通知...);System.err.println(ex.getMessage());}// 最终通知After(execution(* com.Spring.dao.UserDao.*(..)))public void myAfter() {System.out.println(最终通知);}// 环绕通知Around(execution(* com.Spring.dao.UserDao.*(..)))public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println(环绕前);Object obj proceedingJoinPoint.proceed(); // 执行方法System.out.println(环绕后);return obj;} }测试 Test public void testAdd2(){ApplicationContext ac new ClassPathXmlApplicationContext(bean1.xml);UserDao userDao (UserDao) ac.getBean(userDao);userDao.update(); }如何为一个类下的所有方法统一配置切点 在通知类中添加方法配置切点 Pointcut(execution(* com.Spring.dao.UserDao.*(..))) public void pointCut(){}在通知方法上使用定义好的切点 Before(pointCut()) public void myBefore(JoinPoint joinPoint) {System.out.println(前置通知...); }AfterReturning(“pointCut()”) public void myAfterReturning(JoinPoint joinPoint) { System.out.println(“后置通知…”); } 配置类如何代替xml中AOP注解支持 在配置类上方添加EnableAspectJAutoProxy即可 Configuration ComponentScan(com.Spring) EnableAspectJAutoProxy public class SpringConfig {}原生Spring实现AOP 除了AspectJSpring支持原生方式实现AOP。 引入依赖 !-- AOP -- dependencygroupIdorg.springframework/groupIdartifactIdspring-aop/artifactIdversion5.3.13/version /dependency编写通知类 // Spring原生Aop的通知类 public class SpringAop implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice, MethodInterceptor {/*** 前置通知* param method 目标方法* param args 目标方法的参数列表* param target 目标对象* throws Throwable*/Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(前置通知);}/*** 后置通知* param returnValue 目标方法的返回值* param method 目标方法* param args 目标方法的参数列表* param target 目标对象* throws Throwable*/Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println(后置通知);}/*** 环绕通知* param invocation 目标方法* return* throws Throwable*/Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println(环绕前);Object proceed invocation.proceed();System.out.println(环绕后);return proceed;}/*** 异常通知* param ex 异常对象*/public void afterThrowing(Exception ex){System.out.println(发生异常了);} }Spring原生方式实现AOP时只支持四种通知类型 通知类型实现接口前置通知MethodBeforeAdvice后置通知AfterReturningAdvice异常通知ThrowsAdvice环绕通知MethodInterceptor 编写配置类 !-- 通知对象 -- bean idspringAop classcom.Spring.advice.SpringAop/bean!-- 配置代理对象 -- bean iduserDaoProxy classorg.springframework.aop.framework.ProxyFactoryBean!-- 配置目标对象 --property nametarget refuserDao/property!-- 配置通知 --property nameinterceptorNameslistvaluespringAop/value/list/property!-- 代理对象的生成方式 true使用CGLib false使用原生JDK生成--property nameproxyTargetClass valuetrue/property /bean编写测试类 public class UserDaoTest2 {Testpublic void testAdd(){ApplicationContext ac new ClassPathXmlApplicationContext(bean2.xml);UserDao userDao (UserDao) ac.getBean(userDaoProxy); // 获取的是代理对象userDao.update();} }SchemaBased实现AOP SchemaBased(基础模式)配置方式是指使用Spring原生方式定义通知而使用AspectJ框架配置切面。 编写通知类 public class SpringAop implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice, MethodInterceptor {/*** 前置通知* param method 目标方法* param args 目标方法的参数列表* param target 目标对象* throws Throwable*/Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(前置通知);}/*** 后置通知* param returnValue 目标方法的返回值* param method 目标方法* param args 目标方法的参数列表* param target 目标对象* throws Throwable*/Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println(后置通知);}/*** 环绕通知* param invocation 目标方法* return* throws Throwable*/Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println(环绕前);Object proceed invocation.proceed();System.out.println(环绕后);return proceed;}/*** 异常通知* param ex 异常对象*/public void afterThrowing(Exception ex){System.out.println(发生异常了);} }配置切面 !-- 通知对象 -- bean idspringAop2 classcom.Spring.aop.SpringAop2/!-- 配置切面 -- aop:config!-- 配置切点--aop:pointcut idmyPointcut expressionexecution(* com.Spring.dao.UserDao.*(..))/!-- 配置切面advice-ref通知对象 pointcut-ref切点 --aop:advisor advice-refspringAop2 pointcut-refmyPointcut/ /aop:config测试 Test public void t6(){ApplicationContext ac new ClassPathXmlApplicationContext(aop3.xml);UserDao userDao (UserDao) ac.getBean(userDao);userDao.add(); }Spring事务 事务简介 事务不可分割的原子操作。即一系列的操作要么同时成功要么同时失败。 开发过程中事务管理一般在service层service层中可能会操作多次数据库这些操作是不可分割的。否则当程序报错时可能会造成数据异常。 如张三给李四转账时需要两次操作数据库张三存款减少、李四存款增加。如果这两次数据库操作间出现异常则会造成数据错误。 准备数据库 CREATE DATABASE spring ; USE spring; DROP TABLE IF EXISTS account;CREATE TABLE account (id int(11) NOT NULL AUTO_INCREMENT,username varchar(255) DEFAULT NULL,balance double DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT3 DEFAULT CHARSETutf8;insert into account(id,username,balance) values (1,张三,1000),(2,李四,1000); 创建maven项目引入依赖 dependencies!-- mybatis --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.7/version/dependency!-- mysql驱动包 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.26/version/dependency!-- druid连接池 --dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.2.8/version/dependency!-- spring --dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.13/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-tx/artifactIdversion5.3.13/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion5.3.13/version/dependency!-- MyBatis与Spring的整合包该包可以让Spring创建MyBatis的对象 --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion2.0.6/version/dependency!-- junit,如果Spring5整合junit则junit版本至少在4.12以上 --dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency!-- spring整合测试模块 --dependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion5.3.13/versionscopetest/scope/dependency /dependencies 创建配置文件 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:contexthttp://www.springframework.org/schema/contextxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!-- 包扫描 --context:component-scan base-packagecom.Spring/context:component-scan!-- 创建druid数据源对象 --bean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName valuecom.mysql.jdbc.Driver/propertyproperty nameurl valuejdbc:mysql:///spring/propertyproperty nameusername valueroot/propertyproperty namepassword valueroot/property/beanbean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBeanproperty namedataSource refdataSource/property/beanbean idmapperScanner classorg.mybatis.spring.mapper.MapperScannerConfigurerproperty namebasePackage valuecom.Spring.dao/property/bean /beans 编写Java代码 // 账户 public class Account {private int id; // 账号private String username; // 用户名private double balance; // 余额// 省略getter/setter/tostring/构造方法 }Repository public interface AccountDao {// 根据id查找用户Select(select * from account where id #{id})Account findById(int id);// 修改用户Update(update account set balance #{balance} where id #{id})void update(Account account); }Service public class AccountService {Autowiredprivate AccountDao accountDao;/*** 转账* param id1 转出人id* param id2 转入人id* param price 金额*/public void transfer(int id1, int id2, double price) {// 转出人减少余额Account account1 accountDao.findById(id1);account1.setBalance(account1.getBalance()-price);accountDao.update(account1);int i 1/0; // 模拟程序出错// 转入人增加余额Account account2 accountDao.findById(id2);account2.setBalance(account2.getBalance()price);accountDao.update(account2);} } 测试转账 RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(locationsclasspath:applicationContext.xml) public class AccountServiceTest {Autowiredprivate AccountService accountService;Testpublic void testTransfer(){accountService.transfer(1,2,500);} } 此时没有事务管理会造成张三的余额减少而李四的余额并没有增加。所以事务处理位于业务层即一个service方法是不能分割的。 Spring事务管理方案 在service层手动添加事务可以解决该问题 Autowired private SqlSessionTemplate sqlSession;public void transfer(int id1, int id2, double price) {try{// account1修改余额Account account1 accountDao.findById(id1);account1.setBalance(account1.getBalance()-price);accountDao.update(account1);int i 1/0; // 模拟转账出错// account2修改余额Account account2 accountDao.findById(id2);account2.setBalance(account2.getBalance()price);accountDao.update(account2); sqlSession.commit();}catch(Exception ex){sqlSession.rollback();} }但在Spring管理下不允许手动提交和回滚事务。此时我们需要使用Spring的事务管理方案在Spring框架中提供了两种事务管理方案 编程式事务通过编写代码实现事务管理。声明式事务基于AOP技术实现事务管理。 在Spring框架中编程式事务管理很少使用我们对声明式事务管理进行详细学习。 Spring的声明式事务管理在底层采用了AOP技术其最大的优点在于无需通过编程的方式管理事务只需要在配置文件中进行相关的规则声明就可以将事务规则应用到业务逻辑中。 使用AOP技术为service方法添加如下通知 Spring事务管理器 Spring依赖事务管理器进行事务管理事务管理器即一个通知类我们为该通知类设置切点为service层方法即可完成事务自动管理。由于不同技术操作数据库进行事务操作的方法不同。如JDBC提交事务是connection.commit()MyBatis提交事务是sqlSession.commit()所以Spring提供了多个事务管理器。 事务管理器名称作用org.springframework.jdbc.datasource.DataSourceTransactionManager针对JDBC技术提供的事务管理器。适用于JDBC和MyBatis。org.springframework.orm.hibernate3.HibernateTransactionManager针对于Hibernate框架提供的事务管理器。适用于Hibernate框架。org.springframework.orm.jpa.JpaTransactionManager针对于JPA技术提供的事务管理器。适用于JPA技术。org.springframework.transaction.jta.JtaTransactionManager跨越了多个事务管理源。适用在两个或者是多个不同的数据源中实现事务控制。 我们使用MyBatis操作数据库接下来使用DataSourceTransactionManager进行事务管理。 引入依赖 !-- 事务管理 -- dependencygroupIdorg.springframework/groupIdartifactIdspring-tx/artifactIdversion5.3.13/version /dependency !-- AspectJ -- dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.8.7/version /dependency在配置文件中引入约束 xmlns:aophttp://www.springframework.org/schema/aop xmlns:txhttp://www.springframework.org/schema/txhttp://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 进行事务配置 !-- 事务管理器 -- bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property /bean!-- 进行事务相关配置 -- tx:advice id txAdvicetx:attributestx:method name*//tx:attributes /tx:advice!-- 配置切面 -- aop:config!-- 配置切点 --aop:pointcut idpointcut expressionexecution(* com.Spring.service.*.*(..))/!-- 配置通知 --aop:advisor advice-reftxAdvice pointcut-refpointcut/aop:advisor /aop:config 事务控制的API Spring进行事务控制的功能是由三个接口提供的这三个接口是Spring实现的在开发中我们很少使用到只需要了解他们的作用即可 PlatformTransactionManager接口 PlatformTransactionManager是Spring提供的事务管理器接口所有事务管理器都实现了该接口。该接口中提供了三个事务操作方法 TransactionStatus getTransactionTransactionDefinition definition获取事务状态信息。void commitTransactionStatus status事务提交void rollbackTransactionStatus status事务回滚 TransactionDefinition接口 TransactionDefinition是事务的定义信息对象它有如下方法 String getName()获取事务对象名称。int getIsolationLevel()获取事务的隔离级别。int getPropagationBehavior()获取事务的传播行为。int getTimeout()获取事务的超时时间。boolean isReadOnly()获取事务是否只读。 TransactionStatus接口 TransactionStatus是事务的状态接口它描述了某一时间点上事务的状态信息。它有如下方法 void flush() 刷新事务boolean hasSavepoint() 获取是否存在保存点boolean isCompleted() 获取事务是否完成boolean isNewTransaction() 获取是否是新事务boolean isRollbackOnly() 获取是否回滚void setRollbackOnly() 设置事务回滚 事务的相关配置 在tx:advice中可以进行事务的相关配置 tx:advice idtxAdvicetx:attributestx:method name*/tx:method namefind* read-onlytrue//tx:attributes /tx:advicetx:method中的属性 name指定配置的方法。*表示所有方法find*表示所有以find开头的方法。read-only是否是只读事务只读事务不存在数据的修改数据库将会为只读事务提供一些优化手段会对性能有一定提升建议在查询中开启只读事务。timeout指定超时时间在限定的时间内不能完成所有操作就会抛异常。默认永不超时rollback-for指定某个异常事务回滚其他异常不回滚。默认所有异常回滚。no-rollback-for指定某个异常不回滚其他异常回滚。默认所有异常回滚。propagation事务的传播行为isolation事务的隔离级别 事务的传播行为 事务传播行为是指多个含有事务的方法相互调用时事务如何在这些方法间传播。 如果在service层的方法中调用了其他的service方法假设每次执行service方法都要开启事务此时就无法保证外层方法和内层方法处于同一个事务当中。 // method1的所有方法在同一个事务中 public void method1(){// 此时会开启一个新事务这就无法保证method1()中所有的代码是在同一个事务中method2();System.out.println(method1); }public void method2(){System.out.println(method2); }事务的传播特性就是解决这个问题的Spring帮助我们将外层方法和内层方法放入同一事务中。 传播行为介绍REQUIRED默认。支持当前事务如果当前没有事务就新建一个事务。这是最常见的选择。SUPPORTS支持当前事务如果当前没有事务就以非事务方式执行。MANDATORY支持当前事务如果当前没有事务就抛出异常。REQUIRES_NEW新建事务如果当前存在事务把当前事务挂起。NOT_SUPPORTED以非事务方式执行操作如果当前存在事务就把当前事务挂起。NEVER以非事务方式执行如果当前存在事务则抛出异常。NESTED必须在事务状态下执行如果没有事务则新建事务如果当前有事务则创建一个嵌套事务 事务的隔离级别 事务隔离级别反映事务提交并发访问时的处理态度隔离级别越高数据出问题的可能性越低但效率也会越低。 隔离级别脏读不可重复读幻读READ_UNCOMMITTED读取未提交内容YesYesYesREAD_COMMITTED读取提交内容NoYesYesREPEATABLE_READ重复读NoNoYesSERIALIZABLE可串行化NoNoNo 如果设置为DEFAULT会使用数据库的隔离级别。 SqlServer , Oracle默认的事务隔离级别是READ_COMMITTEDMysql的默认隔离级别是REPEATABLE_READ 注解配置声明式事务 Spring支持使用注解配置声明式事务。用法如下 注册事务注解驱动 !-- 注册事务注解驱动 -- tx:annotation-driven transaction-managertransactionManager/tx:annotation-driven在需要事务支持的方法或类上加Transactional Service // 作用于类上时该类的所有public方法将都具有该类型的事务属性 Transactional(propagation Propagation.REQUIRED,isolation Isolation.DEFAULT) public class AccountService {Autowiredprivate AccountDao accountDao;/*** 转账* param id1 转出人id* param id2 转入人id* param price 金额*/// 作用于方法上时该方法将都具有该类型的事务属性Transactional(propagation Propagation.REQUIRED,isolation Isolation.DEFAULT)public void transfer(int id1, int id2, double price) {// account1修改余额Account account1 accountDao.findById(id1);account1.setBalance(account1.getBalance()-price);accountDao.update(account1);int i 1/0; // 模拟转账出错// account2修改余额Account account2 accountDao.findById(id2);account2.setBalance(account2.getBalance()price);accountDao.update(account2);} }配置类代替xml中的注解事务支持在配置类上方写EnableTranscationManagement Configuration ComponentScan(com.Spring) EnableTransactionManagement public class SpringConfig {Beanpublic DataSource getDataSource(){DruidDataSource druidDataSource new DruidDataSource();druidDataSource.setDriverClassName(com.mysql.jdbc.Driver);druidDataSource.setUrl(jdbc:mysql:///spring);druidDataSource.setUsername(root);druidDataSource.setPassword(root);return druidDataSource;}Beanpublic SqlSessionFactoryBean getSqlSession(DataSource dataSource){SqlSessionFactoryBean sqlSessionFactoryBean new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);return sqlSessionFactoryBean;}Beanpublic MapperScannerConfigurer getMapperScanner(){MapperScannerConfigurer mapperScannerConfigurer new MapperScannerConfigurer();mapperScannerConfigurer.setBasePackage(com.Spring.dao);return mapperScannerConfigurer;}Beanpublic DataSourceTransactionManager getTransactionManager(DataSource dataSource){DataSourceTransactionManager dataSourceTransactionManager new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;} }
http://www.sadfv.cn/news/136620/

相关文章:

  • wordpress页面回收站位置长沙seo在哪
  • 网站开发雇佣平台百度网页制作html
  • html5 购物网站事业单位网站登录模板
  • 汽车网站制作策划方案公司网站建设费属于什么费用
  • 咸阳网站建设公司哪家好wordpress 不收录设置
  • 网站建设首页面成都百度推广优化创意
  • app开发哪个公司专业网站seo源码
  • 建站快车设计素材网站p
  • 在线自助网站按照程序酷家乐必须先学cad吗
  • 东莞软件网站推广html前端网站开发PPT
  • 厦门百度搜索网站排名工业制品网站建设
  • 律师做推广宣传的网站仿新浪首页网站模板
  • 体育用品东莞网站建设广东建设网工程信息网站
  • 网站建站第十四课东莞企业网站推广
  • 响应式网站模板 食品自学网站建设需要什么学历
  • 网页制作与网站建设宝典(第2版)建企业网站哪家好
  • 怎么用linux做网站服务器吗wordpress工作原理
  • 代驾网站开发淮安网站建设设计制作
  • 乐山企业网站建设企业网站模板源码免费
  • 河源市网站建设公司做网站需要了解哪些
  • 分析某个网站建设哈尔滨专业建网站哪家好
  • 有哪些网站可以免费的网页游戏开服表37
  • 梧州网站建设推广wordpress主页图片不显示图片
  • 旅游网站域名应该如何设计重庆网站建设快速建站
  • 绵竹网站建设门户网站建设开发需要注意什么
  • 做业务在那几个网站上找客户端百度网站适配代码
  • 哈尔滨网站建设兼职南京新标特企业网站哪家广告做的
  • 谁有做爰网站号中山cp网站建设
  • 网站页尾内容丽水房产网站建设
  • 做水电到哪个网站找信息代做财务报表分析网站