Spring之DAO二

上一篇算是把JdbcDaoSupport的使用演示了一下,这篇主要是演示MappingSqlQuery、SqlUpdate、SqlFunction的使用以及Spring的事务管理。

一、MappingSqlQuery的使用

在上一篇获取所有User的方法QueryAllUser()中,使用getJdbcTemplate().queryForList()返回的是List<Map<String,Object>>类型,需要遍历转换成Java对象,那问题来了,查询的不止这一个方法,可能以后会有条件查询的方法,那每次都要把从数据库返回的List<Map<String,Object>>类型的List转一遍,当然也可以专门写一个转换的方法,这样每次传List<Map<String,Object>>类型的参数,然后返回List<User>类型的值。其实还有一种方式,就是使用MappingSqlQuery。MappingSqlQuery是一个抽象类,需要实现它的方法mapRow()。下面的代码就是定义了类UserMappingSqlQuery,继承了抽象类MappingSqlQuery,实现了它的mapRow()方法。

package Cuiyw.Spring.Dao;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.object.MappingSqlQuery;

import Cuiyw.Spring.Model.User;

public class UserMappingSqlQuery extends MappingSqlQuery {

    @Override
    protected Object mapRow(ResultSet rs, int rowNum) throws SQLException {
        // TODO Auto-generated method stub
        User user=new User();
        user.setUserId((Integer)rs.getInt("id"));
        user.setName((String)rs.getString("name"));
        user.setMoney((Float)rs.getFloat("money"));
        return user;
    }

}

上面定义之后就是该怎么使用了。还是UserDAO类中,重写List<User> QueryAllUser()方法。代码中主要是为了尝试使用参数,所有增加了一个过滤条件。

    public List<User> QueryAllUser() {

        String sql="select id,name,money from tb_user where name=?";
        UserMappingSqlQuery userQuery=new UserMappingSqlQuery();
        userQuery.setDataSource(getDataSource());
        userQuery.setSql(sql);
        userQuery.setParameters(new SqlParameter(java.sql.Types.VARCHAR));
        userQuery.compile();
        return userQuery.execute(new Object[]{new String("cuiywA")});
    }

执行QueryAllUser(),打印出查询的list。

        List<User> list=userDao.QueryAllUser();
        for(User u:list)
        {
            System.out.println("name:"+u.getName()+" money: "+u.getMoney());
        }

二、SqlUpdate的使用

上面熟悉了查询的用法,SqlUpdate主要是用来更新。下面定义了UserSqlUpdate继承SqlUpdate

package Cuiyw.Spring.Dao;

import javax.sql.DataSource;

import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.SqlUpdate;

public class UserSqlUpdate extends SqlUpdate{

    public UserSqlUpdate(DataSource ds, String sql) {
        super(ds, sql);
        declareParameter(new SqlParameter(java.sql.Types.FLOAT) );
        declareParameter(new SqlParameter(java.sql.Types.VARCHAR) );
    }

    public int updateUserMoney(String name,float money)
    {
        compile();
        return update(new Object[]{new Float(money),new String(name)});
    }
}

上面的构造函数传两个参数,这两个参数我都放在上下文xml中。dataSource还是上一博客中配置的数据库信息。

<bean id="userSqlUpdate" class="Cuiyw.Spring.Dao.UserSqlUpdate">
<constructor-arg type="java.lang.String" index="1">
<value>update tb_user set money=? where name=?</value>
</constructor-arg>
<constructor-arg ref="dataSource" index="0"></constructor-arg>
</bean>

        UserSqlUpdate userSqlUpdate=(UserSqlUpdate)factory.getBean("userSqlUpdate");
        userSqlUpdate.updateUserMoney("cuiywA",666); 

在updateUserMoney()前后遍历数据库的user,发现以及修改了。


三、SqlFunction的使用

SqlFunction返回单一行的查询结果,默认返回int,也可以重载返回其他类型。下面的我是直接在main函数中使用。

        BasicDataSource dataSource=(BasicDataSource)factory.getBean("dataSource");
        SqlFunction sf=new SqlFunction(dataSource,"select count(1) from tb_user;");
        sf.compile();
        int count=sf.run();
        System.out.println("User Count:"+count);


四、Spring事务管理

什么是事务这些就不说了,事务最常见的例子就是转账,我定义User有money字段就是为了事务而定义的。实现事务在spring中有好几种方式,这里只简单介绍基于jdbc的声明式事务。

