JPA - 选择,加入,子查询和最大值

时间:2013-11-13 18:27:58

标签: java sql hibernate jpa

我尝试将此查询映射到JPA,加入,子查询和其他对我来说非常重要。也许你可以帮助我。这是我的疑问:

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。还有其他状态,但我只想要那些2.

所以我有这些表:

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

我的代码片段:

Customer.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...

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

问候,Chesmuh

1 个答案:

答案 0 :(得分:0)

您还需要映射created表的actions列。然后,您可以应用以下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
)