2011-08-01 17 views
9

que tiene una estructura de clases como esto:JPA los criterios del API: propiedades de la consulta de la subclase

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
public abstract class Article { 
    private String aBaseProperty; 
} 

@Entity 
public class Book extends Article { 
    private String title; 
} 

@Entity 
public class CartItem { 
    @ManyToOne(optional = false) 
    public Article article; 
} 

He intentado lo siguiente para recibir toda CartItems que tiene una referencia a un Book con title = 'Foo':

CriteriaBuilder builder = em.getCriteriaBuilder(); 
CriteriaQuery<CartItem> query = builder.createQuery(CartItem.class); 
Root<CartItem> root = query.from(CartItem.class); 
builder.equal(root.get("article").get("title"), "Foo"); 
List<CartItem> result = em().createQuery(query).getResultList(); 

Pero desafortunadamente, esto produce un error (tiene sentido para mí, ya que title está en Book, no en Article ...):

 
java.lang.IllegalArgumentException: Could not resolve attribute named title 
    at org.hibernate.ejb.criteria.path.SingularAttributePath.locateAttributeInternal(SingularAttributePath.java:101) 
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:216) 
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:189) 
... 

Sin embargo, yo era capaz de lograr lo que quiero utilizando la siguiente HQL:

SELECT c, a FROM CartItem c INNER JOIN c.article a WHERE a.title = ? 

Entonces, ¿por qué este último trabajo y puedo lograr algo similar utilizando la API de criterios?

+0

¿No le falta 'builder.select (root)'? Además, su consulta de criterios no se corresponde con la consulta JPQL. –

+0

¡Gracias por tu comentario! Hmm, mi 'constructor' (de' hibernate-jpa-2.0-api-1.0.0.Final.jar') no tiene un método 'select()'. Sí, no se corresponden porque me falta algo obviamente ;-) ¿Estás diciendo que tendría que agregar el JOIN al 'Article' por mí mismo? – msonntag

Respuesta

1

No soy un experto, pero desde un punto de vista OO diría que un artículo no tiene un título de propiedad y, por lo tanto, no se encuentra en la propiedad del artículo CarItem nombrado.

Tal vez deba comprobar si el artículo es del tipo Libro.

no estoy seguro de cómo hacer esto utilizando CriteriaBuilder

Criteria c=session.createCriteria(CarItem.class, "caritem"); 
c.add(Restrictions.eq("caritem.class", Book.class)); 
List<Article> list=c.list(); 
1

que tenía el mismo problema y encontró una solución gracias a chris (ver JPA Criteria API where subclass).

Para esto necesita JPA 2.1, y utiliza uno de los métodos CriteriaBuilder.treat(). Simplemente reemplace su línea builder.equal... por:

builder.equal(builder.treat(root.get("article"), Book.class).get("title"), "Foo"); 
+0

Funcionó como un encanto :) – wuerg

Cuestiones relacionadas