spring jdbctemplate 实体属性映射值为null 博客分类: java SpringJPADerbyHibernateMySQL
程序员文章站
2024-02-04 22:30:34
...
今天在做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值失败
太晚了..有时间再详细研究...
总的来说就是下划线造成的.
我艹...讨厌的下划线