声明式:针对编程人员,声明spring容器遇到哪些目标方法时需要开启事务,哪些不用开启事务。
事务处理:把事务处理交给spring容器来完成。
spring声明式事务处理的目标:
让程序员从事务处理中脱离开来,交给spring完成,并声明哪些目标方法需要开启事务,哪些不需要。
导入所需jar包
代码实现如下:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/hibernate1
jdbc.username=root
jdbc.password=root
上面的是放在classpath下的jdbc.properties
下面是spring配置文件的配置:
<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.propertiesvalue>
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>
beans>
/**
* 测试类
*/
public class test {
//由于所有的测试都在这个类完成,所以把applicationContext设置成静态
public static ApplicationContext applicationContext;
static{
applicationContext=new ClassPathXmlApplicationContext("cn/ansel/config/applicationContext.xml");
}
/**
* 看看是否成功把dataSource放到spring容器中。如果没有成功的话,会报错
*/
@Test
public void testDataSource(){
DataSource dataSource=(DataSource) applicationContext.getBean("dataSource");
System.out.println(dataSource);
}
}
代码实现如下:
/**
* 创建bean层的目的是为了等下需要操作数据库,所以要有一个bean
*/
public class Person implements Serializable {
private Long pid;
private String pname;
private String pdescription;
//省略getter&setter
}
/**dao层
* 这个类需要有2个方法,
* 一个是保存用户
* 另外一个是获取所有的用户
*/
public interface PersonDao {
//保存用户
public void savePerson();
//获取所有的用户
public List getAllPerson();
}
/**
* dao层的实现。
* 前面我们已经说到,要与jdbc结合的3种方法,在这里我们需要通过jdbc来操作数据库
* 我们就用继承jdbcDaoSupport类来实现
*/
public class PersonDaoImpl extends JdbcDaoSupport implements PersonDao {
/**
* 实现获取所有用户的方法
*/
@Override
public List getAllPerson() {
//获取到jdbcTemplate类,调用查询方法,直接返回
//这里还要用到rowMapper匿名内部类实现对于person的赋值
return this.getJdbcTemplate().query("select * from person", new RowMapper() {
@Override
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Person person=new Person();
person.setPdescription(rs.getString("pdescription"));
person.setPid(rs.getLong("pid"));
person.setPname(rs.getString("pname"));
return person;
}
});
}
/**
* 实现保存用户的方法
*/
@Override
public void savePerson() {
//获取到jdbcTemplate类,调用update方法保存
this.getJdbcTemplate().update("insert into person(pname,pdescription) values('ansel','nice')");
}
}
/**
* service层
*这里的方法还是跟dao的方法一致
*/
public interface PersonService {
public void savePerson();
public List getAllPerson();
}
/**
* service层的实现类
* 这里还需要把personDao引用进来
*/
public class PersonServiceImpl implements PersonService {
//在这里调用了personDao,就还需要利用Di把personDao注入进来,所以要
//设置它的getter&setter方法
private PersonDao personDao;
/**
* 调用dao层来获取所有用户
*/
@Override
public List getAllPerson() {
return personDao.getAllPerson();
}
/**
* 调用dao层保存用户
*/
@Override
public void savePerson() {
personDao.savePerson();
}
//personDao的getter&setter方法
public PersonDao getPersonDao() {
return personDao;
}
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
}
把dao和service层配置到spring容器中,配置文件的书写如下:
<bean id="personDao" class="cn.ansel.dao.impl.PersonDaoImpl">
<property name="dataSource">
<ref bean="dataSource"/>
property>
bean>
<bean id="personService" class="cn.ansel.service.impl.PersonServiceImpl">
<property name="personDao">
<ref bean="personDao"/>
property>
bean>
测试dao,service层是否成功放到spring容器:
/**
* 测试dao层是否成功放到Spring容器中
* 如果没有成功,我们在获取的时候就会报错
* service层也是一样
*/
@Test
public void testDao(){
applicationContext.getBean("personDao");
}
//service层的测试:
@Test
public void testService(){
applicationContext.getBean("personService");
}
现在Dao,service层都准备好了,我们就进行aop的配置了。
这个接口有一个继承类:abstractPlatformTransactionManager, 其里面的方法:
在这里省略了方法主体,从这个抽象类的方法我们可以看到,只有getTransaction的方法是抽象的,谁继承这个类,就由谁来实现获取事务的方法。在这里我们使用abstractPlatformTransactionManager的其中一个子类:DataSourceTransactionManager。下面是它的视图
在这里,也引用了dataSource,并且这里实现了getTransaction方法。
配置文件如下:
为了验证我们的配置成功,我们在PersonServiceImpl中设置一个异常
/**
* 调用dao层保存用户
*/
@Override
public void savePerson() {
personDao.savePerson();
//在这里设置一个异常。如果处在同一事务的话,就没有保存成功
//如果保存成功了 就配置错误了。
int a=1/0;
}
/**
* 测试aop配置是否成功
*/
@Test
public void testTransaction(){
PersonService personService=(PersonService) applicationContext.getBean("personService");
personService.savePerson();
}
运行结果: