11

将三个表建模为三个实体:

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

任何唯一的 process-operation-sequence 单条记录都由具有 3-way join 约束的 SQL 获得:

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 指定了传递的第三个连接约束:

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 注释对传递连接进行建模?

4

2 回答 2

2

您似乎正在尝试为查询建模,而不是您的数据。您应该正确地对数据建模,然后编写查询。

你好像有

事件

  • 过程
  • 多对一(进程 ID)

过程

  • 事件 - 一对多
  • 操作 - 一对多

手术

  • 流程 - ManyToOne (sequence)(这个有点奇怪,因为序列不是 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。

于 2012-10-03T13:05:30.913 回答
1

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

@OneToOne
@JoinColumns({
  @JoinColumn(
    name = "datetime", referencedColumnName="datetime",
    insertable=false, updatable=false),
  @JoinColumn(
    name = "sequence", referencedColumnName="sequence",
    insertable=false, updatable=false)
})
private Operation operations;
于 2016-02-09T18:17:36.803 回答