【问题标题】:Hibernate Criteria on EmbeddedId property throws org.hibernate.QueryException: could not resolve propertyEmbeddedId 属性上的休眠条件抛出 org.hibernate.QueryException:无法解析属性
【发布时间】:2016-04-28 18:29:04
【问题描述】:

我在使用 Hibernate Criteria API 时遇到了一个非常奇怪的 Hibernate 行为。我正在使用休眠 4.3.6 Final。 我有一个这样的类 AnnouncementAttribute:

@Entity
@Table(name = "announcement_attribute")
public class AnnouncementAttribute implements Serializable {

    @EmbeddedId
    protected AnnouncementAttributePK id;

    @Column(name = "attribute_value")
    private String attributeValue;
}

及以下 AnnouncementAttributePK 类:

@Embeddable
public class AnnouncementAttributePK implements Serializable {
    @ManyToOne
    @JoinColumn(name = "attribute_id")
    private Attribute attr;

    @ManyToOne
    @JoinColumn(name = "announcement_id")
    private Announcement announcement;
}

还有属性类:

@Entity
@Table(name = "attribute")
public class Attribute implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "attribute_type")
    private Integer attributeType;

    @Column(name = "attribute_name")
    private String attributeName;
}

我在这里省略了 getter/setter。

问题是当我尝试通过 Criteria API 访问 @EmbeddedId 属性 attr 时:

Criteria ac = session().createCriteria(AnnouncementAttribute.class);
ac.add(Restrictions.and(
                    Restrictions.eq("id.attr.attributeName", "someKey"), 
                    Restrictions.eqOrIsNull("attributeValue", "someValue")));

我明白了:

org.hibernate.QueryException:无法解析属性:id.attr.attributeName of:com.example.app.domain.AnnouncementAttribute

我已经尝试为 embeddedId 创建别名 - 仍然没有成功。

【问题讨论】:

    标签: java hibernate hibernate-criteria


    【解决方案1】:

    试试

    Criteria ac = session().createCriteria(AnnouncementAttribute.class)
    .createAlias("id", "id")
    .createAlias("id.attr", "idAttr")
    .add(Restrictions.and(
                        Restrictions.eq("idAttr.attributeName", "someKey"), 
                        Restrictions.eqOrIsNull("attributeValue", "someValue")));
    

    【讨论】:

    • 我试过这样的方法,我得到:org.hibernate.QueryException: Criteria objects cannot be created directly on components。创建拥有实体的条件并使用点属性访问组件属性:id
    【解决方案2】:

    好吧,虽然我不相信我找到的解决方案,但我还是会发布它,也许有人会觉得它有用,或者它可能是进一步讨论的好主题。

    我从 AnnouncementAttributePK 中删除了 @Embedded

    public class AnnouncementAttributePK implements Serializable {
        @ManyToOne
        @JoinColumn(name = "attribute_id")
        private Attribute attr;
    
        @ManyToOne
        @JoinColumn(name = "announcement_id")
        private Announcement announcement;
    }
    

    ,然后在 AnnouncementAttribute 中我将@EmbeddedId 更改为@IdClass 和@Id 的组合:

    @Entity
    @Table(name = "announcement_attribute")
    @IdClass(AnnouncementAttributePK.class)
    public class AnnouncementAttribute implements Serializable {
    
        @Id
        private Attribute attr;
        @Id
        private Announcement announcement;
    
        @Column(name = "attribute_value")
        private String attributeValue;
    }
    

    最后在标准中:

    Criteria ac = session().createCriteria(AnnouncementAttribute.class)
                .createAlias("attr", "atrib");
    ac.add(Restrictions.and(
                        Restrictions.eq("atrib.attributeName", "someKey"), 
                        Restrictions.eqOrIsNull("attributeValue", "someValue")));
    

    在这些更改之后,一切正常。我不知道为什么......无论如何我会进一步调查它,因为它至少很奇怪。也许这与我的应用程序在 Spring Context 中运行,使用 LocalContainerEntityManagerFactoryBean 和 spring-data-jpa 并通过解包 EntityManager 获得 org.hibernate.Session 对象这一事实有关? :

    @PersistenceContext
    private EntityManager entityManager;
    

    和会话:

    private Session session(){
        return entityManager.unwrap(Session.class);
    }
    

    【讨论】:

    • 您知道正确的解决方案吗?我现在面临同样的问题。我创建别名。现在我得到 //org.hibernate.QueryException: Criteria objects cannot be created directly on components。在拥有实体上创建标准并使用点属性访问组件属性//异常。但我不认为你的解决方案是正确的
    【解决方案3】:

    一种解决方法是将嵌套的 id 列添加为列,并将 insert 和 update 设置为 false。因此,您拥有可以在条件中使用而没有任何问题的 embeddedId 的只读映射。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-25
      • 1970-01-01
      • 2016-02-26
      • 1970-01-01
      • 2013-07-25
      • 2014-02-24
      • 1970-01-01
      相关资源
      最近更新 更多