PropertyNotFoundException:could not find a setter forXXX

使用过hibernate的同事一定对PropertyNotFoundException异常非常熟悉,产生原因也很好找,通常的错误原因有:

1. hibernate配制文件错误,属性里有空格等。

2.是get方法和属性不对应。

但是今天在开发过程中发现配制文件 和 get方法都没有错误,但是还是报PropertyNotFoundException异常。

PO 抽像类如下:

private String gAccountId;

/**
* getGAccountId描述:
*
* @return 返回 gAccountId。
*/
public String getGAccountId()
{
return gAccountId;
}

/**
* setGAccountId描述:
*
* @param accountId 要设置的 gAccountId。
*/
public void setGAccountId(String accountId)
{
gAccountId = accountId;
}

hib.xml 如下:

**********

所以我一直认识配制的没有错误,但是一到buildSessionFactory时就报异常。

想了很久发现 get 方法最可能出错,于是把getGAccountId() 改成getgAccountId();显然这是不符合javabean的命名规范的,但是问题竟然解决了。反编译了hibbernate代码发现hibbernate是这么处理的,首先利用配制文件的package 和 name 找到要映射到的类,按上面的配制文件就是 gmt.boss.interfaces.customer.po.TAccount,然后利用反射取出这个类的信息,取的时候利用了缓存的机制,不是每次都反射一次。然后用这个类的信息中的get,set方法 和 配制文件中进行匹配。以上面的getGAccountId()为例, 先去掉这个方法中的前三位取余下的部分为flag1 = GAccountId,然后调用jdk中的Introspector.decapitalize把这个字符串dropCase 得到flag2, 然而 Introspector.decapitalize dropCase的过程,如果这个字符串开头为一个以上的大写字母,那就不做任何操作反回原串,,所以flag2 =GAccountId 。

匹配的过程为只要 flag1 与flag2 中有一个和 配制文件中的property name一致就为正确的映射。GAccountId 显然和 无法匹配,抛出

PropertyNotFoundException 也就很自然了。

最后把配制文件改成

抽像类改成

private String gaccountId;

/**
* getGAccountId描述:
*
* @return 返回 gAccountId。
*/
public String getGaccountId()
{
return gaccountId;
}

问题 OK了。

你可能感兴趣的:(setter,hibernate,string,table,jdk)