论坛首页 Java企业应用论坛

分析Hibernate在做ORM中的属性大小写的问题

浏览 7542 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-06-10  

在利用hibernate做ORM时,如果对于hbm文件的属性,在java的pojo类中没有对应的get和set方法,则会产生如下异常:

java 代码
  1. Caused by: org.hibernate.PropertyNotFoundException: Could not find a getter for auditInfos    
  2. in class EventType   
  3. at org.hibernate.property.BasicPropertyAccessor.createGetter(BasicPropertyAccessor.java:282)   
  4. at org.hibernate.property.BasicPropertyAccessor.getGetter(BasicPropertyAccessor.java:275)   
  5. at org.hibernate.mapping.Property.getGetter(Property.java:272)  

但是今天遇到了一种情况,就是写上某个属性的get和set方法时,同样会出现该异常,该pojo的属性是eTypeName则对应的方法名称为getETypeName();跟踪hibernate的堆栈报错信息,查找到:

org.hibernate.property.BasicPropertyAccessor.createGetter的private static Method getterMethod(Class theClass, String propertyName)方法,其中对于get的处理逻辑是这样的:

java 代码
  1. private static Method getterMethod(Class theClass, String propertyName) {   
  2.   
  3.     Method[] methods = theClass.getDeclaredMethods();   
  4.     for (int i=0; i
  5.         // only carry on if the method has no parameters   
  6.         if ( methods[i].getParameterTypes().length==0 ) {   
  7.             String methodName = methods[i].getName();   
  8.   
  9.             // try "get"   
  10.             if ( methodName.startsWith("get") ) {   
  11.                 String testStdMethod = Introspector.decapitalize( methodName.substring(3) );   
  12.                 String testOldMethod = methodName.substring(3);   
  13.                 if ( testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName) ) {   
  14.                     return methods[i];   
  15.                 }   
  16.   
  17.             }   
  18.   
  19.             // if not "get" then try "is"   
  20.             /*boolean isBoolean = methods[i].getReturnType().equals(Boolean.class) ||  
  21.                 methods[i].getReturnType().equals(boolean.class);*/  
  22.             if ( methodName.startsWith("is") ) {   
  23.                 String testStdMethod = Introspector.decapitalize( methodName.substring(2) );   
  24.                 String testOldMethod = methodName.substring(2);   
  25.                 if ( testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName) ) {   
  26.                     return methods[i];   
  27.                 }   
  28.             }   
  29.         }   
  30.     }   
  31.     return null;   
  32. }  

这里methodName的值为getETypeName,propertyName的值为eTypeName,利用java.beans.Introspector进行对第一个字母的小写化操作得到testStdMethod,去掉get得到的是testOldMethod。

但是问题就出来了,前者的小写操作是有前提的,根据源码可知:

java 代码
  1.    public static String decapitalize(String name) {   
  2. if (name == null || name.length() == 0) {   
  3.     return name;   
  4. }   
  5. if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&   
  6.         Character.isUpperCase(name.charAt(0))){   
  7.     return name;   
  8. }   
  9. char chars[] = name.toCharArray();   
  10. chars[0] = Character.toLowerCase(chars[0]);   
  11. return new String(chars);   
  12.    }  

对于第一个字符和第二个字符都是大写的情况下,则返回的是原来的字符,因此在这种情况下,去掉get的ETypeName在decapitalize之后仍然是ETypeName,所以两者都得到的是ETypeName,而不再执行第14行代码,所以private static Method getterMethod(Class theClass, String propertyName)得到的是null,因此会产生对于某某属性找不到get方法的异常出来。

解决办法可以将getETypeName改成geteTypeName,或者干脆将属性名改成ETypeName。

   发表时间:2007-06-10  
和Hibernate有什么关系,这是JavaBean的规范。好好读读JavaBean的规范。
0 请登录后投票
   发表时间:2007-06-15  
标准的javabean规范是要求
属性第一个字母小写 如:abcDef
相应属性的方法  getAbcDef()
              setAbcDef()
另外,eclipse的代码自动补全功能会自动为你生成符合规范的JavaBean的:)
0 请登录后投票
   发表时间:2007-06-15  
楼上说的没错,但是我说的情况是属性名称第一个字母小写,第二个字母大写,例如:eTypeName,则按照javabean specification规定的getter方法为getETypeName,则会出现找不到getter方法的错误。
今天看了一下javabean specification,规定了一般的属性名称首字母小写,如果遇到前两个字母大写的属性,则getter方法保持属性名称不变,例如URL属性的getter方法为getterURL,但是并没有规定类似eTypeName这样的属性的getter方法写成geteTypeName的形式。
0 请登录后投票
   发表时间:2007-06-15  
如果要符合javabean规范,则只能将eTypeName改成ETypeName,把getter方法改成geteTypeName只是一个tricky的做法。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics