2010-04-20 13 views
12

In hibernate voglio correre questo JPQL/interrogazione HQL: classeÈ possibile: la query JPA/Hibernate con la proprietà elenco nel risultato?

select new org.test.userDTO(u.id, u.name, u.securityRoles) 
FROM User u 
WHERE u.name = :name 

userDTO: Entity

public class UserDTO { 
    private Integer id; 
    private String name; 
    private List<SecurityRole> securityRoles; 

    public UserDTO(Integer id, String name, List<SecurityRole> securityRoles) { 
    this.id = id; 
    this.name = name; 
    this.securityRoles = securityRoles; 
    } 

    ...getters and setters... 
} 

utente:

@Entity 
public class User { 

    @id 
    private Integer id; 

    private String name; 

    @ManyToMany 
    @JoinTable(name = "user_has_role", 
     joinColumns = { @JoinColumn(name = "user_id") }, 
     inverseJoinColumns = {@JoinColumn(name = "security_role_id") } 
) 
    private List<SecurityRole> securityRoles; 

    ...getters and setters... 
} 

Ma quando Hibernate 3.5 (JPA 2) inizia ricevo questo errore:

org.hibernate.hql.ast.QuerySyntaxException: Unable to locate appropriate 
constructor on class [org.test.UserDTO] [SELECT NEW org.test.UserDTO (u.id, 
u.name, u.securityRoles) FROM nl.test.User u WHERE u.name = :name ] 

È una selezione che include un elenco (u.securityRoles) come risultato non possibile? Devo solo creare 2 query separate?

risposta

10

la query senza il NEW (selezione di un valore scalare e un'espressione di percorso collezione valori) non è valido in modo non credo che l'aggiunta di un NEW sarà far funzionare le cose.

Per la cronaca, questo è ciò che la specifica JPA 2.0 dice nella sezione 4.8 SELEZIONA Clausola:

The SELECT clause has the following syntax:

select_clause ::= SELECT [DISTINCT] select_item {, select_item}* 
select_item ::= select_expression [ [AS] result_variable] 
select_expression ::= 
     single_valued_path_expression | 
     scalar_expression | 
     aggregate_expression | 
     identification_variable | 
     OBJECT(identification_variable) | 
     constructor_expression 
constructor_expression ::= 
     NEW constructor_name (constructor_item {, constructor_item}*) 
constructor_item ::= 
     single_valued_path_expression | 
     scalar_expression | 
     aggregate_expression | 
     identification_variable 
aggregate_expression ::= 
     { AVG | MAX | MIN | SUM } ([DISTINCT] state_field_path_expression) | 
     COUNT ([DISTINCT] identification_variable | state_field_path_expression | 
        single_valued_object_path_expression) 
+2

Grazie! Avrei dovuto cercarlo nello spec. JPA. Chiaramente u.securityRoles non è un 'single_valued_path_expression'. Quindi immagino questo significhi, bisogna fare query separate per recuperare collezioni/relazioni (o usare un join e creare le collezioni con un ciclo). – Kdeveloper

+1

@Kdeveloper Se il tuo utente ha molti, molti attributi, credo di si. In caso contrario, basta selezionare l'utente e recuperare i suoi ruoli di sicurezza. –

+0

@pascal thivent E se JPQL restituisce molti utenti, alla fine si otterrà un loop per recuperare i SecurityRoles di ciascun utente giusto? – HopeKing

1

Credo che sia necessario dichiarare un costruttore 0-arg nella classe UserDTO.

MODIFICA: Oppure un costruttore che accetta Integer anziché int come primo argomento. Quando si osservano i costruttori che utilizzano la riflessione Hibernate potrebbero non considerarli come tipi "compatibili".

Fondamentalmente, vorrei concentrarmi sulla parte del messaggio Unable to locate appropriate constructor on class [...UserDTO].

+0

Sono d'accordo, sembra che Hibernate non riesca a trovare un costruttore appropriato. Ma perché? Se rimuovo i ruoli di sicurezza sia nel contructor che nell'interrogazione il codice funziona ... – Kdeveloper

+0

L'int to Integer, non ha fatto la differenza. Il costruttore dell'argomento zero non è necessario, poiché l'HQL utilizza esplicitamente il costruttore nominato (o almeno lo fa normalmente) – Kdeveloper

-1

Penso che si dovrebbe provare qualcosa di simile:

select new org.test.userDTO(u.id, u.name, u.securityRoles) AS uDTO, 
    uDTO.setRoles(u.securityRoles) 
FROM User u 
WHERE u.name = :name 
+0

Il tuo suggerimento non viene compilato. – Maciej

Problemi correlati