Seleccionar la Clave Primaria de la entidad relacionada por OneToOne
Una entidad básica que tiene una referencia OneToOne a otra entidad:
@Entity
public class Amigo {
// ...
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Amigo mejorAmigo;
}
Me gustaría construir una consulta select que contenga algunos de los campos y el id del mejor amigo.
En SQL puro es trivial: SELECT bestfriendid FROM friend WHERE id = 123
Con el API de criterios de JPA las cosas se vuelven muy interesantes:
EntityManager em = …
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery
Root
query.multiselect(root.get(Friend_.bestFriend).get(Friend_.id), root.get(Friend_.name));
query.where(cb.equal(root.get(Friend_.id), id));
return em.createQuery(query).getSingleResult();
Esto funciona para un amigo con un mejor amigo configurado, pero el SQL generado es tonto: SELECT t0.ID, t1.NAME FROM FRIEND t0, FRIEND t1 WHERE ((t1.ID = ?) AND (t0.ID = t1.BESTFRIEND_ID))
Tampoco funciona en un amigo que no tiene mejor amigo.
Me gustaría ver un simple SELECT t0.NAME, t0.BESTFRIEND_ID FROM FRIEND t0 WHERE t0.ID = ?.
¿Se puede cambiar root.get(Friend_.bestFriend).get(Friend_.id) por algo más para lograr esto?
davy.ai
Sí, para obtener una consulta SQL más simple, puedes usar un left join en lugar de un multiselect. Aquí tienes un ejemplo:
Esto debería generar la consulta SQL deseada:
SELECT t0.NAME, t0.BESTFRIEND_ID FROM FRIEND t0 LEFT OUTER JOIN FRIEND t1 ON (t0.BESTFRIEND_ID = t1.ID) WHERE (t0.ID = ?)
. Además, esta consulta funcionará incluso si un amigo no tiene un mejor amigo debido al left join.</friend,>