-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: internal exceptions of JPA2 Criteria API implementation
PostPosted: Mon Sep 27, 2010 1:11 pm 
Newbie

Joined: Mon Nov 26, 2007 3:30 pm
Posts: 3
suppose i have a simple entity with an embedded one:

Code:
@Entity
@Table(name="TABLE")
public class TestEntity {
   @Id
   @Column(name = "ID", nullable = false)
   private Integer id;
...
   @Embedded
   private TestEntity2 embeddedAttribute;
...
}

@Embeddable
public class TestEntity2 {
...
   @Column(name = "BLAH")
   @Enumerated(EnumType.STRING)
   private TestEnum enumeratedAttribute;
...
}


public enum TestEnum {
   ONE, TWO;
}


when i create a JPA2 criteria:

Code:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<TestEntity> q = builder.createQuery(TestEntity.class);
Root<TestEntity> r = q.from(TestEntity.class);
q.select(r.<TestEntity>get("id"));
//q.where(builder.equal(r.join("embeddedAttribute").get("enumeratedAttribute"), TestEnum.ONE));   //q.where(builder.equal(r.get("embeddedAttribute.enumeratedAttribute"),TestEnum.ONE));
em.createQuery(q).getResultList()


and then run it using hibernate 3.5.6-Final, i get the following exceptions depending on which "where" line i use:
first one
Code:
java.lang.ClassCastException: org.hibernate.ejb.metamodel.SingularAttributeImpl cannot be cast to javax.persistence.metamodel.ManagedType
   at org.hibernate.ejb.criteria.path.AbstractFromImpl.locateManagedType(AbstractFromImpl.java:151)
   at org.hibernate.ejb.criteria.path.AbstractFromImpl.locateAttributeInternal(AbstractFromImpl.java:145)
   at org.hibernate.ejb.criteria.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:216)
   at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:189)
   at my.TestSearchCriteria.testSimpleNativeCriteria(TestSearchCriteria.java:46)

second one
Code:
java.lang.NullPointerException
   at org.hibernate.ejb.criteria.path.AbstractPathImpl.unknownAttribute(AbstractPathImpl.java:110)
   at org.hibernate.ejb.criteria.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:218)
   at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:189)
   at my.TestSearchCriteria.testSimpleNativeCriteria(TestSearchCriteria.java:47)

equivalent JPQL queries run just fine both ways:

Code:
em.createQuery("select r from TestEntity r where r.embeddedAttribute.enumeratedAttribute = 'ONE'").getResultList());
em.createQuery("select r from TestEntity r join r.embeddedAttribute c where c.enumeratedAttribute = 'ONE'").getResultList());


Example #3 in Section 6.7 of JSR promises us that joining on embedded entities should work just fine... is it something known not to work? is there a workaround?


Top
 Profile  
 
 Post subject: Re: internal exceptions of JPA2 Criteria API implementation
PostPosted: Mon Sep 27, 2010 5:57 pm 
Newbie

Joined: Mon Sep 27, 2010 5:40 pm
Posts: 3
I think your criteria query has been defined incorrectly. Here's my explanation:

In this createQuery call you are basically saying that you are going to select a list of TestEntity objects.
Code:
CriteriaQuery<TestEntity> q = builder.createQuery(TestEntity.class);


However, in this line you are selecting the id, not the object (and you are also specifying <TestEntity> with generics here which is incorrect):
Code:
q.select(r.<TestEntity>get("id"));


The first exception is thrown because you are selecting the "id" attribute but you have specified that the results will be TestEntity objects.
The second exception is thrown because you are selecting the "id" attribute and trying to join id.embeddedAttribute which of course doesn't exist.

So, the fix should be pretty simple. Use this instead:
Code:
q.select(r);


The second query should work fine once you fix the select clause :)
I recommend using the first where clause but both should work.

Sadly it is very easy to make such simple mistakes with JPA 2 criteria queries and the exceptions can be very hard to understand. I've spent a lot of time debugging some of my queries where I defined a field name of type incorrectly.
If you want more safety, I suggest using the canonical metamodel which solves most type safety issues. In your queries the metamodel would enable you to replace the "magical" string values "id", "embeddedAttribute" and "enumeratedAttribute" with type-safe references.


Top
 Profile  
 
 Post subject: Re: internal exceptions of JPA2 Criteria API implementation
PostPosted: Tue Sep 28, 2010 4:43 am 
Newbie

Joined: Mon Nov 26, 2007 3:30 pm
Posts: 3
gekkio wrote:
I think your criteria query has been defined incorrectly. Here's my explanation:

In this createQuery call you are basically saying that you are going to select a list of TestEntity objects.
Code:
CriteriaQuery<TestEntity> q = builder.createQuery(TestEntity.class);


However, in this line you are selecting the id, not the object (and you are also specifying <TestEntity> with generics here which is incorrect):
Code:
q.select(r.<TestEntity>get("id"));


The first exception is thrown because you are selecting the "id" attribute but you have specified that the results will be TestEntity objects.
The second exception is thrown because you are selecting the "id" attribute and trying to join id.embeddedAttribute which of course doesn't exist.

So, the fix should be pretty simple. Use this instead:
Code:
q.select(r);



it doesn't matter what you select (and should not because what is selected has nothing to do with what is restricted). you can see it for yourself as it works both ways: with select(r) and with select(r.get("id")).

the problem i experience is that hibernate seems not to allow to join on embedded entities, while JSR clearly says that it should ;).

the fix for this problem is when you need to join on an embedded entity, you must do a "get" instead of "join", which is absolutely not convenient:
Code:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<TestEntity> q = builder.createQuery(TestEntity.class);
Root<TestEntity> r = q.from(TestEntity.class);
q.select(r.<TestEntity>get("id"));
q.where(builder.equal(r.get("embeddedAttribute").get("enumeratedAttribute"), TestEnum.ONE));
em.createQuery(q).getResultList();


gekkio wrote:
I suggest using the canonical metamodel which solves most type safety issues. In your queries the metamodel would enable you to replace the "magical" string values "id", "embeddedAttribute" and "enumeratedAttribute" with type-safe references.


i can't use metamodel, because i need to be able to address attributes without knowing which attribute this actually is.


Top
 Profile  
 
 Post subject: Re: internal exceptions of JPA2 Criteria API implementation
PostPosted: Tue Sep 28, 2010 1:22 pm 
Newbie

Joined: Mon Sep 27, 2010 5:40 pm
Posts: 3
zam0th wrote:
it doesn't matter what you select (and should not because what is selected has nothing to do with what is restricted). you can see it for yourself as it works both ways: with select(r) and with select(r.get("id")).


Yes, you're right. Sorry, I read your code too quickly and I was distracted by the mismatch between the types in q.select and builder.createQuery.

zam0th wrote:
the problem i experience is that hibernate seems not to allow to join on embedded entities, while JSR clearly says that it should ;).


I made a quick test project using your code and tested it with EclipseLink 2.1.1. It worked fine so indeed this seems like a Hibernate bug.
Even Hibernate 3.6.0.CR1 had the same behaviour. I guess you'll have to report the bug and hope it'll be fixed at some point :(


Top
 Profile  
 
 Post subject: Re: internal exceptions of JPA2 Criteria API implementation
PostPosted: Tue May 15, 2012 12:56 pm 
Newbie

Joined: Tue May 15, 2012 12:52 pm
Posts: 1
I had the same problem, must be a bug in Hibernate.

Workaround is to use metamodel (I tried it it works).

You can always have a if-else for metamodel if you need the field to be dynamically determined.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.