2011-03-23 56 views
2

我使用的是Hibernate 3.6,JPA 2.0和Spring 3.0.6。我在我的對象,如以下字段:在Hibernate/JPA中,字段名稱是否以單個字母駝峯開頭?

class PersonContact { 
    Long eAddressCpId; 
    ElectronicAddress eAddress; 
} 

我使用字段訪問(在我的ORM文件)和查詢/插入/等工作沒有問題。這些字段既在類中,也在orm文件中。但在應用程序的啓動,JPA配置負載吐出警告:

 
2011-02-22 15:38:10,785 [[STANDBY] ExecuteThread: '3' for queue: 'weblogic.kernel.Default (self-tuning)'] WARN org.hibernate.cfg.annotations.reflection.JPAOverridenAnnotationReader - Property com.foo.model.contactpoint.ElectronicAddress.eAddress not found in class but described in (possible typo error) 
2011-02-22 15:38:10,801 [[STANDBY] ExecuteThread: '3' for queue: 'weblogic.kernel.Default (self-tuning)'] WARN org.hibernate.cfg.annotations.reflection.JPAOverridenAnnotationReader - Property com.foo.model.person.PersonContact.eAddressCpId not found in class but described in (possible typo error) 
2011-02-22 15:38:10,801 [[STANDBY] ExecuteThread: '3' for queue: 'weblogic.kernel.Default (self-tuning)'] WARN org.hibernate.cfg.annotations.reflection.JPAOverridenAnnotationReader - Property com.foo.model.person.PersonContact.eAddress not found in class but described in (possible typo error) 
2011-02-22 15:38:10,817 [[STANDBY] ExecuteThread: '3' for queue: 'weblogic.kernel.Default (self-tuning)'] WARN org.hibernate.cfg.annotations.reflection.JPAOverridenAnnotationReader - Property com.foo.model.person.PartyContact.eAddressCpId not found in class but described in (possible typo error) 
2011-02-22 15:38:10,817 [[STANDBY] ExecuteThread: '3' for queue: 'weblogic.kernel.Default (self-tuning)'] WARN org.hibernate.cfg.annotations.reflection.JPAOverridenAnnotationReader - Property com.foo.model.person.PartyContact.eAddress not found in class but described in (possible typo error) 

如果我改變我的字段名是electronicAddressCpId和electronicAddress,然後我沒有得到這些警告。

圍繞字段名稱有要求嗎?

謝謝.jay

---------附加信息--------------------------- ----- 這是我的POJO片段。

/** 
* This is a generated class. Do not modify. 
*/ 
@XmlRootElement(namespace = "http://foo.com/model", name = "ElectronicAddress") 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(namespace = "http://foo.com/model", name = "ElectronicAddress", propOrder = { "eAddress", "id" }) 
public class ElectronicAddress extends ContactPoint { 

    /** 
    * The serialize value. 
    */ 
    private static final long serialVersionUID = -1L; 
    /** 
    * The eAddress field. 
    */ 
    @XmlElement(name = "EAddress", namespace = "##default") 
    private String eAddress; 
    /** 
    * The id field. 
    */ 
    @XmlElement(name = "Id", namespace = "##default") 
    private Long id; //NOPMD 

    /** 
    * Gets the value of the eAddress property. 
    * This field is Required. 
    * 
    * @return eAddress object is {@link String } 
    */ 
    public String getEAddress() { 
     return eAddress; 
    } 

    /** 
    * Sets the value of the eAddress property. 
    * This field is Required 
    * 
    * @param eAddress object is {@link String } 
    */ 
    public void setEAddress(String eAddress) { 
     this.eAddress = eAddress; 
    } 

    /** 
    * Gets the value of the id property. 
    * This field is Optional. 
    * 
    * @return id object is {@link Long } 
    */ 
    public Long getId() { 
     return id; 
    } 

    /** 
    * Sets the value of the id property. 
    * This field is Optional 
    * genericInheritGetterSetter 
    * @param id object is {@link Long } 
    */ 
    public void setId(Long id) { 
     this.id = (Long) id; 
    } 

} 

這是一個orm文件的片段。

