【问题标题】:JPA CriteriaBuilder Subquery multiselectJPA CriteriaBuilder 子查询多选
【发布时间】:2014-03-28 21:12:03
【问题描述】:

我对 jpa 中的子查询类有疑问。 我需要用两个自定义字段创建子查询,但子查询没有多选方法,选择方法有表达式输入参数(在查询中这是选择)和 constact 方法不适合。

我也有关于连接子查询结果的问题,有可能吗?怎么做?

我有:

链实体

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

} 

消息实体

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

}

查询包装器

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

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

我需要创建这个查询(这是查询的一部分,另一部分是我从谓词中得到的。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; 

在子查询中我做

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))
));

但是,子查询在参数中没有使用 CompoundSelection 进行选择,我不能使用 CriteriaBuilder 构造方法。

【问题讨论】:

  • 如果没有具体的数据示例、要执行的查询类型和编码 sn-ps,几乎不可能为您提供帮助。但似乎您根本不​​需要子查询,但可能需要加入。
  • 我同意,请发布一些代码。
  • 你有什么想法吗?
  • 我在这里,在 2016 年 12 月想知道同样的事情。
  • 在where中用子查询代替join不是一个选项吗?

标签: java jpa criteria criteria-api


【解决方案1】:

映射为实体的数据库视图将完成您需要的工作。 它被映射为一个普通的表,只使用标签@View。

我的项目也是如此。

【讨论】:

    【解决方案2】:

    您可以从 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]);
    }
    

    【讨论】:

      【解决方案3】:
      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"))));
      

      【讨论】:

      • 避免只包含代码的回复。添加说明。
      猜你喜欢
      • 2019-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-30
      • 2011-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多