【问题标题】:JPA how to join these entitiesJPA 如何加入这些实体
【发布时间】:2013-05-29 08:14:48
【问题描述】:

鉴于下面的 JPA 实体,我想获得所有具有至少一个成功状态的请求的借记。

可以有很多请求具有相同的debit_id和不同的状态

我应该使用这样的东西还是有更好的做事方式

entityManager.createQuery("select c from Debit d join d.id where request.status =Succesful"

@Entity(name = "T_DEBIT")
public class Debit {
  public enum Status { NEW, OLD } 

  @Column(name = "STATUS", nullable = false, length = 20)
  @Enumerated(value = EnumType.STRING)
  private Status status;
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "ID")
  private Long id;

  @ManyToOne(optional = false)
  @JoinColumn(name = "ACCOUNT_ID", updatable = false, nullable = false)
  private Account account;

}

其他实体是

@Entity(name = "T_REQUEST")
public class Request{  

  public enum Status { PENDING, FAILED, SUCCESFUL}  

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "ID")
  private Long id;

  @ManyToOne(optional = false)
  @JoinColumn(name = "DEBIT_ID", updatable = false, nullable = false)
  private Debit debit;

  @Column(name = "STATUS", nullable = false, length = 20)
  @Enumerated(value = EnumType.STRING)
  private Status status;

 }

如果有任何遗漏,请发表评论,而不是关闭或否决问题!

【问题讨论】:

    标签: java sql jpa


    【解决方案1】:

    基本上:

    select d
    from T_DEBIT d
    where exists (
        select r
        from T_REQUEST r
        where 
        r.debit.id = d.id and
        r.status = SUCCESSFUL
    )
    

    检查 JPQL 中的枚举语法,我通常不将枚举用于实体,在此示例中可能是错误的。

    作为样式问题,我将实体名称 == 类名称而不是实体名称 == 表名称。这使得 JPQL IS NOT SQL 更清晰

    更新

    Spring 要求解决类似问题。解决这些问题的方法非常系统:

    a) 仅使用基本过滤器和以下表达式重写您的问题:

    1. “存在一些……使得条件为真”
    2. “对于所有...条件为真”

    b) 翻译:

    1. 这个案例变成exists (select ... where condition)
    2. 这个案例变成not exists (select ... where NOT condition)

    在 Spring 的特定问题中,“排除所有成功的请求”,目标不是很明确。如果他/她的意思是“在没有成功请求的情况下获得所有借记”,那么你会这样做:

    a) 将问题改写为“获取所有借记项,以便对于所有关联的请求,请求状态不成功”。 b) 翻译为

    select d
    from T_DEBIT d
    where not exists (
        select r
        from T_REQUEST r
        where 
        -- This is the join condition, so it should not be negated
        r.debit.id = d.id and 
        -- This is the actual filtering condition, negate as this is a FOR ALL
        not (r.status != SUCCESSFUL)
    )
    

    然后你可以简化最后一个条件,得到:

    select d
    from T_DEBIT d
    where not exists (
        select r
        from T_REQUEST r
        where 
        r.debit.id = d.id and
        r.status = SUCCESSFUL
    )
    

    【讨论】:

    • 谢谢,你能解释一下为什么在这里使用“where”而不是join吗?
    • @spring 这里不需要where子句,因为已经使用了EXISTS关键字:techonthenet.com/sql/exists.php
    • @Spring 您使用连接来从多个表中检索数据。当您只想通过另一个表的内容过滤一个表时,不加入而是在 where 子句中使用存在过滤器 (exists) 更正确:它使 DBMS 有可能更高效和在许多情况下避免了使用distinct 过滤掉重复结果的需要
    • @Spring 即使我写的是“表”,请记住这个查询是 JPQL 查询而不是 SQL 查询。 JPQL 通常是 SQL 之上的一个薄层,但也有区别。
    • @Spring 如果您使用“玩具”数据库,它可能效率低下。体面的 DBMS(例如:Oracle、PostgreSQL)应该像处理连接一样处理它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 2020-05-22
    • 2011-12-12
    • 2011-06-29
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    相关资源
    最近更新 更多