这里在IUserDAO中定义了两个接口,一个是存取款,一个是转账,并在UserDAO中实现。理想情况一个加一个减,但是加入减的成功了,加的失败了,那转账就是错误。

    public Boolean outInMoney(int toUserId,float money)
    {
        String sql="update  tb_user set money=money+? where id=? ";
        int row=getJdbcTemplate().update(sql, new Object[]{money,toUserId});
        if(row>0)
        {
            return true;
        }
        return false;
    }

    public Boolean transfer(int fromUserId, int toUserId, float transferMoney) {
        Boolean out= outInMoney(fromUserId,-transferMoney);
        Boolean in=outInMoney(toUserId,transferMoney);
        return out&in;
    }

spring使用DataSourceTransactionManager作为jdbc的事务管理者,被管理对象使用TransactionProxyFactoryBean配置。

1.配置DataSourceTransactionManager

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

2.配置TransactionProxyFactoryBean

这里transactionAttributes是来配置哪些方法使用事务管理,这里只配置了transfer方法,使用*,表达所有的方法,prop的值可以是PROPAGATION(事务的传播行为),ISOLATIONf(事务的隔离级别) -Exception(发生哪些异常回滚事务) +Exception(发生哪些事务不回滚)

PROPAGATION类型:

PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。 
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作

Exception:
- 表示抛出该异常时需要回滚
+表示即使抛出该异常事务同样要提交
-ApplicationException :表示抛出ApplicationException 时,事务需要回滚。但不是说只抛出ApplicationException 异常时,事务才回滚,如果程序抛出RuntimeException和Error时,事务一样会回滚,即使这里没有配置。因为Spring中默认对所有的RuntimeException和Error都会回滚事务

 <!-- 配置业务层代理 -->
<bean id="userDaoProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <!-- 配置目标对象 -->
    <property name="target" ref="userDao"/>
    <!-- 注入事务管理器 -->
    <property name="transactionManager" ref="transactionManager"/>
    <!-- 注入事务的属性 -->
    <property name="transactionAttributes">
        <props>
            <prop key="transfer">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

3.这里先理想情况的转账一个,可以看到cuiywA账号减100,cuiywB账号加100.

        List<User> list=userDao.QueryAllUser();
        for(User u:list)
        {
            System.out.println("name:"+u.getName()+" money: "+u.getMoney());
        }
        userDao.transfer(1, 2, 100);
        list=userDao.QueryAllUser();
        for(User u:list)
        {
            System.out.println("name:"+u.getName()+" money: "+u.getMoney());
        }

4.异常转账

模拟异常这里在转账时增加一个错误1/0

    public Boolean transfer(int fromUserId, int toUserId, float transferMoney) {
        Boolean out= outInMoney(fromUserId,-transferMoney);
        int a=1/0;
        Boolean in=outInMoney(toUserId,transferMoney);
        return out&in;
    }

这里遇到了一个坑,配置之后还是按照前面的factory.getBean("userDao"),但始终不成功,找了好久,觉得配置的userDaoProxy并没有用到,这不科学啊,又百度了一下,发现还真是。在获取bean时不应时userDao了,而是TransactionProxyFactoryBean对象。

        IUserDAO userDao=(IUserDAO)factory.getBean("userDaoProxy");

          ApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"ApplicationContext.xml"});
        BeanFactory factory=context;
        IUserDAO userDao=(IUserDAO)factory.getBean("userDaoProxy");
        List<User> list=userDao.QueryAllUser();
        for(User u:list)
        {
            System.out.println("name:"+u.getName()+" money: "+u.getMoney());
        }
        try
        {
          userDao.transfer(1, 2, 100);
        }
        catch(Exception e)
        {}
        list=userDao.QueryAllUser();
        for(User u:list)
        {
            System.out.println("name:"+u.getName()+" money: "+u.getMoney());
        }

上面在转账的地方增加了try-catch,主要是为了看执行转账之后的金额是否与之前的一致。上面截图可以看到是一致的,事务是有回滚的。事务管理还有其他方式,以后会一一介绍。

原文地址:https://www.cnblogs.com/5ishare/p/8213370.html

时间: 2024-10-09 23:06:31

Spring之DAO二的相关文章

Spring之DAO一

