2017-05-30 52 views
0

嗨,我写了下面的Criteria-API查询,由于多选,创建一个损坏的sql-select语句。如果我取消注释multiselect查询按预期工作,但事情是我不想拥有所有数据。在我的门户对象中有几种关系,并且在我目前的情况下加载它们都是绝对没有必要的。休眠打乱了我的查询

的方法是这样的:

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

和破碎的查询看起来是这样的:

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 

任何建议,为什么,如果我使用多选Hibernate是搞乱了我这样的查询?

编辑:

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

和代码级

@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

门户实体的代码是什么?为什么不使用JPQL进行这样的静态查询? –

+0

为什么门户网站的代码很重要? JPQL产生相同的错误 – Goldfish

+0

嘿,你是需要帮助的人。投票结束,因为你不想提供所需的信息让我帮你免费。 –

回答

1

你不能选择整个集合(codes)。

假设你想要的结果的每一行组成的代码证书的,在JPQL查询应该是

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

因为有代码在给定的那当然会返回尽可能多的行门户网站,而不只是一个。

避免加载门户实体的其他列可能是不成熟的,不必要的优化。它应该是更容易只是做

em.find(Portal.class, id) 

,或者,如果要加载代码和证书在同一查询

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

这将返回包含门户网站的唯一行,与预取的一组代码。

如果您确实希望自己的应用程序速度更快,您应该在默认情况下(尤其是许多关联)使关联更为懒惰,并在需要时使用获取联接。