关闭

PropertyNotFoundException:could not find a setter forXXX

标签: setterhibernatestringtablejdk
1561人阅读 评论(0) 收藏 举报

使用过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 如下:

<hibernate-mapping package="gmt.boss.interfaces.customer.po">

<class name="TAccount" table="T_ACCOUNT">

<property name="gAccountId" column="G_ACCOUNT_ID" type="java.lang.String" />

**********

所以我一直认识配制的没有错误,但是一到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 显然和 <property name="gAccountId" column="G_ACCOUNT_ID" type="java.lang.String" />无法匹配,抛出

PropertyNotFoundException 也就很自然了。

最后把配制文件改成

<property name="gaccountId" column="G_ACCOUNT_ID" type="java.lang.String" />

抽像类改成

private String gaccountId;

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

问题 OK了。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:72102次
    • 积分:1440
    • 等级:
    • 排名:千里之外
    • 原创:58篇
    • 转载:11篇
    • 译文:13篇
    • 评论:13条
    博客专栏
    github地址:https://github.com/juine
    最新评论