问题?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
+ "]";
}
}
Dao层
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;
}
});
}
}
service层
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>
jdbc.properies配置文件
<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();//测试及测试事务回滚
}
}