spring jdbctemplate 实体属性映射值为null

今天在做mysql和derby数据迁移的时候出现个问题.实体的某些属性经常获取不到值.总是为null

方法如下:

 

 public List<Test1> getTestAll() {
        String sql = "select * from Test";
        List<Test1> l = null;
        try {
            l = getSimpleJdbcTemplate().query(sql,
                    ParameterizedBeanPropertyRowMapper.newInstance(Test.class),
                    new Object[]{});
        } catch (DaoException e) {
            logger.error(e);
            throw e;
        }
        return l;
    }

 

 

 下图为test表的字段


 

 

下面是数据库对应的实体文件Test

 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Column(name = "T_CurTag")
    private String tCurTag;
    @Column(name = "R_IsDel")
    private Integer rIsDel;
    @Column(name = "CPicPath")
    private String cPicPath;
    //get set方法省略...

 

实体文件使用hibernate jpa生成的

 

 

方法执行完毕之后.返回的list中取出实体对象test发现.

tCurTag,rIsDel值都为null.

很纳闷.自己瞅瞅几个字段区别也就在大小写和下划线了.

于是乎改了改.

数据库的字段变成了

T_Curtag,R_Isdel         正确

T_Cur_Tag,R_Is_Del    正确

TCurTag,RIsDel            正确

 

通过研究发现..java的命名规范还是有用的.

如果命名为

T_CurTag那么生成的属性就是tCurTag.通过看spring jdbctemplate的源码发现.

如果属性的名称不符合java的规范(还是jdbc的规范?)则会造成属性值映射失败的现象

 

首先根据这句

 

 ParameterizedBeanPropertyRowMapper.newInstance(Test1.class),

 

 查看其源码:

 

public static <T> ParameterizedBeanPropertyRowMapper<T> newInstance(Class<T> mappedClass) {
		ParameterizedBeanPropertyRowMapper<T> newInstance = new ParameterizedBeanPropertyRowMapper<T>();
		newInstance.setMappedClass(mappedClass);
		return newInstance;
	}
 

 

继续找这句

 

newInstance.setMappedClass(mappedClass);
 

 

 

 

         /**
	 * Set the class that each row should be mapped to.
	 */
	public void setMappedClass(Class mappedClass) {
		if (this.mappedClass == null) {
			initialize(mappedClass);
		}
		else {
			if (!this.mappedClass.equals(mappedClass)) {
				throw new InvalidDataAccessApiUsageException("The mapped class can not be reassigned to map to " +
						mappedClass + " since it is already providing mapping for " + this.mappedClass);
			}
		}
	}
 

 

然后是这句

 

initialize(mappedClass);

 

 找到这里.

 

 

/**
	 * Initialize the mapping metadata for the given class.
	 * @param mappedClass the mapped class.
	 */
	protected void initialize(Class mappedClass) {
		this.mappedClass = mappedClass;
		this.mappedFields = new HashMap();
		this.mappedProperties = new HashSet();
		PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(mappedClass);
		for (int i = 0; i < pds.length; i++) {
			PropertyDescriptor pd = pds[i];
			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());
			}
		}
	}

 

 

终于找到关键代码:

 

 

    /**
     * Convert a name in camelCase to an underscored name in lower case.
     * Any upper case letters are converted to lower case with a preceding underscore.
     * @param name the string containing original name
     * @return the converted name
     */
    private String underscoreName(String name) {
        StringBuffer result = new StringBuffer();
        if (name != null && name.length() > 0) {
            //把第一个字母小写了
            result.append(name.substring(0, 1).toLowerCase());
            for (int i = 1; i < name.length(); i++) {
                //获取第二个字母
                String s = name.substring(i, i + 1);
                //如果第二个字母是大写的
                if (s.equals(s.toUpperCase())) {
                    //给他添加下划线
                    result.append("_");
                    //然后加上第三个小写字母
                    result.append(s.toLowerCase());
                } else {
                    //或者直接返回
                    result.append(s);
                }
            }
        }
        return result.toString();
    }

 

 

执行完这段代码发现.

 

CPicPath被替换成了c_pic_path

T_CurTag被替换成了t_cur_tag和tcurtag

但是却没有一个和tCurTag替换出来的属性一样.所以实体的这个属性最终没有set到值

不知道我说的对不....个人理解.因为spring的有段源码实在看不懂..只能瞎猜了.

具体的原因是因为字段的下划线.所以在获取方法.根据set方法设置属性的时候发生了错位.造成set值失败

太晚了..有时间再详细研究...

总的来说就是下划线造成的.

 

我艹...讨厌的下划线

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
jdbcTemplateSpring框架中用于简化JDBC操作的一个模板类,query方法是其中的一个常用方法,用于执行SQL查询语句并返回结果集。 query方法有多个重载,其中一个常用的重载方法的参数如下: ```java public <T> List<T> query(String sql, Object[] args, RowMapper<T> rowMapper) throws DataAccessException; ``` 解释一下每个参数的含义: 1. sql:要执行的SQL语句,可以包含占位符(?); 2. args:一个Object数组,用于替换SQL语句中的占位符。数组中的每个元素将按照顺序依次替换占位符,如果没有占位符则可以传入一个空数组或者null; 3. rowMapper:一个RowMapper类型的对象,用于将查询结果的每一行映射为一个Java对象。RowMapper是一个接口,一般使用Lambda表达式或匿名内部类来实现。 例如,以下代码演示了如何使用query方法查询数据库中的所有用户信息: ```java List<User> userList = jdbcTemplate.query("SELECT * FROM user", new Object[]{}, new RowMapper<User>() { @Override public User mapRow(ResultSet resultSet, int i) throws SQLException { User user = new User(); user.setId(resultSet.getInt("id")); user.setName(resultSet.getString("name")); user.setAge(resultSet.getInt("age")); return user; } }); ``` 这个例子中,第一个参数是SQL查询语句,第二个参数是一个空数组,表示没有占位符需要替换,第三个参数是一个RowMapper对象,用于将查询结果中的每一行映射为一个User对象。最终返回的是一个包含所有用户信息的List<User>对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值