JPA 3-way join annotation

大城市里の小女人 提交于 2019-12-08 15:27:25

问题


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:

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

@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:

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:

@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

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?


回答1:


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)

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)

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.




回答2:


Your pseudo-mappings are almost the correct solution, you just need to group two @JoinColumns in 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;


来源:https://stackoverflow.com/questions/12697703/jpa-3-way-join-annotation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!