org.springframework.jdbc.core.JdbcTemplate.query(String sql, Object[] args, RowMapper<StaffUnionVO> rowMapper) throws DataAccessException

1.自定义rowMapper

public class StaffUnionVO implements RowMapper<StaffUnionVO>, Serializable {
private static final long serialVersionUID = 1544023434308856628L; public StaffUnionVO() {
}
  private String code;// 员工编码
  
private String name;// 员工姓名   public String getCode() {
return code;
} public void setCode(String code) {
this.code = code;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}private boolean isExistColumn(ResultSet rs, String columnName) {
try {
if (rs.findColumn(columnName) > 0) {
return true;
}
} catch (SQLException e) {
return false;
} return false;
} @Override
public StaffUnionVO mapRow(ResultSet rs, int row) throws SQLException {
StaffUnionVO vo = new StaffUnionVO();
 
    if (isExistColumn(rs, "code"))
vo.setCode(rs.getString("code"));
    if (isExistColumn(rs, "name"))
vo.setName(rs.getString("name"));
  
    return vo;
}
}

  示例: List<StaffUnionVO> vos = JdbcTemplate.query(sql, new Object[0], new StaffUnionVO() );

2.使用BeanPropertyRowMapper

public class StaffUnionVO implements Serializable {
private static final long serialVersionUID = 1544023434308856628L; public StaffUnionVO() {
} private String code;// 员工编码 private String name;// 员工姓名 public String getCode() {
return code;
} public void setCode(String code) {
this.code = code;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

  示例:List<StaffUnionVO> vos = JdbcTemplate.query(sql, new Object[0], BeanPropertyRowMapper.newInstance(StaffUnionVO.class));

  看一下 BeanPropertyRowMapper.java 的源码,可以学到不少东西。

/*** Eclipse Class Decompiler plugin, copyright (c) 2016 Chen Chao (cnfree2000@hotmail.com) ***/
package org.springframework.jdbc.core; import java.beans.PropertyDescriptor;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.NotWritablePropertyException;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils; public class BeanPropertyRowMapper<T> implements RowMapper<T> {
protected final Log logger = LogFactory.getLog(super.getClass());
private Class<T> mappedClass;
private boolean checkFullyPopulated = false; private boolean primitivesDefaultedForNullValue = false;
private Map<String, PropertyDescriptor> mappedFields;
private Set<String> mappedProperties; public BeanPropertyRowMapper() {
} public BeanPropertyRowMapper(Class<T> mappedClass) {
initialize(mappedClass);
} public BeanPropertyRowMapper(Class<T> mappedClass, boolean checkFullyPopulated) {
initialize(mappedClass);
this.checkFullyPopulated = checkFullyPopulated;
} public void setMappedClass(Class<T> mappedClass) {
if (this.mappedClass == null) {
initialize(mappedClass);
} else if (!(this.mappedClass.equals(mappedClass)))
throw new InvalidDataAccessApiUsageException(
new StringBuilder().append("The mapped class can not be reassigned to map to ").append(mappedClass)
.append(" since it is already providing mapping for ").append(this.mappedClass).toString());
} protected void initialize(Class<T> mappedClass) {
this.mappedClass = mappedClass;
this.mappedFields = new HashMap();
this.mappedProperties = new HashSet();
PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(mappedClass);
for (PropertyDescriptor pd : pds)
if (pd.getWriteMethod() != null) {
this.mappedFields.put(pd.getName().toLowerCase(), pd);
String underscoredName = underscoreName(pd.getName());
if (!(pd.getName().toLowerCase().equals(underscoredName))) {
this.mappedFields.put(underscoredName, pd);
}
this.mappedProperties.add(pd.getName());
}
}
  //在大写的字符前加入下滑线
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 final Class<T> getMappedClass() {
return this.mappedClass;
} public void setCheckFullyPopulated(boolean checkFullyPopulated) {
this.checkFullyPopulated = checkFullyPopulated;
} public boolean isCheckFullyPopulated() {
return this.checkFullyPopulated;
} public void setPrimitivesDefaultedForNullValue(boolean primitivesDefaultedForNullValue) {
this.primitivesDefaultedForNullValue = primitivesDefaultedForNullValue;
} public boolean isPrimitivesDefaultedForNullValue() {
return this.primitivesDefaultedForNullValue;
} public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
Assert.state(this.mappedClass != null, "Mapped class was not specified");
Object mappedObject = BeanUtils.instantiate(this.mappedClass);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(mappedObject);
initBeanWrapper(bw); ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
Set populatedProperties = (isCheckFullyPopulated()) ? new HashSet() : null;//稀少的特性 for (int index = 1; index <= columnCount; ++index) {
String column = JdbcUtils.lookupColumnName(rsmd, index);
PropertyDescriptor pd = (PropertyDescriptor) this.mappedFields
.get(column.replaceAll(" ", "").toLowerCase());
if (pd == null)
continue;
try {
Object value = getColumnValue(rs, index, pd);
if ((this.logger.isDebugEnabled()) && (rowNumber == 0))
this.logger.debug(
new StringBuilder().append("Mapping column '").append(column).append("' to property '")
.append(pd.getName()).append("' of type ").append(pd.getPropertyType()).toString());
try {
bw.setPropertyValue(pd.getName(), value);
} catch (TypeMismatchException e) {
if ((value == null) && (this.primitivesDefaultedForNullValue)) {
this.logger.debug(new StringBuilder().append("Intercepted TypeMismatchException for row ")
.append(rowNumber).append(" and column '").append(column).append("' with value ")
.append(value).append(" when setting property '").append(pd.getName())
.append("' of type ").append(pd.getPropertyType()).append(" on object: ")
.append(mappedObject).toString());
} else {
throw e;
}
}
if (populatedProperties != null) {
populatedProperties.add(pd.getName());
}
} catch (NotWritablePropertyException ex) {
throw new DataRetrievalFailureException(new StringBuilder().append("Unable to map column ")
.append(column).append(" to property ").append(pd.getName()).toString(), ex);
} } if ((populatedProperties != null) && (!(populatedProperties.equals(this.mappedProperties)))) {
throw new InvalidDataAccessApiUsageException(new StringBuilder()
.append("Given ResultSet does not contain all fields necessary to populate object of class [")
.append(this.mappedClass).append("]: ").append(this.mappedProperties).toString());
} return mappedObject;
} protected void initBeanWrapper(BeanWrapper bw) {
} protected Object getColumnValue(ResultSet rs, int index, PropertyDescriptor pd) throws SQLException {
return JdbcUtils.getResultSetValue(rs, index, pd.getPropertyType());
} public static <T> BeanPropertyRowMapper<T> newInstance(Class<T> mappedClass) {
BeanPropertyRowMapper newInstance = new BeanPropertyRowMapper();
newInstance.setMappedClass(mappedClass);
return newInstance;
}
}

  1.通过PropertyDescriptor反映射调用set和get方法

  2.HashSet、TreeSet equals方法

  AbstractSet.java

  public boolean equals(Object o) {
if (o == this)
return true; if (!(o instanceof Set))
return false;
Collection<?> c = (Collection<?>) o;
if (c.size() != size())
return false;
try {
return containsAll(c);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
}

  3.BeanPropertyRowMapper checkFullyPopulated 默认是false,这样的话如果 sql结果集中的字段 和 DTO 字段不匹配,就会抛异常。可以手动设置这个值。

  4.PO BO VO DTO POJO DAO概念及其作用(附转换图)

JdbcTemplate使用小结的更多相关文章

  1. Spring JdbcTemplate操作小结

    Spring 提供了JdbcTemplate 来封装数据库jdbc操作细节: 包括: 数据库连接[打开/关闭] ,异常转义 ,SQL执行 ,查询结果的转换 使用模板方式封装 jdbc数据库操作-固定流 ...

  2. Spring JdbcTemplate小结

    提供了JdbcTemplate 来封装数据库jdbc操作细节: 包括: 数据库连接[打开/关闭] ,异常转义 ,SQL执行 ,查询结果的转换 使用模板方式封装 jdbc数据库操作-固定流程的动作,提供 ...

  3. spring jdbctemplate源码跟踪

    闲着没事,看看源码也是一种乐趣! java操作数据库的基本步骤都是类似的: 1. 建立数据库连接 2. 创建Connection 3. 创建statement或者preparedStateement ...

  4. 编写DAO,通过JdbcTemplate操作数据库的实践

    目的:编写DAO,通过Spring中的JdbcTemplate,对数据库中的学生数据进行增删改查操作. 要操作的数据库表结构为: 一.大体框架 1.要利用JdbcTemplate,首先要添加Sprin ...

  5. 21JDBC_事务&JDBCTemplate

    一.JDBC_事务 通过JDBC来操作银行转账的事务 1.API介绍     Connection接口中与事务有关的方法 void setAutoCommit(boolean autoCommit) ...

  6. 初识JdbcTemplate

    1.spring配置文件里注冊:參照使用 Spring jdbcTemplate 进一步简化 JDBC 操作 2.写javabean 3.写rowmapper(依据javabean来封装结果集) 4. ...

  7. SpringBoot 系列教程之事务隔离级别知识点小结

    SpringBoot 系列教程之事务隔离级别知识点小结 上一篇博文介绍了声明式事务@Transactional的简单使用姿势,最文章的最后给出了这个注解的多个属性,本文将着重放在事务隔离级别的知识点上 ...

  8. SpringBoot2.x入门教程:引入jdbc模块与JdbcTemplate简单使用

    这是公众号<Throwable文摘>发布的第23篇原创文章,收录于专辑<SpringBoot2.x入门>. 前提 这篇文章是<SpringBoot2.x入门>专辑的 ...

  9. JdbcTemplate+PageImpl实现多表分页查询

    一.基础实体 @MappedSuperclass public abstract class AbsIdEntity implements Serializable { private static ...

随机推荐

  1. 【洛谷P1087】FBI树

    题目大意:后序遍历 题解:建立二叉树的码风不知道怎么突然跟线段树一样了...当然,这道题不建树也是可以的. 代码如下 #include <bits/stdc++.h> using name ...

  2. npm 设置地址

    -- 查看当前地址: npm config get registry https://registry.npmjs.org/ npm config get disturl undefined -- 设 ...

  3. 960CSS框架,之前有用过 了解下框架基本原理

    http://blog.sina.com.cn/s/blog_8173443e010160b8.html CSS框架已经出现很长时间了,关于这些框架的用处也被我们讨论了很多遍了.有人说,CSS框架不够 ...

  4. pthread_detach pthread_create实例

    //pool.h 1 #ifndef POOL_H #define POOL_H #include <pthread.h> class pool { public: pool(); ~po ...

  5. 【CSS】定义元素的位置

    CSS定义元素的位置html元素的position属性,有4个属性值,分别是static.relative.fixed.absolute static: 1.默认值,一般不显式设置为static 2. ...

  6. 在“安装”阶段发生异常。 System.Security.SecurityException: 未找到源,但未能

    写Windows服务的时候,运行了一下,就是没反应,命令框一闪而过,查了一下异常,大致是题目的那样.原因是因为权限不足.但是在网上搜的方法都不顶用. 解决方法如下: (1)以管理员身份运行CMD: ( ...

  7. 说说SQL Server的数据类型

    以SQL Server为例,SQL Server的数据类型总共有33种,归纳为一下类别: 精确数字 Unicode字符串 近似数字 二进制字符串 日期和时间 其他数据类型 字符串   1.数字数据类型 ...

  8. 如何把手机app的视频下载到手机上?网页上的视频怎么下载?

    手机上小视频怎么下载?求推荐不需要安装软件的下载方法? 如何把手机app的视频下载到手机上?比如把快手上的视频下载到手机上? 如何免费下载视频? ... 答案当然是用iiiLab提供的在线视频解析下载 ...

  9. 第11月第31天 keyboardwillshow CGAffineTransformMakeTranslation

    1. - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)registerN ...

  10. 关于markdown文件插入图片遇到的小问题和解决办法

    今天用md文件时候发现需要插入图片,以前没做过,所以写下来分享下. 1.先在自己的github上建一个仓库,里面新建个img文件夹存放图片,怎么建仓库可以上网找资料,这里就不详细说明了.建好的仓库如下 ...