首先,需要了解spring jdbc查询时,有三种回调方式来处理查询的结果集。可以参考 使用spring的JdbcTemplate进行查询的三种回调方式的比较,写得还不错。

1.返回对象(queryForObject)

有两种办法,即两个容易混淆的方法:

//
public Object queryForObject(String sql, Map<String, ?> paramMap, RowMapper rowMapper) {...}
//
public Object queryForObject(String sql, Map<String, ?> paramMap, Class requiredType) {...}

第一种方法是需要一个实现了RowMapper接口的对象实例作为第三个参数,实现RowMapper接口的类如下(其中类User.java有id、username、password、dept四个属性。):

public class UserRowMapper implements RowMapper<User>{
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt(1));
user.setUsername(rs.getString(2));
user.setPassword(rs.getString(3));
user.setDept(4);
return user;
}
}

UserRowMapper.java类在dao中使用方法如下:

public User queryForObject(String sql, Map<String, Object> params) {
return this.getNamedParameterJdbcTemplate().queryForObject(sql,params,new UserRowMapper());
}

在JUnit测试,代码如下:

@Test
public void getUser(){
String sql = "select * from user where id = :id";
Map<String,Object> map = new HashMap<>();
map.put("id", 1);
User user = dao.queryForObject(sql, map);
System.out.println(user.getId());
}

输出结果为:1。

第二种方法,需要传一个类的类作为参数,在dao中使用方法如下:

public Object queryForObject(String sql, Map<String, Object> params,Class<T> ObjectClass) {
try {
return this.getNamedParameterJdbcTemplate().queryForObject(sql,params,new BeanPropertyRowMapper<T>(ObjectClass));
} catch (EmptyResultDataAccessException e) {
return null;//当查询记录为0时,会抛出EmptyResultDataAccessException异常,所以可以捕获它并做适当的处理,如返回null
    }
}

用JUnit测试,代码如下:

@Test
public void getUser(){
String sql = "select * from user where id = :id";
Map<String,Object> map = new HashMap<>();
map.put("id", 100);
User user = (User) dao.queryForObject(sql, map, User.class);
System.out.println(user.getId());
}

2.返回对象列表

通过实现接口org.springframework.jdbc.core.ResultSetExtractor来定制能实现需要的功能的类。此处以能返回一个List<User>的类作为示例,是仿造上面BeanPropertyRowMapper.java的源码实现的,但BeanPropertyRowMapper只处理一行记录:

public class BeanPropertyRowsMapper<T> implements ResultSetExtractor<List<T>> {

    private Class<T> clazz;
private Map<String,PropertyDescriptor> mappedFields; public BeanPropertyRowsMapper(Class<T> clazz){
initialize(clazz);
} public Class<T> getClazz() {
return clazz;
} public void initialize(Class<T> clazz){
this.clazz = clazz;
this.mappedFields = new HashMap<String, PropertyDescriptor>();
PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(clazz);
for (PropertyDescriptor pd : pds) {
if (pd.getWriteMethod() != null) {
this.mappedFields.put(pd.getName().toLowerCase(), pd);
//将数据库中格式为"xxx_xxx"变成驼峰式"xxxXxx"才需要用到下面的代码
// String underscoredName = underscoreName(pd.getName());
// if (!pd.getName().toLowerCase().equals(underscoredName)) {
// this.mappedFields.put(underscoredName, pd);
// }
}
}
} // private String underscoreName(String name) {
// if (!StringUtils.hasLength(name)) {
// return "";
// }
// StringBuilder result = new StringBuilder();
// result.append(name.substring(0, 1).toLowerCase());
// for (int i = 1; i < name.length(); i++) {
// String s = name.substring(i, i + 1);
// String slc = s.toLowerCase();
// if (!s.equals(slc)) {
// result.append("_").append(slc);
// }
// else {
// result.append(s);
// }
// }
// return result.toString();
// } public List<T> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<T> list = new ArrayList<T>();
Class<T> clazz = getClazz(); try {
while(rs.next()){
T t = BeanUtils.instantiate(clazz);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(t);
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
for(int i = 1;i<=columnCount;i++){
String column = StringUtils.capitalize(JdbcUtils.lookupColumnName(rsmd, i));
PropertyDescriptor pd = this.mappedFields.get(column.replaceAll(" ", "").toLowerCase());
if(pd != null){Object value = JdbcUtils.getResultSetValue(rs, i, pd.getPropertyType());
bw.setPropertyValue(pd.getName(),value);
}
}
list.add(t);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
return list;
}
}

BeanPropertyRowsMapper类在dao中使用方法如下:

public List<User> getUsers(String sql,Map<String, Object> params){
return this.getNamedParameterJdbcTemplate().query(sql, params, new BeanPropertyRowsMapper<User>(User.class));
}

用JUnit测试,代码如下:

@Test
public void getUsers(){
String sql = "select * from user where id < :id";
Map<String,Object> map = new HashMap<>();
map.put("id", 10);
List<User> list = dao.getUsers(sql, map);
System.out.println(list.size());
}

BeanPropertyRowsMapper类使用到了泛型,所以可以通用,只需在实例化的时候传递一个javabean的Class给构造方法即可。注意:javabean中的属性名与查询的结果集的列名必须一致或由数据库的列名转成的“驼峰式”,且必须有set方法,否则不一致的或没有set方法的属性不会有查询结果列与之对应,即该属性不会有值。

但是有时结果集只有很少的几列,比如只查询username(用户名)或者是用户名和密码的Map集合等,只需在extractData(ResultSet rs)方法中修改即可。下面来看实现ResultSetExtractor接口的另一种用法,示例如下:

private class UsernameList implements ResultSetExtractor<List<String>> {

