spring jdbc 查询结果返回对象、对象列表

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

1.返回对象(queryForObject)

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

//1
public Object queryForObject(String sql, Map<String, ?> paramMap, RowMapper rowMapper) {...}
//2
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集合,第二种可用来处理只返回少数列的情况。

转载于:https://www.cnblogs.com/sprinkle/p/6253663.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值