首页 > 解决方案 > Crieria.Root 类无法获取作为复合键属性的本地属性

问题描述

我有实体类 UniversityBasicInformation.java 和 UniversityBasicInformation.hbm.xml 文件。我想写一个条件查询。我的代码出现错误root.get("surveyYear"), surveyYear)

错误说

Java.lang.illegalArgumentsException:无法找到具有给定名称调查年份的本地属性。

在调试时,我发现 JPA 无法识别复合键属性。

public class UniversityBasicInformation implements Serializable{        
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @JsonProperty
    private String aisheCode;
    @JsonProperty
    private Integer surveyYear;
    @JsonProperty
    private String state;
    @JsonProperty
    private String name;
    @JsonProperty
    private String district;
    @JsonProperty
    private String type;
}
<hibernate-mapping>
    <class name="gov.nic.aishe.read.pojo.UniversityBasicInformation" table="university_basic_information"
        schema="readonly">
        <composite-id>
            <key-property name="aisheCode" type="java.lang.String">
                <column name="aishe_code" />
            </key-property>
            <key-property name="surveyYear" type="java.lang.Integer">
                <column name="survey_year" />
            </key-property>
        </composite-id>
        <property name="state" type="java.lang.String">
            <column name="state" />
        </property>
        <property name="district" type="java.lang.String">
            <column name="district" />
        </property>
        <property name="type" type="java.lang.String">
            <column name="type" />
        </property>        
    </class>

</hibernate-mapping>
public List<UniversityBasicInformation> getUniversityList(Integer surveyYear, String stateCode, String type,
        String speciality, String districtCode) {

    CriteriaBuilder builder = sessionFactory.getCurrentSession().getCriteriaBuilder();
    CriteriaQuery<UniversityBasicInformation> criteriaQuery = builder.createQuery(UniversityBasicInformation.class);
    Root<UniversityBasicInformation> root = criteriaQuery.from(UniversityBasicInformation.class);


    List<Predicate> predicates = new ArrayList<Predicate>();

    predicates.add(builder.equal(root.get("surveyYear"), surveyYear)); //line with error

    if (stateCode != null) {

        predicates.add(builder.equal(root.get("state"), stateCode));

    }

我希望将调查年份参数值添加为谓词。但是上面的代码给出了错误,因为找不到具有给定名称的本地属性 [surveyYear]

标签: hibernatejpacriteriaquery

解决方案


看来您选择了不鼓励的映射。 https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/mapping.html#mapping-declaration-compositeid

不幸的是,这种方法意味着持久对象是它自己的标识符。除了对象本身之外,没有方便的“句柄”。您必须先实例化持久类本身的实例并填充其标识符属性,然后才能 load() 与复合键关联的持久状态。我们将此方法称为嵌入式复合标识符,并且不鼓励将其用于严肃的应用程序。

持久类必须重写 equals() 和 hashCode() 以实现复合标识符相等。它还必须实现 Serializable。

要按整个键搜索,您需要覆盖equals()并将整个传递 UniversityBasicInformation

predicates.add(builder.equal(root, anUniversityBasicInformation));

我也进行了调试org.hibernate.query.criteria.internal.path.AbstractFromImpl.locateManagedType(),模型中既不id存在也不存在其部分。显然,这不是我们想要的。

我建议您遵循上面链接中的建议,并通过为您的复合 ID 使用一个类来修改您的映射。

https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/components.html#components-compositeid

最重要的是,您是否坚持使用 xml 映射?注释现在很流行。


推荐阅读