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. oracle执行update语句时卡住问题分析及解决办法

    转载:http://www.jb51.net/article/125754.htm 这篇文章主要介绍了oracle执行update语句时卡住问题分析及解决办法,涉及记录锁等相关知识,具有一定参考价值, ...

  2. opencv ---getRotationMatrix2D函数

    getRotationMatrix2D函数 主要用于获得图像绕着 某一点的旋转矩阵  Mat getRotationMatrix2D(Point2f center, double angle, dou ...

  3. cygwin简介及使用

    一个是真实的假货,一个是冒牌的真品前指 Cygwin,后指 Linux/VMWare 路不管平还是陡,终归你要走的,如果你愿意投入到linux开发的社群中来,不会安装linux系统,不会配置工作环境是 ...

  4. HDU 6158 笛卡尔定理+韦达定理

    The Designer Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  5. linux常用端口查询

    0 | 无效端口,通常用于分析操作系统1 | 传输控制协议端口服务多路开关选择器2 | 管理实用程序3 | 压缩进程5 | 远程作业登录7 | 回显9 | 丢弃11 | 在线用户13 | 时间17 | ...

  6. Spark记录-Spark on mesos配置

    1.安装mesos #用centos6的源yum安装 # rpm -Uvh http://repos.mesosphere.io/el/6/noarch/RPMS/mesosphere-el-repo ...

  7. 流媒体技术学习笔记之(九)减少VLC 延迟的方法

    之前写过一篇关于在Linux平台上编译Android平台上VLC播放器源代码的文章,vlc这款播放器非常优秀而且是开源的,它的核心是开源视频编解码库ffmpeg.而且这款播放器还支持RTSP协议,这个 ...

  8. springboot(五):springboot整合shiro-登录认证和权限管理

    http://z77z.oschina.io/ http://www.cnblogs.com/aqsunkai/category/982003.html https://www.cnblogs.com ...

  9. Zookeeper笔记之四字命令

    Zookeeper支持一些命令用来获取服务的状态和相关信息,因为这些命令都是四个字母的,所以一般称为四字命令. 四字命令可以使用telnet或者nc向服务器提交,使用下面这个脚本可以当做是一个简易的客 ...

  10. MySQL-数据操作-增删改查

    1.增加: insert into 表 (列名,列名...) values (值,值,值...) insert into 表 (列名,列名...) values (值,值,值...),(值,值,值.. ...