2017-05-30 5 views
0

Hallo Ich schrieb die folgende Criteria-API-Abfrage, die eine defekte sql-select-Anweisung erstellt, wegen der Multiselect. Wenn ich die Mehrfachauswahl auskommentiere, funktioniert die Abfrage wie erwartet, aber die Sache ist, dass ich nicht alle Daten haben möchte. Es gibt mehrere Beziehungen in meinem Portal-Objekt und das Laden von ihnen ist in meinem aktuellen Fall absolut nicht notwendig.Hibernate vermasselt meine Abfrage

Das Verfahren sieht wie folgt aus:

@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(); 
    } 
    } 

und die gebrochene Abfrage sieht wie folgt aus:

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 

Anregungen, warum Hibernate ist meine Frage wie diese vermasselt, wenn ich Mehrfachauswahl verwenden?

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

und der Code-Klasse

@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

Wie lautet der Code der Portal-Entität? Warum verwenden Sie JPQL nicht für eine solche statische Abfrage? –

+0

Warum ist der Code des Portals wichtig? JPQL erzeugt den gleichen Fehler – Goldfish

+0

Hey, du bist derjenige, der Hilfe braucht. Voting zu schließen, da Sie die angeforderten Informationen nicht zur Verfügung stellen möchten, damit ich Ihnen kostenlos weiterhelfen kann. –

Antwort

1

Sie können nicht eine ganze Sammlung auswählen (codes).

Angenommen, Sie jede Zeile des Ergebnisses wollen einen Code, der sich aus und eines Zertifikats sollte die JPQL Abfrage

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

sein Das wird natürlich so viele Zeilen zurück, da es Codes in der angegebenen sind Portal, und nicht nur eins.

Das Löschen anderer Spalten der Portaleinheit ist wahrscheinlich eine vorzeitige, unnötige Optimierung. Es sollte viel einfacher sein, nur

em.find(Portal.class, id) 

oder tun, wenn Sie die Codes und das Zertifikat in der gleichen Abfrage

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

laden mögen, die eine eindeutige Zeile mit dem Portal zurückkehren würde, mit der vorgelesener Satz von Codes.

Wenn Sie wirklich möchten, dass Ihre Anwendung schnell ist, sollten Sie stattdessen standardmäßig Verbindungen (insbesondere zu vielen Verknüpfungen) träge machen und bei Bedarf Fetch-Joins verwenden.