J'ai besoin de joindre des tables sur un objet dans une hiérarchie de classes ORM où la colonne de jointure n'est PAS la clé primaire de la classe de base. Voici un exemple de table :
CREATE TABLE APP.FOO
(
FOO_ID INTEGER NOT NULL,
TYPE_ID INTEGER NOT NULL,
PRIMARY KEY( FOO_ID )
)
CREATE TABLE APP.BAR
(
FOO_ID INTEGER NOT NULL,
BAR_ID INTEGER NOT NULL,
PRIMARY KEY( BAR_ID ),
CONSTRAINT bar_fk FOREIGN KEY( FOO_ID ) REFERENCES APP.FOO( FOO_ID )
)
CREATE TABLE APP.BAR_NAMES
(
BAR_ID INTEGER NOT NULL,
BAR_NAME VARCHAR(128) NOT NULL,
PRIMARY KEY( BAR_ID, BAR_NAME),
CONSTRAINT bar_names_fk FOREIGN KEY( BAR_ID ) REFERENCES APP.BAR( BAR_ID )
)
Et voici les mappings (getters et setters éliminés par souci de concision)
@Entity
@Table(name = "FOO")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TYPE_ID", discriminatorType = javax.persistence.DiscriminatorType.INTEGER)
public abstract class Foo {
@Id
@Column(name = "FOO_ID")
private Long fooId;
}
@Entity
@DiscriminatorValue("1")
@SecondaryTable(name = "BAR", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "FOO_ID", referencedColumnName = "FOO_ID") })
public class Bar extends Foo{
@Column(table = "BAR", name = "BAR_ID")
Long barId;
}
Comment puis-je ajouter le mappage pour BAR_NAMES
étant donné que sa colonne de jonction n'est pas FOO_ID
pero BAR_ID
?
J'ai essayé ce qui suit :
@CollectionOfElements(fetch = FetchType.LAZY)
@Column(name = "BAR_NAME")
@JoinTable(name = "BAR_NAMES", joinColumns = @JoinColumn(table = "BAR", name = "BAR_ID", referencedColumnName="BAR_ID"))
List<String> names = new ArrayList<String>();
Cette opération échoue parce que le code SQL utilisé pour récupérer l'objet Bar tente d'obtenir une valeur BAR_ID à partir de la table FOO. J'ai également essayé de remplacer l'annotation JoinTable par
@JoinTable(name = "BAR_NAMES", joinColumns = @JoinColumn(name = "BAR_ID"))
Cela ne produit pas d'erreur SQL, mais ne permet pas non plus de récupérer des données, car la requête sur BAR_NAMES utilise le FOO_ID comme valeur de jointure au lieu du BAR_ID.
À des fins de test, j'ai alimenté la base de données avec les commandes suivantes
insert into FOO (FOO_ID, TYPE_ID) values (10, 1);
insert into BAR (FOO_ID, BAR_ID) values (10, 20);
insert into BAR_NAMES (BAR_ID, BAR_NAME) values (20, 'HELLO');
De nombreuses solutions qui semblent fonctionner renvoient une collection vide lorsqu'elles obtiennent l'objet Foo pour l'ID 10 (par opposition à une collection contenant 1 nom).