jdbcTemplate的使用,RowMapper实现类:BeanPropertyRowMapper和SingleColumnRowMapper

RowMapper匿名类使用

这里直接一个个设置返回实体类的属性

 public Student getStudentByName(String name) {
        String sql = "select id,name from student where name = ?";
        Student student = this.jdbcTemplate.queryForObject(sql, new Object[]{name}, new RowMapper<Student>() {
            @Override
            public Student mapRow(ResultSet rs, int i) throws SQLException {
                Student s = new Student();
                s.setId(rs.getString("id"));
                s.setName(rs.getString("name"));
                return s;
            }
        });
        return student;
    }

SingleColumnRowMapper使用

当查询单个字段时,可以直接使用SingleColumnRowMapper

   public String getStudentNameById(String id) {
       String sql = "select name from test_student where id = ?";
       return this.jdbcTemplate.queryForObject(sql, new Object[]{id},
               new SingleColumnRowMapper<>(String.class));
   }

BeanPropertyRowMapper使用

当查询字段多,或者你想直接偷懒,就用他,他源代码的实现方法已经实现了忽略大小写、驼峰命名转换的映射,不用再自己一个个set属性,方便简单,什么狗屁效率,快速开发就完事了。

public Student getStudentByName(String name) {
        String sql = "select id,name from student where name = ?";
        Student student = this.jdbcTemplate.queryForObject(sql, new Object[]{name}, new BeanPropertyRowMapper<>(Student.class));
        return student;
	}

附录BeanPropertyRowMapper源代码实现

initialize函数
  • 使用mappedClass poclass储存起来
  • po实体类的field小写field转驼峰小写放入mappedFields属性,以供后面映射使用
	public BeanPropertyRowMapper(Class<T> mappedClass) {
		initialize(mappedClass);
	}

	/**
	 * Initialize the mapping meta-data for the given class.
	 * @param mappedClass the mapped class
	 */
	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(lowerCaseName(pd.getName()), pd);
				String underscoredName = underscoreName(pd.getName());
                //这里将所以对象属性名称转为驼峰命名放入
				if (!lowerCaseName(pd.getName()).equals(underscoredName)) {
					this.mappedFields.put(underscoredName, pd);
				}
				this.mappedProperties.add(pd.getName());
			}
		}
	}
实现mapRow()方法

这个方法,就是将查询数据库字段的值赋予对应对象属性。

	/**
	 * Extract the values for all columns in the current row.
	 * <p>Utilizes public setters and result set meta-data.
	 * @see java.sql.ResultSetMetaData
	 */
	@Override
	public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
		Assert.state(this.mappedClass != null, "Mapped class was not specified");
		T mappedObject = BeanUtils.instantiateClass(this.mappedClass);
		BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(mappedObject);
		initBeanWrapper(bw);

		ResultSetMetaData rsmd = rs.getMetaData();
		int columnCount = rsmd.getColumnCount();
		Set<String> populatedProperties = (isCheckFullyPopulated() ? new HashSet<>() : null);
   		//这里会根据数据库查询出的字段名称,从mappedFields获取字段,设置value
		for (int index = 1; index <= columnCount; index++) {
			// 获取数据库结果rs的字段名column 
			String column = JdbcUtils.lookupColumnName(rsmd, index);
			// column 转换小写,变量名=field 
			String field = lowerCaseName(column.replaceAll(" ", ""));
			// 获取column 对应的po的属性的PropertyDescriptor 
			PropertyDescriptor pd = (this.mappedFields
mappedFields != null ? this.mappedFields.get(field) : null);
			if (pd != null) {
				try {
					// 使用rs、index,pd的class,获取column的值并转换成value
					Object value = getColumnValue(rs, index, pd);
					if (rowNumber == 0 && logger.isDebugEnabled()) {
						logger.debug("Mapping column '" + column + "' to property '" + pd.getName() +
								"' of type '" + ClassUtils.getQualifiedName(pd.getPropertyType()) + "'");
					}
					try {
						bw.setPropertyValue(pd.getName(), value);
					}
					catch (TypeMismatchException ex) {
						if (value == null && this.primitivesDefaultedForNullValue) {
							if (logger.isDebugEnabled()) {
								logger.debug("Intercepted TypeMismatchException for row " + rowNumber +
										" and column '" + column + "' with null value when setting property '" +
										pd.getName() + "' of type '" +
										ClassUtils.getQualifiedName(pd.getPropertyType()) +
										"' on object: " + mappedObject, ex);
							}
						}
						else {
							throw ex;
						}
					}
					if (populatedProperties != null) {
						populatedProperties.add(pd.getName());
					}
				}
				catch (NotWritablePropertyException ex) {
					throw new DataRetrievalFailureException(
							"Unable to map column '" + column + "' to property '" + pd.getName() + "'", ex);
				}
			}
			else {
				// No PropertyDescriptor found
				if (rowNumber == 0 && logger.isDebugEnabled()) {
					logger.debug("No property found for column '" + column + "' mapped to field '" + field + "'");
				}
			}
		}

		if (populatedProperties != null && !populatedProperties.equals(this.mappedProperties)) {
			throw new InvalidDataAccessApiUsageException("Given ResultSet does not contain all fields " +
					"necessary to populate object of class [" + this.mappedClass.getName() + "]: " +
					this.mappedProperties);
		}

		return mappedObject;
	}
在你提供的引用中,你遇到了一个错误消息" Incorrect column count: expected 1, actual 42"。这个错误消息表示实际返回的列数与期望的列数不一致。根据你的描述,你使用的是jdbcTemplate的queryForList方法,它期望返回单列对象或者返回一个包含多个列的List<Map<String, Object>>对象。 根据你的代码和问题描述,我猜测你在使用queryForList方法时可能出现了以下问题: 1. 你的SQL查询语句返回了42列,而queryForList方法期望只返回1列。 2. 你可能没有正确地配置单列映射器(singleColumnRowMapper),导致报错。 要解决这个问题,你可以尝试以下几点: 1. 确认你的SQL查询语句是否正确,确保它只返回了1列。如果你的SQL查询语句返回了多列,你可以考虑使用query方法并结合BeanPropertyRowMapper来直接返回对象集合。 2. 确认你正确配置了单列映射器(singleColumnRowMapper)。你需要确保映射器的列数与实际返回的列数一致。 综上所述,你遇到的错误是由于实际返回的列数与期望的列数不一致所导致的。你可以通过检查SQL查询语句和正确配置单列映射器来解决这个问题。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [jdbcTemplate报错:Incorrect column count: expected 1, actual 2](https://blog.csdn.net/happy488127311/article/details/120591563)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [EurekaLog_7.5.0.0_Enterprise](https://download.csdn.net/download/jsdf007/9683759)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值