spring声明式事务处理(使用jdbc操作数据库)

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

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

构建开发环境

导入所需jar包

这里写图片描述

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

代码实现如下:

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">
    <!--
        细心的人可以发现,这里多了几行数据,是关于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");
    }

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

    //service层的测试:
    @Test
    public void testService(){
        applicationContext.getBean("personService");
    }

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

现在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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值