Kr Zaq
Kr Zaq

Reputation: 31

Hibernate Criteria on EmbeddedId property throws org.hibernate.QueryException: could not resolve property

I'm struggling with a very weird behaviour of Hibernate when using Hibernate Criteria API. I'm using hibernate 4.3.6 Final. I got a class AnnouncementAttribute like this:

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

    @EmbeddedId
    protected AnnouncementAttributePK id;

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

and below the AnnouncementAttributePK class:

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

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

And the Attribute class:

@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;
}

I ommitted getters/ setters here.

Problem is when I try to access @EmbeddedId property attr via Criteria API:

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

I'm getting:

org.hibernate.QueryException: could not resolve property: id.attr.attributeName of: com.example.app.domain.AnnouncementAttribute

I already tried to create an alias for embeddedId - still no luck.

Upvotes: 1

Views: 2713

Answers (3)

Johannes Klapwijk
Johannes Klapwijk

Reputation: 91

A workaround is to add the nested id columns as columns as well with insert and update as false. So you have a read-only mapping of the embeddedId that you can use in criteria without any problems.

Upvotes: 0

Kr Zaq
Kr Zaq

Reputation: 31

Well, altough I'm not convinced to the solution I found, I'll post it anyways, maybe someone will find it useful or maybe it will be a good subject for further discussion.

I removed @Embedded from AnnouncementAttributePK

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

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

, then in AnnouncementAttribute I've changed @EmbeddedId to combination of @IdClass and @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;
}

and finally in the Criteria:

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

After those changes everything works just fine. I got no clue why... I'll further investigate it anyway, because it's at least weird. Maybe it has something to do with a fact that my application is running in Spring Context, using LocalContainerEntityManagerFactoryBean and spring-data-jpa, and a org.hibernate.Session object is obtained by unwraping EntityManager ? :

@PersistenceContext
private EntityManager entityManager;

and session:

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

Upvotes: 1

Mykola Yashchenko
Mykola Yashchenko

Reputation: 5371

try

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")));

Upvotes: 0

Related Questions