2017-10-02 3 views
0

Essayer de comprendre comment fonctionne la jointure sur JPQL CreateQuery. J'ai une fonction de recherche partielle pour le nom du gestionnaire avec le code SQL:Rejoindre JPQL, CreateQuery

SELECT 
e.EMPLOYEE_ID  AS empId, 
e.FIRST_NAME  AS empFirstName, 
e.LAST_NAME  AS empLastName, 
m.FIRST_NAME || ' ' || m.LAST_NAME AS empMgrName 
FROM 
EMPLOYEES e 
LEFT JOIN 
EMPLOYEES m ON e.MANAGER_ID = m.EMPLOYEE_ID 
WHERE 
LOWER(m.FIRST_NAME || ' ' || m.LAST_NAME) LIKE '%"ManagerName"%' 

J'ai essayé de faire cela dans un format JPQL et je suis venu avec les éléments suivants:

StringBuilder query = new StringBuilder(); 
query.setLength(0); 
query.append(" FROM "); 
query.append(" Employee e "); 
query.append(" JOIN "); 
query.append(" e.Manager m "); 
query.append(" WHERE 1 = 1 "); 
query.append(" LOWER(m.FIRST_NAME || ' ' || m.LAST_NAME) LIKE :empMgrName "); 
Query listEmpQuery = JPA.em().createQuery(query.toString(), Employee.class); 
if (!StringUtil.isNullOrEmpty(strMgr)) { 
    listEmpQuery.setParameter("empMgrName", "%" + strMgr.toLowerCase() + "%"); 
} 
List<Employee> listEmp = listEmpQuery.getResultList(); 

Disons que l'utilisateur a entré la valeur de "ill gat" au strMgr pour rechercher le nom du gestionnaire "Bill Gates". Il devrait rechercher l'employé qui est sous les portes de facture de gestionnaire. Mais dans ce code, l'erreur ff se produit:

IllegalArgumentException: Cannot create TypedQuery for query with more than one return using requested result type [models.db.Employee]] 

Qu'est-ce que j'ai fait de mal?

Référence: Employee.class

@Entity 
@Table(name="EMPLOYEES") 
@SequenceGenerator(name = "EMPLOYEES_SEQ", sequenceName = "EMPLOYEES_SEQ") 
public class Employee { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO, generator = "EMPLOYEES_SEQ") 
public Integer EMPLOYEE_ID; 

public String FIRST_NAME; 

public String LAST_NAME; 

@OneToOne 
@JoinColumn(name="MANAGER_ID") 
public Employee Manager; 

Je rejoins moi au gestionnaire de l'employé comme « gestionnaire »

+1

pourrait tout aussi bien prendre regarder les Conventions de Java Naming, en particulier pour vos noms d'attributs. Jetez un oeil à la partie Variables: http://www.oracle.com/technetwork/java/codeconventions-135099.html – veljkost

+1

JPQL commence par "SELECT {alias}", tous les docs JPQL vous le diraient. "||" est invalide JPQL, mais il y a une fonction CONCAT. Ce document vous le dirait aussi – DN1

Répondre

2

La chose est que lorsque vous avez plus d'une entité dans la requête, vous devez spécifier celui que vous voulez comme résultat (sauf si c'est une projection).

query.append(" SELECT e") 
query.append(" FROM "); 
query.append(" Employee e "); 
query.append(" JOIN "); 
query.append(" e.Manager m "); 

ou SELECT m si vous souhaitez avoir le gestionnaire comme résultat.

La clause LIKE est très bien ... elle est construite pour empêcher l'injection de sql.

+0

Vous avez changé cela d'une jointure externe à une jointure interne. Et je pense que c'est une bonne habitude de faire que FETCH JOINS récupère les jointures pour éviter la duplication des données dans les relations ManyToOne. – fhossfel

1

Ce que vous essayez d'atteindre est LEFT OUTER FETCH JOIN:

query.append("SELECT e FROM "); 
query.append(" Employee e "); 
query.append("LEFT JOIN FETCH "); 
query.append(" e.Manager"); 
query.append(" WHERE LOWER(CONCAT(m.FIRST_NAME, ' ', m.LAST_NAME)) LIKE :empMgrName ");