zoukankan      html  css  js  c++  java
  • 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;
        }
    
    }
    View Code

    上面定义之后就是该怎么使用了。还是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")});
        }
    View Code

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

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

     二、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)});
        }
    }
    View Code

    上面的构造函数传两个参数,这两个参数我都放在上下文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>
    View Code
            UserSqlUpdate userSqlUpdate=(UserSqlUpdate)factory.getBean("userSqlUpdate");
            userSqlUpdate.updateUserMoney("cuiywA",666); 
    View Code

    在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);
    View Code


    四、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;
        }
    View Code

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

    1.配置DataSourceTransactionManager

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

    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>
    View Code

     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());
            }
    View Code

    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;
        }
    View Code

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

            IUserDAO userDao=(IUserDAO)factory.getBean("userDaoProxy");
    View Code
              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());
            }
    View Code

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

  • 相关阅读:
    强制表格内容不换行
    数组深度
    JDBC连接SQLService时报错误:“驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接"
    Excel中神奇的vlookup函数之基础应用
    利用python进行泰坦尼克生存预测——数据探索分析
    pandas数据处理基础——基础加减乘除的运算规则
    pandas数据处理基础——筛选指定行或者指定列的数据
    python读取文本文件数据
    服务器硬件基础知识
    WordPress实现伪静态
  • 原文地址:https://www.cnblogs.com/5ishare/p/8213370.html
Copyright © 2011-2022 走看看