问题?Spring-jdbc-处理事务详解及案例
首先我们要想到spring以及把jdbc很多事儿都做了,为什么还要事务呢?
事务包括事务的提交及回滚,加入当我们进行数据交互的时候,数据发生错误,不允许出现事务被修改了,那么我们就要实现事务回滚的操作。
必须加的jar包
首先是在applicationContext.xml配置文件中声明事务
spring声明式事务处理
spring
声明:针对的是程序员,程序员告诉spring容器,哪些方法需要事务,哪些方法不需要事务(就比如为我们在hibernate中增、删、改就需要事务,而查就不需要事务了)
事务处理 spring容器来做事务处理
目的:让spring管理事务,开发者不再关注事务
那么久会呈现出下面这种状态:
那么我们的事务又怎么获得呢!在这里我们就需要一个得到事务的接口类了
PlatFormTransactionManage接口
spring声明式事务处理的步骤:
1、搭建环境
2、把dao层和service层的接口和类写完
3、在spring的配置文件中,先导入dataSource
4、测试
5、导入dao和service层的bean
6、测试
7、进行AOP的配置
1、引入事务管理器
2、进行aop的配置
8、测试service层的类看是否是代理对象
程序员做的事儿:在spring容器中,引入注入,及引入数据源
spring容器做的事儿:就是事务的声明,事务的启动,切面的通知
案例:
bean类:
package cn.itcast.sh.spring.domain; public class Person { private Long pid; private String pname; private String psex; public Long getPid() { return pid; } public void setPid(Long pid) { this.pid = pid; } public String getPname() { return pname; } public void setPname(String pname) { this.pname = pname; } public String getPsex() { return psex; } public void setPsex(String psex) { this.psex = psex; } @Override public String toString() { return "Person [pid=" + pid + ", pname=" + pname + ", psex=" + psex + "]"; } }
package cn.itcast.sh.spring.dao; import java.util.List; import cn.itcast.sh.spring.domain.Person; public interface PersonDao { public void savePerson(); public List<Person> getPerson(); }
package cn.itcast.sh.spring.dao; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.support.JdbcDaoSupport; import cn.itcast.sh.spring.domain.Person; public class PersonDaoImpl extends JdbcDaoSupport implements PersonDao{ public void savePerson() { this.getJdbcTemplate().update("insert into person(pname,psex) values('sss1','sss1')"); } public List<Person> getPerson() { return this.getJdbcTemplate().query("select *from person", new RowMapper() { public Object mapRow(ResultSet arg0, int arg1) throws SQLException { Person person = new Person(); person.setPid(arg0.getLong("pid")); person.setPname(arg0.getString("pname")); person.setPsex(arg0.getString("psex")); return person; } }); } }
package cn.itcast.sh.spring.service; import java.util.List; import cn.itcast.sh.spring.domain.Person; public interface PersonService { public void savePerson(); public List<Person> getPerson(); }
package cn.itcast.sh.spring.service; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.transaction.PlatformTransactionManager; import cn.itcast.sh.spring.dao.PersonDao; import cn.itcast.sh.spring.domain.Person; public class PersonServiceImpl implements PersonService{ private PersonDao personDao; public PersonDao getPersonDao() { return personDao; } public void setPersonDao(PersonDao personDao) { this.personDao = personDao; } public void savePerson() { //这就是spring要利用的事务接口,这个很重要,只要涉及事务就必须有它 //PlatformTransactionManager // int i=1/0; //测试事务回滚: this.personDao.savePerson(); } public List<Person> getPerson() { return this.personDao.getPerson(); } }
异常切面类:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <value>classpath:jdbc.properties</value> </property> </bean> <!-- 创建数据源 --> <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- dao层 事务层用到数据源datasource:增删改查--> <bean id="personDao" class="cn.itcast.sh.spring.dao.PersonDaoImpl"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <!-- service层 --> <bean id="personService" class="cn.itcast.sh.spring.service.PersonServiceImpl"> <property name="personDao"> <ref bean="personDao"/> </property> </bean> <!-- 异常切面 --> <bean id="exception" class="cn.itcast.sh.spring.exception.MyException"></bean> <!-- 创建事务管理器 :用到数据源datasource,起事务--> <bean id="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"><!-- 注入数据源对象 --> <ref bean="dataSource"/> </property> </bean> <!-- 创建事务管理器的对像名必须和下面,下面的通知transaction-manager=""相同 --> <!-- 通知: 1、告诉spring容器,采用什么样的方法来处理事务 (这里采取的是jdbc的DataSourceTransactionManager的方式, 当然也有hibernate的事务) 2、高数spring容器,采取什么样的事务策略 --> <tx:advice id="tx" transaction-manager="transactionManager1"> <tx:attributes> <!-- name:规定方法的 isolation:数据库隔离机制 默认值DEFAULT propagation:传播机制(属性)默认值REQUIRED 所以这两个属性不用写,直接就是默认值 --> <tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution(* cn.itcast.sh.spring.service.*.*(..))" id="perfram"/> <aop:advisor advice-ref="tx" pointcut-ref="perfram"/> <aop:aspect ref="exception"> <aop:after-throwing method="myException" throwing="ee" pointcut-ref="perfram"/> </aop:aspect> </aop:config> </beans>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <value>classpath:jdbc.properties</value> </property> </bean> <!-- 创建数据源 --> <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- dao层 事务层用到数据源datasource:增删改查--> <bean id="personDao" class="cn.itcast.sh.spring.dao.PersonDaoImpl"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <!-- service层 --> <bean id="personService" class="cn.itcast.sh.spring.service.PersonServiceImpl"> <property name="personDao"> <ref bean="personDao"/> </property> </bean> <!-- 异常切面 --> <bean id="exception" class="cn.itcast.sh.spring.exception.MyException"></bean> <!-- 创建事务管理器 :用到数据源datasource,起事务--> <bean id="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"><!-- 注入数据源对象 --> <ref bean="dataSource"/> </property> </bean> <!-- 创建事务管理器的对像名必须和下面,下面的通知transaction-manager=""相同 --> <!-- 通知: 1、告诉spring容器,采用什么样的方法来处理事务 (这里采取的是jdbc的DataSourceTransactionManager的方式, 当然也有hibernate的事务) 2、高数spring容器,采取什么样的事务策略 --> <tx:advice id="tx" transaction-manager="transactionManager1"> <tx:attributes> <!-- name:规定方法的 isolation:数据库隔离机制 默认值DEFAULT propagation:传播机制(属性)默认值REQUIRED 所以这两个属性不用写,直接就是默认值 --> <tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution(* cn.itcast.sh.spring.service.*.*(..))" id="perfram"/> <aop:advisor advice-ref="tx" pointcut-ref="perfram"/> <aop:aspect ref="exception"> <aop:after-throwing method="myException" throwing="ee" pointcut-ref="perfram"/> </aop:aspect> </aop:config> </beans>
package cn.itcast.sh.spring.test; import javax.sql.DataSource; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.itcast.sh.spring.dao.PersonDao; import cn.itcast.sh.spring.service.PersonService; public class TransactionTest { public static ApplicationContext applicationContext; static{ applicationContext=new ClassPathXmlApplicationContext("cn/itcast/sh/spring/transaction/applicationContext.xml"); } //测试datasource(JDBC) @Test public void transaction(){ DataSource dataSource = (DataSource)applicationContext.getBean("dataSource"); System.out.println("datasource "+dataSource); } //测试dao层 @Test public void persondao(){ PersonDao personDao = (PersonDao)applicationContext.getBean("personDao"); System.out.println("dao层dataSource "+personDao); } //测试service层 @Test public void personService(){ PersonService personService = (PersonService)applicationContext.getBean("personService"); System.out.println("Service "+personService); personService.savePerson();//测试及测试事务回滚 } }