    public List<String> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<String> list = null;
while (rs.next()) {
if (list == null) {
list = new ArrayList<String>();
}
list.add(rs.getString(1));
}
return list;
}
}

在dao的使用方法如下:

public List<String> getUsernames(String sql,Map<String, Object> params){
return this.getNamedParameterJdbcTemplate().query(sql, params,new UsernameList());
}

用JUnit测试,代码如下:

@Test
public void getUsernames(){
String sql = "select username from user where id < 10";
Map<String,Object> map = new HashMap<>();
map.put("id", 10);
List<String>list = dao.getUsernames(sql, map);
System.out.println(list);
}

测试结果是打印了几个用户名。

第一种可用来返回javabean集合,第二种可用来处理只返回少数列的情况。

spring jdbc 查询结果返回对象、对象列表的更多相关文章

  1. 让JPA的Query查询接口返回Map对象

    在JPA 2.0 中我们可以使用entityManager.createNativeQuery()来执行原生的SQL语句. 但当我们查询结果没有对应实体类时,query.getResultList() ...

  2. Spring MVC学习笔记——返回JSON对象

    1.想要GET请求返回JSON对象,首先需要导入jackson-all-1.9.4.jar包 2.在控制器中添加不同的show()方法 //show()方法返回JSON对象 @RequestMappi ...

  3. Spring JDBC查询数据

    以下示例将展示如何使用Spring jdbc进行查询数据记录,将从student表中查询记录. 语法: String selectQuery = "select * from student ...

  4. spring jdbc查询 依赖JdbcTemplate这个类模版封装JDBC的操作

    package cn.itcast.spring.jdbc; import java.util.List; import org.springframework.jdbc.core.support.J ...

  5. Spring JDBC查询返回对象代码跟踪

    在封装方法的时候突然发现通过 ResultSetMetaData的getColumnCount()获取到的列明会多一列(ROWSTAT),而且每次的值都是1,目前没有找到相关信息,在国外网站上看到有类 ...

  6. SpringBoot JDBC 源码分析之——NamedParameterJdbcTemplate 查询数据返回bean对象

    1,NamedParameterJdbcTemplate 查询列表 /***测试***/ public void queyBeanTest(){ String s = "select * f ...

  7. Hibernate查询,返回new对象(注意这个新定义的类要有构造函数),使用sql带条件分页查询并且把结果显示到一个对象的集里面的解决方案

     IIndexDao package com.ucap.netcheck.dao; import com.ucap.netcheck.combination.beans.IndexCombinat ...

  8. tp5将查询数据返回为对象转为数组

    use think\Model; collection()->toArray(); $result = collection(model("Menu")->order( ...

  9. Spring Data Jpa 查询返回自定义对象

    转载请注明出处:http://www.wangyongkui.com/java-jpa-query. 今天使用Jpa遇到一个问题,发现查询多个字段时返回对象不能自动转换成自定义对象.代码如下: //U ...

随机推荐

  1. sql语句with as 和with(nolock)

    当with和as一起用时,表示定义一个SQL字句 例: with sonword as ( select * from person  ) select * from  student where n ...

  2. 使用ganglia监控hadoop及hbase集群

    一.Ganglia简介 Ganglia 是 UC Berkeley 发起的一个开源监视项目,设计用于测量数以千计的节点.每台计算机都运行一个收集和发送度量数据(如处理器速度.内存使用量等)的名为 gm ...

  3. node.js express 4.x 安装指南

    前几天express 推出了4.0,得知这个消息,自己尝试了一下,突然发现用以前的文档上的操作出现了各种问题.结果只能去看文档,现在在这个给大家分享下4.0版本的安装. 先说下如果需要用express ...

  4. Node.js包管理器Yarn的入门介绍与安装

    FAST, RELIABLE, AND SECURE DEPENDENCY MANAGEMENT. 就在昨天, Facebook 发布了新的 node.js 包管理器 Yarn 用以替代 npm .咱 ...

  5. jBPM4.4 no jBPM DB schema: no JBPM4_EXECUTION table. Run the create.jbpm.schema target first in the install tool.

    jBPM4.4 no jBPM DB schema: no JBPM4_EXECUTION table. Run the create.jbpm.schema target first in the ...

  6. 完整部署CentOS7.2+OpenStack+kvm 云平台环境(4)--用OZ工具制作openstack镜像

    在部署openstack云平台环境的时候,需要上传镜像到glance. 首先下载iso镜像,这里下载了centos6.5镜像,放到/usr/local/src目录下然后用OZ工具制作openstack ...

  7. NPOI操作EXCEL(四)——反射机制批量导出excel文件

    前面我们已经实现了反射机制进行excel表格数据的解析,既然有上传就得有下载,我们再来写一个通用的导出方法,利用反射机制实现对系统所有数据列表的筛选结果导出excel功能. 我们来构想一下这样一个画面 ...

  8. Wannafly Union Goodbye 2016

    A 题意:平面上有n个点(n<=100000),给你一个p(20<=p<=100) 判断是否存在一条直线至少过[np/100](向上取整)个点,时限20s,多组数据 分析:概率算法 ...

  9. .NET Mvc中ViewBag、ViewData、TempData如何使用

    ViewBag 获取动态视图数据字典 作用:给视图传递数据,不需要转换类型,由系统动态解析,比ViewData执行性能要差 ViewData   获取或设置视图数据的字典         给视图传递数 ...

  10. Dubbo_异常_Service启动时默认将方法注册到内网IP

    一.背景 一般Dubbo服务都是通过内网调用,Dubbo服务启动时默认会将服务注册到内网IP,消费端就无法从外网访问. 二.解决过程 1.Linux的hosts中设置外网IP a) 通过hostnam ...