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;
	}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