1,NamedParameterJdbcTemplate 查询列表

  1. /***测试***/
  2.  
  3. public void queyBeanTest(){
  4. String s = "select * from PT_USER ";
  5.  
  6. List<PtUser> list = namedJdbcTemplate.query(s, new BeanPropertyRowMapper<PtUser>(PtUser.class));
  7.  
  8. System.out.println(list);
  9.  
  10. }

  

2,如果有参数,期间会把  参数绑定的 例如: :name 替换成

源码:getPreparedStatementCreator 方法。 所以最后还是调用  JdbcTemplate  模板。

3,按源码一直走下去。下面是一个抽象类实现的模板方法。

  1. /**
  2. * Query using a prepared statement, allowing for a PreparedStatementCreator
  3. * and a PreparedStatementSetter. Most other query methods use this method,
  4. * but application code will always work with either a creator or a setter.
  5. * @param psc Callback handler that can create a PreparedStatement given a
  6. * Connection
  7. * @param pss object that knows how to set values on the prepared statement.
  8. * If this is null, the SQL will be assumed to contain no bind parameters.
  9. * @param rse object that will extract results.
  10. * @return an arbitrary result object, as returned by the ResultSetExtractor
  11. * @throws DataAccessException if there is any problem
  12. */
  13. public <T> T query(
  14. PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse)
  15. throws DataAccessException {
  16.  
  17. Assert.notNull(rse, "ResultSetExtractor must not be null");
  18. logger.debug("Executing prepared SQL query");
  19.  
  20. return execute(psc, new PreparedStatementCallback<T>() {
  21. @Override
  22. public T doInPreparedStatement(PreparedStatement ps) throws SQLException {
  23. ResultSet rs = null;
  24. try {
  25. if (pss != null) {
  26. pss.setValues(ps);
  27. }
  28. rs = ps.executeQuery();
  29. ResultSet rsToUse = rs;
  30. if (nativeJdbcExtractor != null) {
  31. rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);
  32. }
  33. return rse.extractData(rsToUse);
  34. }
  35. finally {
  36. JdbcUtils.closeResultSet(rs);
  37. if (pss instanceof ParameterDisposer) {
  38. ((ParameterDisposer) pss).cleanupParameters();
  39. }
  40. }
  41. }
  42. });
  43. }

4,因为一开始 我们 用的 BeanPropertyRowMapper 类,也就是用这个类来装载返回的数据。

  一开始new 的时候会初始化方法。

  

  1. /**
  2. * Create a new {@code BeanPropertyRowMapper}, accepting unpopulated
  3. * properties in the target bean.
  4. * <p>Consider using the {@link #newInstance} factory method instead,
  5. * which allows for specifying the mapped type once only.
  6. * @param mappedClass the class that each row should be mapped to
  7. */
  8. public BeanPropertyRowMapper(Class<T> mappedClass) {
  9. initialize(mappedClass);
  10. }

这个方法,其实是把实体类的属性拆分了来存的,例如:userName 存为user_name.

  1. /**
  2. * Initialize the mapping metadata for the given class.
  3. * @param mappedClass the mapped class
  4. */
  5. protected void initialize(Class<T> mappedClass) {
  6. this.mappedClass = mappedClass;
  7. this.mappedFields = new HashMap<String, PropertyDescriptor>();
  8. this.mappedProperties = new HashSet<String>();
  9. PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(mappedClass);
  10. for (PropertyDescriptor pd : pds) {
  11. if (pd.getWriteMethod() != null) {
  12. this.mappedFields.put(lowerCaseName(pd.getName()), pd);
  13. String underscoredName = underscoreName(pd.getName());
  14. if (!lowerCaseName(pd.getName()).equals(underscoredName)) {
  15. this.mappedFields.put(underscoredName, pd);
  16. }
  17. this.mappedProperties.add(pd.getName());
  18. }
  19. }
  20. }

  下面这个方法是最终实现,会把数据库的字段都转成小写。所以也支持Oracle 。

  1. /**
  2. * Extract the values for all columns in the current row.
  3. * <p>Utilizes public setters and result set metadata.
  4. * @see java.sql.ResultSetMetaData
  5. */
  6. @Override
  7. public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
  8. Assert.state(this.mappedClass != null, "Mapped class was not specified");
  9. T mappedObject = BeanUtils.instantiateClass(this.mappedClass);
  10. BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(mappedObject);
  11. initBeanWrapper(bw);
  12.  
  13. ResultSetMetaData rsmd = rs.getMetaData();
  14. int columnCount = rsmd.getColumnCount();
  15. Set<String> populatedProperties = (isCheckFullyPopulated() ? new HashSet<String>() : null);
  16.  
  17. for (int index = 1; index <= columnCount; index++) {
  18. String column = JdbcUtils.lookupColumnName(rsmd, index);
  19. String field = lowerCaseName(column.replaceAll(" ", ""));
  20. PropertyDescriptor pd = this.mappedFields.get(field);
  21. if (pd != null) {
  22. try {
  23. Object value = getColumnValue(rs, index, pd);
  24. if (rowNumber == 0 && logger.isDebugEnabled()) {
  25. logger.debug("Mapping column '" + column + "' to property '" + pd.getName() +
  26. "' of type '" + ClassUtils.getQualifiedName(pd.getPropertyType()) + "'");
  27. }
  28. try {
  29. bw.setPropertyValue(pd.getName(), value);
  30. }
  31. catch (TypeMismatchException ex) {
  32. if (value == null && this.primitivesDefaultedForNullValue) {
  33. if (logger.isDebugEnabled()) {
  34. logger.debug("Intercepted TypeMismatchException for row " + rowNumber +
  35. " and column '" + column + "' with null value when setting property '" +
  36. pd.getName() + "' of type '" +
  37. ClassUtils.getQualifiedName(pd.getPropertyType()) +
  38. "' on object: " + mappedObject, ex);
  39. }
  40. }
  41. else {
  42. throw ex;
  43. }
  44. }
  45. if (populatedProperties != null) {
  46. populatedProperties.add(pd.getName());
  47. }
  48. }
  49. catch (NotWritablePropertyException ex) {
  50. throw new DataRetrievalFailureException(
  51. "Unable to map column '" + column + "' to property '" + pd.getName() + "'", ex);
  52. }
  53. }
  54. else {
  55. // No PropertyDescriptor found
  56. if (rowNumber == 0 && logger.isDebugEnabled()) {
  57. logger.debug("No property found for column '" + column + "' mapped to field '" + field + "'");
  58. }
  59. }
  60. }
  61.  
  62. if (populatedProperties != null && !populatedProperties.equals(this.mappedProperties)) {
  63. throw new InvalidDataAccessApiUsageException("Given ResultSet does not contain all fields " +
  64. "necessary to populate object of class [" + this.mappedClass.getName() + "]: " +
  65. this.mappedProperties);
  66. }
  67.  
  68. return mappedObject;
  69. }

