实验五 Spring整合Mybatis增加事务管理
实验目的:
- 了解事务的作用
- 学会用注解实现事务
- 添加事务管理
实验类型:
验证性
实验学时:
2学时
实验内容:
在spring实验4的基础上:
实验任务1.修改测试类:
@Test
public void query(){
ApplicationContext context=new ClassPathXmlApplicationContext("spring-mybaits.xml");
StudentController controller=context.getBean("studentController",StudentController.class);
Student student = new Student();
student.setUsername("五十六精研");
student.setSno("1001");
controller.add(student);
controller.query();
}
实验任务2.StudentController中的add方法:
public String add(Student student){
service.add(student);
System.out.println(1/0);
return null;
}
运行后:
java.lang.ArithmeticException: / by zero
at com.hxci.controller.StudentController.add(StudentController.java:26)
at com.hxci.controller.StudentController$$FastClassBySpringCGLIB$$18a7de90.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685)
at com.hxci.controller.StudentController$$EnhancerBySpringCGLIB$$4fb2937f.add(<generated>)
at MyTest.query(MyTest.java:18)
由上代码可以看出报错,原因是add方法中有一个System.out.println(1/0);
而0是不能做分母的因此报了异常。
现在看一下数据库:
数据库将刚刚的数据添加了上去。
现在分析一下,程序出了错误,但是数据却添加了进去,这是不合理的。
要做就全做,不然就全不做。
现在给add方法添加上事务注解@Transactional,删除数据库中的所有记录。
@Transactional
public String add(Student student){
service.add(student);
System.out.println(1/0);
return null;
}
运行后:
java.lang.ArithmeticException: / by zero
at com.hxci.controller.StudentController.add(StudentController.java:26)
at com.hxci.controller.StudentController$$FastClassBySpringCGLIB$$18a7de90.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at com.hxci.controller.StudentController$$EnhancerBySpringCGLIB$$9cac15f8.add(<generated>)
at MyTest.query(MyTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
同样报了异常,现在看一下数据库:
这此没有将数据添加进去,这就是事务的作用。
事务是恢复和并发控制的基本单位。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个 事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
事务有配置文件实现的方式和注解实现的方式,本文中只写了用注解的方式实现。