【问题标题】:JPA - Select, Join, Subquery and maxJPA - 选择、加入、子查询和最大值
【发布时间】:2013-11-13 18:27:58
【问题描述】:

我尝试将此查询映射到 JPA 和 Join、Subqueries 和其他对我来说很重要。也许你可以帮助我。这是我的查询:

SELECT customers.*
FROM actions
         JOIN customers
              ON customers.id = actions.customer_id
WHERE actions.action_type = 'CUSTOMER_TRAINING_BEGIN'
  AND actions.created IN (
    SELECT max(created)
    FROM actions
    WHERE action_type = 'CUSTOMER_TRAINING_BEGIN'
       OR action_type = 'CUSTOMER_TRAINING_END'
    GROUP BY customer_id
);

我尝试收集最后一个状态(CUSTOMER_TRAINING_BEGIN 或 CUSTOMER_TRAINING_END)为 CUSTOMER_TRAINING_BEGIN 的所有客户。还有其他状态,但我只想要那两个。

所以我有这些表:

                     Table "public.actions"  
   Column    |           Type           |       Modifiers           
-------------+--------------------------+------------------------   
 id          | bigint                   | not null   
 action_type | character varying(30)    | not null   
 user_name   | character varying(30)    | not null   
 customer_id | bigint                   |    
 created     | timestamp with time zone | not null default now()   
 updated     | timestamp with time zone | not null default now()   

                     Table "public.customers"
    Column    |           Type           |       Modifiers        
--------------+--------------------------+------------------------
 id           | integer                  | not null
 fore_name    | character varying(50)    | not null
 last_name    | character varying(50)    | not null
 matrikel     | integer                  | not null
 day_of_birth | timestamp with time zone | not null
 created      | timestamp with time zone | not null default now()
 updated      | timestamp with time zone | not null default now()

还有我的代码 sn-ps:

客户.java

@Data
@Entity
@NoArgsConstructor
@Table(name = "CUSTOMERS")
@EqualsAndHashCode(callSuper = false)
public class Customer extends AbstractTimestampEntity {

    @Id
    @SequenceGenerator(sequenceName = "CUSTOMERS_ID_SEQ", name = "CUSTOMERS_ID_GEN", allocationSize = 1)
    @GeneratedValue(generator = "CUSTOMERS_ID_GEN", strategy = GenerationType.SEQUENCE)
    private long id;

    @Column(name = "FORE_NAME")
    private String foreName;

    @Column(name = "LAST_NAME")
    private String lastName;

    @Column(name = "MATRIKEL")
    private int matrikelNumber;

    @Column(name = "DAY_OF_BIRTH")
    private Date dayOfBirth;

}

ActionType.java

@AllArgsConstructor
public enum ActionType {
    /**
     * Customer starts training.
     */
    CUSTOMER_TRAINING_BEGIN("ActionType.customerTrainingBegin.label"),
    /**
     * Customer stops training
     */
    CUSTOMER_TRAINING_END("ActionType.customerTrainingEnd.label");

    @Getter
    private String labelKey;
}

Action.java

@Data
@Entity
@Table(name = "ACTIONS")
@EqualsAndHashCode(callSuper = false)
public class Action extends AbstractTimestampEntity {
  
    @Id
    @SequenceGenerator(sequenceName = "ACTIONS_ID_SEQ", name = "actions_id_gen", allocationSize = 1)
    @GeneratedValue(generator = "actions_id_gen", strategy = GenerationType.SEQUENCE)
    private long id;
    
    @OneToOne
    @JoinColumn(name = "USER_NAME")
    private User user;
 
    @OneToOne
    @JoinColumn(name = "CUSTOMER_ID")
    private Customer customer;

    @Enumerated(EnumType.STRING)
    @Column(name = "ACTION_TYPE")
    private ActionType type;

}

我的问题是,我必须收集客户。我必须从行动加入到客户,因为我没有从客户到行动的参考。所以我不能这样做:

CriteriaBuilder criteriaBuilder = this.em.getCriteriaBuilder();
CriteriaQuery<Customer> query = criteriaBuilder.createQuery(Customer.class);
Root<Customer> from = query.from(Customer.class);

query.select(from);

// Join here to action...

也许这有助于理解我的问题。非常感谢。

你好,切斯穆

【问题讨论】:

  • 请包括您的实体/映射的相关部分。如果不知道 CustomerActionCustomer 之间的关系(例如 ActionCustomerCustomer 的子类吗?),这很难回答。
  • 对不起,每次都想念那些该死的小cmets ... :-/

标签: java sql hibernate jpa


【解决方案1】:

您还需要映射actions 表的created 列。然后您可以应用以下 JPQL 查询(请注意子选择中的更改;您设计 SQL 查询的方式,它不会带来您想要的结果):

SELECT a.customer
FROM Action a
WHERE a.type = 'CUSTOMER_TRAINING_BEGIN' 
AND a.created = 
(
SELECT max(created)
FROM Action
WHERE (type = 'CUSTOMER_TRAINING_BEGIN' 
OR type = 'CUSTOMER_TRAINING_END')
AND customer.id = a.customer.id
)

【讨论】:

  • 感谢您的回答。如果我用 a.customer_id 切换 a.customer,它的结果与我的查询相同。但我尝试使用 Criteria Builder 在 JPA 中编写这些查询。
  • 请问您为什么更喜欢标准而不是 JPQL? :)
猜你喜欢
  • 1970-01-01
  • 2018-09-07
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
  • 2015-10-02
  • 1970-01-01
  • 2013-01-19
  • 1970-01-01
相关资源
最近更新 更多