2012-10-02 9 views
9

Es gibt drei Tabellen als drei Einheiten modelliert:JPA 3-Wege verbinden Anmerkung

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

Jeder einzigartige einzelnen Datensatz von Prozess-Betrieb-Sequenz wird durch die SQL erhalten, die eine 3-Wege-Join-Einschränkung hat:

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

um dies in JPA zu implementieren, muss ich eine Liste von Operationen machen, , die zu einem einzigen Datensatz nach unten thro der JQPL Gleichheit p.sequence = q.sequence ausdrücklich eingeschränkt werden würde

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

Wo die JPQL die transitive 3. legt beitreten Einschränkung:

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

Aber ich möchte, dass alle drei Bedingungen innerhalb des Unternehmens POJO modelliert werden. Sollte es keine Möglichkeit geben, JPA-Annotationen allein für dreiseitige Verbindungen zu verwenden? Wie die folgende Einheit Pseudo-Code zeigt:

@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 dass es nicht notwendig wäre, um anzugeben, transitive-Join-Einschränkung in der JPQL

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

Wie modelliere ich eine transitive Verknüpfung mit JPA Anmerkungen?

+0

BTW, ich habe die JAXB Anmerkungen weggelassen. Event muss absolut das XML-Root-Tag sein. Daher wird die Entity mit dem Event POJO modelliert. Die Event-Entität wird direkt als XML-DTO durch JAXB verwendet. Das heißt, Sie sollten nicht vorschlagen, dass ich ein anderes POJO als Wurzel verwende. –

+0

Ich bin nicht 100% sicher, was Ihr Problem ist ... Wenn Sie die ON-Klausel der Joins angeben, löst es Ihr Problem nicht? – slambeth

Antwort

2

Sie scheinen zu versuchen, eine Abfrage anstelle Ihrer Daten zu modellieren. Sie sollten Ihre Daten korrekt modellieren und dann Ihre Abfrage schreiben.

Sie scheinen

Ereignis

  • Prozess
  • ManyToOne (processId)

Prozess

  • Ereignisse zu haben - OneToMany
  • Operationen - OneToMany

Betrieb

  • Prozess - ManyToOne (Sequenz) (dies ist ein wenig ungerade als Folge nicht die ID ist, diese außerhalb des JPA spec ist, aber einige JPA Anbieter kann es unterstützen)

Um alle Operationen für ein Ereignis abzufragen, die Sie verwenden können,

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

alle das Objekt verwenden, um zurück,

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

Wenn Sie wirklich die Abfrage als eine Beziehung brauchen zu modellieren, ist dies außerhalb der PPV-Spezifikation, aber einige PPV-Anbieter es unterstützen. In EclipseLink können Sie einen DescriptorCustomizer verwenden, um beliebige Beziehungen für die Verwendung beliebiger Ausdruckskriterien zu konfigurieren, oder Sie besitzen SQL.

+4

Bitte akzeptieren Sie meine Entschuldigung - aber könnten Sie Ihre Antwort restrukturieren, um meine Frage zu beantworten, anstatt mir zu raten, wie ich mein Leben von Trümmern säubern soll, die Leute auf mich werfen? Vielen Dank. –

1

Ihre pseudo-Mappings sind fast die richtige Lösung, die Sie brauchen nur zu einer Gruppe zwei @JoinColumn s in einem @JoinColumns:

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