总结: 因为源码就是这样写死的。所以要约定装配实体类。

SpringBoot JDBC 源码分析之——NamedParameterJdbcTemplate 查询数据返回bean对象的更多相关文章

  1. Solr4.8.0源码分析(5)之查询流程分析总述

    Solr4.8.0源码分析(5)之查询流程分析总述 前面已经写到,solr查询是通过http发送命令,solr servlet接受并进行处理.所以solr的查询流程从SolrDispatchsFilt ...

  2. Mybatis源码分析--关联表查询及延迟加载原理(二)

    在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...

  3. 【原创】005 | 搭上SpringBoot请求处理源码分析专车

    前言 如果这是你第二次看到师长,说明你在觊觎我的美色! 点赞+关注再看,养成习惯 没别的意思,就是需要你的窥屏^_^ 专车介绍 该趟专车是开往Spring Boot请求处理源码分析专车,主要用来分析S ...

  4. HDFS源码分析心跳汇报之数据块汇报

    在<HDFS源码分析心跳汇报之数据块增量汇报>一文中,我们详细介绍了数据块增量汇报的内容,了解到它是时间间隔更长的正常数据块汇报周期内一个smaller的数据块汇报,它负责将DataNod ...

  5. Django之DRF源码分析(二)---数据校验部分

    Django之DRF源码分析(二)---数据校验部分 is_valid() 源码 def is_valid(self, raise_exception=False): assert not hasat ...

  6. 【原创】002 | 搭上SpringBoot事务源码分析专车

    前言 如果这是你第二次看到师长,说明你在觊觎我的美色! 点赞+关注再看,养成习惯 没别的意思,就是需要你的窥屏^_^ 专车介绍** 该趟专车是开往Spring Boot事务源码分析的专车 专车问题 为 ...

  7. Spring源码分析(十八)创建bean

    本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.创建bean的实例 1. autowireConstructor 2 ...

  8. HDFS源码分析心跳汇报之数据块增量汇报

    在<HDFS源码分析心跳汇报之BPServiceActor工作线程运行流程>一文中,我们详细了解了数据节点DataNode周期性发送心跳给名字节点NameNode的BPServiceAct ...

  9. 源码分析:Exchanger之数据交换器

    简介 Exchanger是Java5 开始引入的一个类,它允许两个线程之间交换持有的数据.当Exchanger在一个线程中调用exchange方法之后,会阻塞等待另一个线程调用同样的exchange方 ...

随机推荐

  1. Sitecore CMS中查看标准字段

    什么是标准字段? 标准字段是字段及其字段组的集合,用于包含有关Sitecore中项目的可配置元数据.Sitecore中继承自“标准模板”模板的任何项目都将包含这些字段. 可以在“标准模板”模板项找到/ ...

  2. IOS 开发体验测试问题

    1.键盘收起体验 a. 文本键盘会收起,但是表情包.添加视频的键盘不会收起: b. 在会话场景中,同时进行一个点击输入框,一个向下滑,输入框中的聚焦的竖直细线不会消失:

  3. this上下文一致

    什么是this对象 先来说说什么是this对象吧,每个函数在调用的时候都会自动获取两个特殊变量:this和arguments对象.this值具体是指哪个对象是和该函数的执行环境相关的.如果是作为对象的 ...

  4. Linux基础命令---添加用户useradd

    useradd 创建新的系统用户,useradd指令只能以管理员的身份运行,创建的用户都在“/etc/passwd”文件中.当不加-D参数,useradd指令使用命令列来指定新帐号的设定值and使用系 ...

  5. 【JavaScript 6连载】五、继承的概念

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  6. html div重叠问题,原因分析和处理

    1.现象 <!DOCTYPE html > <html> <head> <meta http-equiv="Content-Type" c ...

  7. jenkins3

    Jenkins是基于java开发的. GitHub Git (熟练使用) Doocker (了解) Jenkins (熟练使用) Django (熟练使用) Angularjs (了解) Sentry ...

  8. 新做了块avr开发板--tft屏研究用

    2010-05-04 14:03:00 测试效果不错,使用也方便.

  9. QT -- plan

     QT  --  跨平台的 C++ 图形用户界面  应用程序框架 GUI介绍框架项目文件  .pro第一个QT (hello QT)父窗口 和 子窗口的区别(控件,部件,构件)信号 和 槽(信号的处理 ...

  10. Codeforces 237A - Free Cash

    题目链接:http://codeforces.com/problemset/problem/237/A Valera runs a 24/7 fast food cafe. He magically ...