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 {@Overrideprotected Object mapRow(ResultSet rs, int rowNum) throws SQLException {// TODO Auto-generated method stubUser 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∈}
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∈}
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,主要是为了看执行转账之后的金额是否与之前的一致。上面截图可以看到是一致的,事务是有回滚的。事务管理还有其他方式,以后会一一介绍。
Spring之DAO二相关推荐
- [Spring 深度解析]第5章 Spring之DAO
第5章 ◄Spring之DAO► 在上一章节中,我们了解了Spring框架中的AOP模块,这一章节我们开始学习Spring框架中的DAO模块. 本章主要涉及的知识点: ● JDBC基本用法:S ...
- SSH框架之Spring4专题4:Spring与DAO
本专题内容主要包含两部分:Spring所使用的操作数据库的技术之一,JDBC模版的使用:另一部分则为Spring对于事务的管理. Spring与Dao部分,是Spring的两大核心技术loC与AOP的 ...
- Spring Boot (二)集成Mybatis、Druid
项目GitHub地址 : https://github.com/FrameReserve/TrainingBoot Spring Boot (二)集成Mybatis.Druid,标记地址: https ...
- spring boot / cloud (二) 规范响应格式以及统一异常处理
spring boot / cloud (二) 规范响应格式以及统一异常处理 前言 为什么规范响应格式? 我认为,采用预先约定好的数据格式,将返回数据(无论是正常的还是异常的)规范起来,有助于提高团队 ...
- Spring Data(二)查询
Spring Data(二)查询 接着上一篇,我们继续讲解Spring Data查询的策略. 查询的生成 查询的构建机制对于Spring Data的基础是非常有用的.构建的机制将截断前缀find-By ...
- Spring学习总结二
Spring框架的代理与AOP.AspectJ Spring学习总结二 0.在理解什么是AOP之前的一些话 1.什么是AOP 2.AOP的重要概念 3.代理模式 3.1.静态代理 3.2.动态代理 3 ...
- spring security 学习二
spring security 学习二 doc:https://docs.spring.io/spring-security/site/docs/ 基于表单的认证(个性化认证流程): 一.自定义登录页 ...
- Spring Boot(二)应用实例
Spring Boot(二) 一 . Spring Boot Web 应用实例 这是一个Spring Boot web应用程序示例,使用嵌入式Tomcat + JSP模板,并将包作为可执行文件WAR文 ...
- Spring4基础 学习笔记(5) ---- Spring与Dao
Spring与DAO: Spring与JDBC模板:为了避免直接使用JDBC而带来的复杂且冗长的代码,Spring提供了一个强有力的模板类:JdbcTemplate 来简化JDBC操作.并且,数据源D ...
最新文章
- [转载] 七龙珠第一部——第035话 北方女孩
- POJ 2391 Ombrophobic Bovines ★(Floyd+二分+拆点+最大流)
- Chrome 输入文字卡死
- 动态创建ActiveRecord条件的查询 MyQuery
- 为什么服务端程序都需要先 listen 一下?
- 杨笠代言电脑遭投诉抵制,网友吵翻!英特尔回应了...
- from rfc 2068 hypertext怎么解决_“倒数第二”英语怎么说?千万不要翻译成“last second”!...
- 拉普拉斯方程与复微分
- Mac 安装JDK 8
- SlideLive:提供关系型PPT模板下载
- 为什么员工辞职时,领导都要象征性挽留一下?
- ‘data‘ hides member of supertype ‘BaseExpAdapter‘ and needs ‘override‘ modifier
- Java学习day07-Java高级编程-多线程
- 黄油安卓_寻找可爱,定义外观为黄油皇家字符
- 蓝桥杯--模拟1 AcWing 1241. 外卖店优先级
- 企业上云是工业互联网的前提,中国企业上云潜力巨大
- 【OpenCV】2020年关于SIFT算法专利版权问题的解决办法
- 十诫诗串词_持续交付的十诫
- 搭建人工智能云服务器,搭建人工智能云连接,实现手机APP远程控制
- cron的使用(二)
热门文章
- 如何去除table的边框_如何擦玻璃,这些擦玻璃知识很实用
- python中print输出格式汇总_python中print输出格式有哪些
- php数组合并如何不覆盖,php如何实现合并数组并且不覆盖重复值
- 重装系统找不到固态_重装系统时找不到固态
- springboot2 war页面放在那_成为微服务架构师--SpringBoot2学习笔记
- 【 FPGA 】UltraFast设计方法学:时序约束
- 对话功率谱与自相关函数
- 为什么有的人喜欢看烧脑剧?
- Git 码云 Github
- 说说标准服务器架构(WWW+Image/CSS/JS+File+DB)