简体   繁体   English

JPA CriteriaBuilder 子查询多选

[英]JPA CriteriaBuilder Subquery multiselect

I have a question about Subquery class in jpa.我有一个关于 jpa 中的子查询类的问题。 I need to create subquery with two custom field, but subquery doesn't have multiselect method and select method has Expression input parameter(In query this is Selection) and constact method not suitable.我需要用两个自定义字段创建子查询,但子查询没有多选方法,选择方法有表达式输入参数(在查询中这是选择)和不适合的 constact 方法。

Also I have question about join subquery results, It is possible?另外我对加入子查询结果有疑问,这可能吗? And how to?以及怎么做?

I have:我有:

Chain Enitity链实体

public class Chain {

    @Id
    @Column(name = "chain_id")
    @GeneratedValue(generator = "seq_cha_id", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = "seq_cha_id", sequenceName = "SEQ_CHA_ID", allocationSize = 1)
    private Long id;

    @Column(name = "user_id")
    private Long userId;

    @Column(name = "operator_id")
    private Long operatorId;

    @Column(name = "subject")
    private String subject;
 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "chain")
    private List<Message> messages;

    @Column(name = "status")
    private Status status;

    public Long getOperatorId() {
        return operatorId;
    }

    public void setOperatorId(Long operatorId) {
        this.operatorId = operatorId;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String theme) {
        this.subject = theme;
    }

    public List<Message> getMessages() {
        return messages;
    }

    public void setMessages(List<Message> messages) {
        this.messages = messages;
    }

} 

Message Enitity消息实体

public class Message {

    @Id
    @Column(name = "message_id")
    @GeneratedValue(generator = "seq_mess_id", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = "seq_mess_id", sequenceName = "SEQ_MESS_ID", allocationSize = 1)
    private Long id;
 
    @Column(name = "user_id")
    private Long userId;

    @Column(name = "message", nullable = true, length = 4000)
    private String message;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "chain_id")
    private Chain chain;

    @Column(name = "creation_date")
    private Date date;
    @Column(name = "status")
    private Status status;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Chain getChain() {
        return chain;
    }

    public void setChain(Chain chain) {
        this.chain = chain;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    } 

}

Wrapper for query用于查询的包装器

public class MessageWrapper {
    private final Long chainId;
    private final Long messageId;

    public MessageWrapper(Long chainId, Long messageId) {
        this.chainId = chainId;
        this.messageId = messageId;
    }
}

I need to create this query (this is part of query, another part I get from predicates. JPQL not suitable)我需要创建这个查询(这是查询的一部分,我从谓词中得到的另一部分。JPQL 不合适)

SELECT ch.* 
FROM   hl_chain ch, 
       (SELECT mes.chain_id, 
               max(message_id) message_id 
        FROM   hl_message mes 
        GROUP  BY chain_id) mes 
WHERE  mes.chain_id = ch.chain_id 
ORDER  BY message_id; 

In Subquery I do在子查询中我做

Subquery<MessageWrapper> subquery = criteriaQuery.subquery(MessageWrapper.class);
Root<Message> subRoot = subquery.from(Message.class);
subquery.select(cb.construct(
    MessageWrapper.class,
    subRoot.get(Message_.chain),
    cb.max(subRoot.get(Message_.id))
));

But, the subquery doesn't have select with CompoundSelection in params and I can't use the CriteriaBuilder construct method.但是,子查询在参数中没有使用 CompoundSelection 进行选择,并且我无法使用CriteriaBuilder构造方法。

A view on database mapped as an entity will do the job you need.映射为实体的数据库视图将完成您需要的工作。 It is mapped as a normal table only with the tag @View instead.它被映射为一个普通的表,只用标签@View 代替。

I did the same on my projects.我在我的项目中也做了同样的事情。

You can call native queries from JPA, for example:您可以从 JPA 调用本机查询,例如:

Query q = em.createNativeQuery("SELECT p.firstname, p.lastname FROM Person p");
List<Object[]> persons= q.getResultList();

for (Object[] p : persons) {
    System.out.println("Person "
            + p[0]
            + " "
            + p[1]);
}
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<MessageWrapper> q = cb.createQuery(MessageWrapper.class);
Root<Chain> c = q.from(Chain.class);
Join<Chain, Message> m = p.join("messages");
q.groupBy(c.get("id"));
q.select(cb.construct(MessageWrapper.class, c.get("id"), cb.max(m.get("id"))));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM