首页 文章

JPA 3路连接注释

提问于
浏览
10

有三个表被建模为三个实体:

@Entity
@Table(name="event")
public class Event {
  public Long datetime;
  public String name;
  public Long processId;
}

@Entity
@Table(name="process")
public class Process {
  public Long Id;
  public Long sequence;
  public Name name;
}

@Entity
@Table(name="operation")
public class Operation {
  public Long Id;
  public Long datetime;
  public Long sequence;
}

具有3向连接约束的SQL可以获得任何唯一的process-operation-sequence单条记录:

SELECT *
FROM event e, process p, operation q 
WHERE e.processId = p.id
  AND e.datetime = q.datetime
  AND p.sequence = q.sequence

为了在JPA中实现它,我必须列出一个操作列表,这些操作将明确地缩小到JQPL相等的单个记录p.sequence = q.sequence

@Entity
@Table(name="event")
public class Event {
  public Long datetime;
  public String name;
  public Long processId;
  @OneToOne
  @JoinColumn(
    name = "processId", referencedColumnName="id",
    insertable=false, updatable=false)
  private Process process;

  @OneToMany
  @JoinColumn(
    name = "datetime", referencedColumnName="datetime",
    insertable=false, updatable=false)
  private List<Operation> operations;
}

JPQL指定传递的第3个连接约束:

SELECT e FROM Event e
INNER JOIN FETCH e.process p
INNER JOIN FETCH e.operations q
WHERE p.sequence = q.sequence

但是,我希望所有三个约束都在实体POJO中建模 . 难道不能单独使用JPA注释进行三向连接吗?如下面的实体伪代码所示:

@Entity
@Table(name="event")
public class Event {
  public Long datetime;
  public String name;
  public Long processId;
  @OneToOne
  @JoinColumn(
    name = "processId", referencedColumnName="id",
    insertable=false, updatable=false)
  private Process process;

  @OneToOne
  @JoinColumn(
    name = "datetime", referencedColumnName="datetime",
    insertable=false, updatable=false)
  @JoinColumn(
    name = "process.sequence", referencedColumnName="sequence",
    insertable=false, updatable=false)
  private Operation operations;
}

因此,没有必要在JPQL中指定传递连接约束

SELECT e FROM Event e
INNER JOIN FETCH e.process p
INNER JOIN FETCH e.operations q

如何使用JPA注释建模传递连接?

2 回答

  • 2

    您似乎试图模拟查询而不是数据 . 您应该正确建模数据,然后编写查询 .

    你似乎有

    事件

    • 进程

    • ManyToOne(processId)

    处理

    • events - OneToMany

    • 操作 - OneToMany

    手术

    • 进程 - ManyToOne(序列)(这个有点奇怪,因为序列不是Id,这不在JPA规范中,但是一些JPA提供者可能支持它)

    要查询事件的所有操作,您可以使用,

    Select o from Operation o join o.process p join p.events e where e.datetime = o.datetime
    

    要让所有对象重新使用,

    Select o, p, e from Operation o join o.process p join p.events e where e.datetime = o.datetime
    

    如果您确实需要将查询建模为关系,则这超出了JPA规范,但某些JPA提供程序可能会支持它 . 在EclipseLink中,您可以使用DescriptorCustomizer配置任何关系以使用任何表达式条件,或者您拥有SQL .

  • 1

    您的伪映射几乎是正确的解决方案,您只需要在_1687751中将两个 @JoinColumn 分组:

    @OneToOne
    @JoinColumns({
      @JoinColumn(
        name = "datetime", referencedColumnName="datetime",
        insertable=false, updatable=false),
      @JoinColumn(
        name = "sequence", referencedColumnName="sequence",
        insertable=false, updatable=false)
    })
    private Operation operations;
    

相关问题