Spring学习心得(22)-- spring声明式事务处理(使用jdbc操作数据库)

来源:互联网 发布:私募 变更 知乎 编辑:程序博客网 时间:2024/05/29 17:58

声明式:针对编程人员,声明spring容器遇到哪些目标方法时需要开启事务,哪些不用开启事务。 
事务处理:把事务处理交给spring容器来完成。 
spring声明式事务处理的目标: 
让程序员从事务处理中脱离开来,交给spring完成,并声明哪些目标方法需要开启事务,哪些不需要。

spring声明式事务处理的步骤:

构建开发环境

导入所需jar包

这里写图片描述

把dataSource放到spring容器中,并测试是否成功。如果没有成功获取到dataSource说明配置文件有问题

代码实现如下:

jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc\:mysql\://localhost\:3306/hibernate1jdbc.username=rootjdbc.password=root
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

上面的是放在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">    <!--        细心的人可以发现,这里多了几行数据,是关于tx的,在下面会讲解到    -->    <!-- ****************读取配置文件信息的固定写法:开始线  **************** -->    <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>    <!-- *****读取配置文件信息的固定写法终结线********************** --></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);    }}

运行结果: 
测试dataSource是否放到spring容器的结果


完成dao,service,bean层,并放到spring容器(bean层不用)。

代码实现如下:
/** * 创建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<Person> getAllPerson();}/** * dao层的实现。 * 前面我们已经说到,要与jdbc结合的3种方法,在这里我们需要通过jdbc来操作数据库 * 我们就用继承jdbcDaoSupport类来实现 */public class PersonDaoImpl extends JdbcDaoSupport implements PersonDao {    /**     * 实现获取所有用户的方法     */    @Override    public List<Person> 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<Person> getAllPerson();}/** * service层的实现类 * 这里还需要把personDao引用进来 */public class PersonServiceImpl implements PersonService {    //在这里调用了personDao,就还需要利用Di把personDao注入进来,所以要    //设置它的getter&setter方法    private PersonDao personDao;    /**     * 调用dao层来获取所有用户     */    @Override    public List<Person> 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容器中,配置文件的书写如下:

<!-- *****把dao,service放到spring容器的开始线********************** -->    <!--         因为personDaoImpl继承了jdbcDaoSuppory类,在这个抽象类中        有dataSource的引用,所以在这里需要把dataSource引入     -->    <bean id="personDao" class="cn.ansel.dao.impl.PersonDaoImpl">        <property name="dataSource">            <ref bean="dataSource"/>        </property>    </bean>    <!--         因为在service层引用了personDao,所以在这里要引进来     -->    <bean id="personService" class="cn.ansel.service.impl.PersonServiceImpl">        <property name="personDao">            <ref bean="personDao"/>        </property>    </bean>    <!-- *****把dao,service放到spring容器的终结线********************** -->

测试dao,service层是否成功放到spring容器:

/**     * 测试dao层是否成功放到Spring容器中     * 如果没有成功,我们在获取的时候就会报错     * service层也是一样     */    @Test    public void testDao(){        applicationContext.getBean("personDao");    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

dao层的运行结果: 
这里写图片描述

    //service层的测试:    @Test    public void testService(){        applicationContext.getBean("personService");    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

运行结果: 
这里写图片描述

现在Dao,service层都准备好了,我们就进行aop的配置了。


aop配置(声明式事务处理)

  • 我们前面说到了,spring的声明式事务处理 就是让程序员从事务中脱离出来,
  • 所以我们在配置config:aop的时候,不用我们自己弄事务,所以此时就不用在中配置事务了,
  • 在spring中,有一个最顶级的接口,是处理事务的。叫PlatformTransactionManager,下面是这个接口的视图

  • 这里写图片描述

这个接口有一个继承类: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();    }

运行前数据库: 
这里写图片描述

运行结果:

这里写图片描述

数据库结果: 
这里写图片描述 
当我们把异常去掉时,运行结果: 
这里写图片描述





0 0