java JPA 三路连接注解

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12697703/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 09:53:06  来源:igfitidea点击:

JPA 3-way join annotation

javajpaormjpql

提问by Blessed Geek

There are three tables modeled as three entities:

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

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

Any unique single record of process-operation-sequence is obtained by the SQL that has a 3-way join constraint:

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

To implement that in JPA, I have to make a list of operations, which would be explicitly narrowed down to a single record thro the JQPL equality 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;
}

Where the JPQL specifies the transitive 3rd join constraint:

其中 JPQL 指定了可传递的第三连接约束:

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

However, I want all three constraints to be modeled inside the entity POJO. Shouldn't there be way to use JPA annotations alone to three-way join? As the following entity pseudo-code illustrates:

但是,我希望在实体 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;
}

So that it would not be necessary to specify transitive-join constraint in the JPQL

这样就没有必要在 JPQL 中指定传递连接约束

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

How do I model a transitive join using JPA annotations?

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

回答by James

You seem to be trying to model a query, instead of your data. You should model your data correctly, then write your query.

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

You seem to have

你好像有

Event

事件

  • process
  • ManyToOne (processId)
  • 过程
  • 多对一(processId)

Process

过程

  • events - OneToMany
  • operations - OneToMany
  • 事件 - 一对多
  • 操作 - 一对多

Operation

手术

  • process - ManyToOne (sequence) (this one is a little odd, as sequence is not the Id, this is outside of the JPA spec, but some JPA provider may support it)
  • process - ManyToOne(序列)(这个有点奇怪,因为序列不是 Id,这超出了 JPA 规范,但一些 JPA 提供者可能支持它)

To query all operations for an event, you could use,

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

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

To get all the object back use,

为了让所有对象重新使用,

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

If you really need to model the query as a relationship, this is outside of the JPA spec, but some JPA providers may support it. In EclipseLink you can use a DescriptorCustomizer to configure any relationship to use any expression criteria, or you own SQL.

如果您确实需要将查询建模为关系,这不在 JPA 规范范围内,但某些 JPA 提供程序可能支持它。在 EclipseLink 中,您可以使用 DescriptorCustomizer 来配置任何关系以使用任何表达式标准,或者您拥有 SQL。

回答by Dragan Bozanovic

Your pseudo-mappings are almost the correct solution, you just need to group two @JoinColumns in a @JoinColumns:

您的伪映射几乎是正确的解决方案,您只需要将两个@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;