<?xml version="1.0" encoding="UTF-8"?> 
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm 
    http://java.sun.com/xml/ns/persistence/orm_2_0.xsd" 
    version="2.0"> 
    <description>com.foo.model.ElectronicAddress Entity Mapping</description> 
    <package>com.foo.model</package> 
    <schema>COMMON</schema> 
    <access>FIELD</access> 
    <entity class="com.foo.model.ElectronicAddress" 
     access="FIELD" metadata-complete="true"> 
     <table name="ELECTRONIC_ADDRESSES" /> 
     <attributes> 
      <id name="id"> 
       <column name="ELECTRONIC_ADDRESS_ID" /> 
       <generated-value strategy="SEQUENCE" generator="ADDR_SEQ" /> 
       <sequence-generator name="ADDR_SEQ" 
        sequence-name="COMMON.ADDR_SEQ" allocation-size="1" /> 
      </id> 
      <basic name="eAddress"> 
       <column name="ELECTRONIC_ADDRESS" /> 
      </basic> 
     </attributes> 
    </entity> 
</entity-mappings> 

回答

1

我發現這個問題,它是在JPAOverridenAnnotationReader方法checkForOrphanProperties的一部分:

for (Method method : clazz.getMethods()) { 
    String name = method.getName(); 
    if (name.startsWith("get")) { 
     properties.add(Introspector.decapitalize(name.substring("get".length()))); 
    } 
    else if (name.startsWith("is")) { 
     properties.add(Introspector.decapitalize(name.substring("is".length()))); 
    } 
} 

的問題是,該方法查找所有公共字段,然後開始加入基於「get」和字段名「是「它找到的方法。 Introspector.decapitalize方法利用特定規則來確定解除資本化的內容。

從Introspector類:

/** 
* Utility method to take a string and convert it to normal Java variable 
* name capitalization. This normally means converting the first 
* character from upper case to lower case, but in the (unusual) special 
* case when there is more than one character and both the first and 
* second characters are upper case, we leave it alone. 
* <p> 
* Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays 
* as "URL". 
* 
* @param name The string to be decapitalized. 
* @return The decapitalized version of the string. 
*/ 
public static String decapitalize(String name) { 
if (name == null || name.length() == 0) { 
    return name; 
} 
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) && 
     Character.isUpperCase(name.charAt(0))){ 
    return name; 
} 
char chars[] = name.toCharArray(); 
chars[0] = Character.toLowerCase(chars[0]); 
return new String(chars); 
} 

因此,例如,我們的領域是:

private String eAddress; 

而我們的獲取方法爲:

public String getEAddress() { 
     return eAddress; 
} 

因此,基於該Introspector.decapitalize功能,資產不足的結果將是「電子地址」,而不是「電子地址」。因爲當代碼從「獲得」中抽出時,它會在「EAddress」中看到兩個大寫字母......它不會使這些字母去除數據。因此它抱怨orm.xml中的eAddress字段不存在。該領域的持久性工作完全正常,這些警告只是在戰爭開始時以及啓動文件時出現。

1

這是JPAOverridenAnnotationReader相關的代碼(我使用的是3.5.6,但可能並沒有太大的改變):

Element element = tree != null ? tree.element("attributes") : null; 
//put entity.attributes elements 
if (element != null) { 
    //precompute the list of properties 
    //TODO is it really useful... 
    Set<String> properties = new HashSet<String>(); 
    for (Field field : clazz.getFields()) { 
     properties.add(field.getName()); 
    } 
    for (Method method : clazz.getMethods()) { 
     String name = method.getName(); 
     if (name.startsWith("get")) { 
      properties.add(Introspector.decapitalize(name.substring("get".length()))); 
     } 
     else if (name.startsWith("is")) { 
      properties.add(Introspector.decapitalize(name.substring("is".length()))); 
     } 
    } 
    for (Element subelement : (List<Element>) element.elements()) { 
     String propertyName = subelement.attributeValue("name"); 
     if (!properties.contains(propertyName)) { 
      log.warn("Property {} not found in class" 
        + " but described in <mapping-file/> (possible typo error)", 
        StringHelper.qualify(className, propertyName)); 
     } 
    } 
} 

我沒有看到那裏的錯誤你描述應該發生。

此代碼:

for (Field field : clazz.getFields()) { 
    properties.add(field.getName()); 
} 

添加所有字段名和驗證碼

if (!properties.contains(propertyName)) { 
    log.warn("Property {} not found in class" 
     + " but described in <mapping-file/> (possible typo error)", 
     StringHelper.qualify(className, propertyName)); 

檢查是否在XML映射字段名的類存在。這些都沒有做任何字符串處理(字符串處理只對方法完成)。我會說你在某個地方有一個錯字。

+0

我花了相當多的時間來回應,但這絕對不是我們在生產中運行時的錯字,所有Hibernate持久化都能成功運行,而且orm文件是由代碼生成的,而不是開發人員操縱的,我們只是獲取這些消息(每個以小寫字母開頭的字段至少大約60+)。此外,我沒有使用註釋,我使用HBM文件......這是否有差異。 – 2012-01-25 20:16:40

相關問題