前面博客把bean.aop简单了解了一下,今天主要是了解Spring中DAO层,如果使用传统的JDBC时需要创建连接.打开.执行sql.关闭连接这一系列的步骤,Spring框架对JDBC进行了封装,我们只需使用封装好的JdbcTemplate执行sql语句.主要还是继承了Spring提供的JdbcDaoSupport.下面主要是用来演示怎么使用JdbcDaoSupport. 一.创建Model 这里创建一个User类,作为model. package Cuiyw.Spring.Model; pu

Spring 对 DAO 的支持

一.Spring 的 DAO 理念 DAO(Data Access Object)是用于访问数据的对象,虽然在大多数情况下将数据保存在数据库中,但这并不是唯一的选择,也可以将数据存储到文件中或 LDAP 中.DAO 不但屏蔽了数据存储的最终介质的不同,也屏蔽了具体的实现技术的不同. 早期,JDBC 是访问数据库的主流选择.近几年,数据持久化技术获得了长足的发展,Hibernate.MyBatis.JPA.JDO 成为持久层中争放异彩的实现技术.只要为数据访问定义好 DAO 接口,并使用具体的技术

深入理解Spring AOP之二代理对象生成

深入理解Spring AOP之二代理对象生成 spring代理对象 上一篇博客中讲到了Spring的一些基本概念和初步讲了实现方法,当中提到了动态代理技术,包含JDK动态代理技术和Cglib动态代理 动态代理这部分我有过一篇博客介绍:动态代理,想深入了解的朋友能够看一看,再回想一下,Spring中怎样区分採用JDK动态代理和CGlib动态代理: 假设目标对象的实现类实现了接口.Spring AOP 将会採用 JDK 动态代理来生成 AOP 代理类: 假设目标对象的实现类没有实现接口,Spring

Spring的DAO模块

Spring的DAO模块提供了对JDBC.Hibernate.JDO等DAO层支持. DAO模块依赖 commons-pool.jar.commons-collections.jar package com.dao; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import org.springframework.jdbc.core.support.

循环调用spring的dao,数个过后无响应

循环调用spring的dao,数个过后无响应 博客分类: spring daospringssh 最近遇到这么一个问题:前台按钮发送AJax请求到后台,后台是SSH框架.每点击一下按钮就发送一次请求. 点击数次(7次)过后,页面无ajax响应. 在排除前台因素之后,找 到后台代码.写一个Test类. public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationCo

spring深入理解二(关于容器工作源码)

spring基本工作原理如下: 1.查找bean配置文件 2.加载bean配置文件并解析生成中间表示BeanDefinition 3.注册beanDefinition 4.如果是单例或lazy-init=false,则直接生成bean spring将 1.查找bean配置文件 2.加载bean配置文件并解析生成中间表示BeanDefinition 3.注册beanDefinition 这三部分开,可以提供更多的定制给用户. spring将配置文件之类的文件资源抽象成一个Resource,封装了g

深入探索spring技术内幕(二): 剖析spring管理Bean的原理与配置

求二叉树的宽度和深度 给定一个二叉树,获取该二叉树的宽度和深度. 例如输入 a / \ b c / \ / \ d e f g 返回3. 详细描述: 接口说明 原型: int GetBiNodeInfo(BiNode &head, unsigned int *pulWidth, unsigned int *pulHeight) 输入参数: head 需要获取深度的二叉树头结点 输出参数(指针指向的内存区域保证有效): pulWidth 宽度 pulHeight 高度 返回值: 0 成功 1 失败

Spring Data 系列(二) Spring+JPA入门

通过[Spring Data 系列(一) 入门]的介绍,通过对比的方式认识到Spring提供的JdbcTemplate的强大功能.通过使用JdbcTemplate,操作数据库,不需要手动处理Connection,Statement等底层SQL对象.可是,Spring对数据库的操作还远远没有结束.本章主要介绍Spring 对JPA的支持. 主要内容 简单介绍JPA Spring Hibernate JPA整合 1.JPA简介 Java Persistence API (JPA),为开发人员提供了一

跟着刚哥学习Spring框架--Spring容器(二)

Spring容器 启动Spring容器(实例化容器) -- IOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化(加载启动),这样才可以从容器中获取Bean的实例并使用.  Bean是Spring管理的基本单位,任何的Java对象和组件都被当成Bean处理,容器还负责管理Bean与Bean之间的依赖关系.  两种类型的启动实现   1.BeanFactory:IOC容器的基本实现,是Spring框架的基础设施,面向Spring本身: -- Spring容器最基本的接口就是BeanF