2017-05-30 3 views
0

Bonjour, J'ai écrit la requête Criteria-API suivante qui crée une instruction sql-select cassée, à cause du multiselect. Si je décommente le multiselect la requête fonctionne comme prévu mais la chose est que je ne veux pas avoir toutes les données. Il y a plusieurs relations dans mon objet-portail et les charger toutes n'est absolument pas nécessaire dans mon cas actuel.hibernate salit ma requête

La méthode ressemble à ceci:

@Override 
    public Optional<Portal> loadPortalData(long clientId) 
    { 
    log.trace("loading data for client with id '{}'", clientId); 
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); 
    CriteriaQuery<Portal> criteriaQuery = criteriaBuilder.createQuery(Portal.class); 
    Root<Portal> root = criteriaQuery.from(Portal.class); 
    criteriaQuery.multiselect(root.get(Portal_.codes), 
           root.get(Portal_.certificate)) 
       .where(criteriaBuilder.equal(root.get(Portal_.id), clientId)); 
    try 
    { 
     return Optional.of(entityManager.createQuery(criteriaQuery).getSingleResult()); 
    } 
    catch (NoResultException noResult) 
    { 
     return Optional.empty(); 
    } 
    } 

et la requête brisée ressemble à ceci:

30 Mai 2017 07:12:56,305 [main] TRACE mypackage.repository.PortalDaoImpl (PortalDaoImpl.java:39) - loading data for client with id '1' 
Hibernate: 
select 
    . as col_0_0_, 
    portal0_.certificate as col_1_0_ 
from 
    portal portal0_ 
inner join 
    Code authorisat1_ 
     on portal0_.id=authorisat1_.client_id 
inner join 
    certificate certificat2_ 
     on portal0_.certificate=certificat2_.id 
where 
    portal0_.id=1 

suggestions pourquoi mise en veille prolongée est la pagaille dans ma requête comme ça si j'utilise multiselect?

EDIT:

@Entity 
@Table(name = "portal") 
public class Portal 
{ 
    ... 
    @Valid 
    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER, mappedBy = "client") 
    private Set<Code> codes = new HashSet<>(); 

    @Valid 
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    @JoinColumn(name = "certificate", referencedColumnName = "id") 
    private Certificate certificate; 
    ... 
} 

et la classe code

@Entity 
public class Code 
{ 

    @Id 
    @GeneratedValue 
    private long id; 

    @NotNull 
    @Column(nullable = false, unique = true) 
    private String code; 

    @NotNull 
    @ManyToOne(fetch = FetchType.EAGER, targetEntity = Portal.class) 
    @JoinColumn(name = "client_id", referencedColumnName = "id", nullable = false) 
    private Portal client; 

    @NotNull 
    @Temporal(TemporalType.TIMESTAMP) 
    @Column(nullable = false) 
    private Date creation_time; 

    @Column(nullable = false) 
    private int expires_in; 
    ... 
} 
+0

Quel est le code de l'entité Portal? Pourquoi n'utilisez-vous pas JPQL pour une telle requête statique? –

+0

Pourquoi le code du portail a-t-il de l'importance? JPQL produit la même erreur – Goldfish

+0

Hey, vous êtes celui qui a besoin d'aide. Voter pour fermer, car vous ne voulez pas fournir les informations demandées me permettant de vous aider, gratuitement. –

Répondre

1

Vous ne pouvez pas sélectionner toute une collection (codes).

En supposant que vous voulez que chaque ligne du résultat composé d'un code et d'un certificat, la requête JPQL doit être

select code, portal.certificate from Portal portal 
left join portal.codes as code 
where portal.id = :id 

Ce sera de retour bien sûr autant de lignes que des codes dans la donnée portail, et pas seulement un. Éviter de charger d'autres colonnes de l'entité du portail est probablement une optimisation prématurée et inutile. Il devrait être beaucoup plus facile de le faire

em.find(Portal.class, id) 

ou, si vous voulez charger les codes et le certificat dans la même requête

select distinct portal from Portal portal 
left join fetch portal.certificate 
left join fetch portal.codes 
where portal.id = :id 

qui renverrait une ligne unique contenant le portail, le ensemble de codes pré-tirés. Si vous voulez vraiment que votre application soit rapide, vous devriez plutôt faire des associations paresseuses par défaut (en particulier pour de nombreuses associations), et utiliser des jointures de fetch si nécessaire.