2010-04-20 11 views
12

W hibernacji Chcę, aby uruchomić ten JPQL/HQL kwerendy: KlasaCzy jest to możliwe: zapytanie JPA/Hibernate z właściwością list w wyniku?

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

userDTO: Podmiot

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... 
} 

użytkownika:

@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... 
} 

ale kiedy hibernacji 3.5 (JPA 2) zaczyna się komunikat o błędzie:

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 ] 

Czy wybór, który zawiera listę (u.securityRoles), jest niemożliwy? Czy powinienem po prostu utworzyć 2 oddzielne zapytania?

Odpowiedz

10

Kwerenda bez NEW (wybierając wartość skalarna i wyrażenie ścieżka zbiór wartości) nie jest ważna, więc nie sądzę, że dodanie NEW uczyni wszystko działa.

Dla przypomnienia, jest to, co specyfikacji JPA 2.0 mówi w sekcji 4,8 klauzuli SELECT:

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

Dzięki! Powinienem był to sprawdzić w specyfikacji JPA. Oczywiście u.securityRoles nie jest "single_valued_path_expression". Sądzę, że oznacza to, że należy wykonać oddzielne zapytania dotyczące pobierania kolekcji/relacji (lub użyć łączenia i utworzyć kolekcje z pętlą). – Kdeveloper

+1

@Kdeveloper Jeśli twój użytkownik ma wiele, wiele atrybutów, tak myślę. Jeśli nie, po prostu wybierz użytkownika i pobierz jego funkcje zabezpieczeń. –

+0

@pascal thivent A jeśli JPQL zwróci wielu użytkowników, to ostatecznie doprowadzi do pętli, aby odzyskać role SecurityRoles każdego użytkownika, prawda? – HopeKing

1

Wierzę, że musisz zadeklarować konstruktor 0-arg w klasie UserDTO.

EDYTOWANIE: Lub jako konstruktor, który przyjmuje Integer zamiast int jako pierwszy argument. Podczas wyszukiwania konstruktorów za pomocą refleksji Hibernate może nie traktować ich jako typów "zgodnych".

Zasadniczo skoncentruję się na części wiadomości w numerze Unable to locate appropriate constructor on class [...UserDTO].

+0

zgadzam, wydaje się, że Hibernate nie może znaleźć odpowiedniego konstruktora. Ale dlaczego? Jeśli usuniemy securityRoles w obu contructor i kwerendy kod działa ... – Kdeveloper

+0

Int do Integer, nie ma znaczenia. Konstruktor argumentów zerowych nie jest potrzebny, ponieważ HQL jawnie używa nazwanego konstruktora (lub przynajmniej normalnie) – Kdeveloper

-1

myślę, że powinieneś spróbować czegoś takiego:

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

Twoja sugestia nie jest kompilowana. – Maciej