J'ai une situation qui est assez similaire à celle décrite dans le diagramme de cette question: JPA. JoinTable and two JoinColumns, mais avec des problèmes différents.JPA @JoinTable - Trois colonnes d'ID
J'ai trois tables: Function
, Group
et Location
. Actuellement, j'ai une table de jointure mise en place entre Location
et Group
en utilisant @JoinTable
. Il est @ManyToMany
des deux côtés, et fonctionne parfaitement bien.
Je tente d'ajouter la contrainte qu'aucun Location
ne doit être associé à plus d'un Group
qui a le même Function
. J'ai donc ajouté une colonne pour Function
à ma table de jointure dans mon schéma SQL et une contrainte d'unicité dans les colonnes Location
et Function
, comme ceci:
create table function_table (
id varchar(50),
primary key(id)
);
create table group_table (
id varchar(50),
function_id varchar(50) not null,
primary key(id)
);
alter table group_table add constraint FK_TO_FUNCTION foreign key (function_id) references function_table;
create table location_table (
id varchar(50),
primary key(id)
);
create table group_location_join (
location_id varchar(50) not null,
group_id varchar(50) not null,
function_id varchar(50) not null,
primary key(location_id, group_id, function_id),
unique(location_id, function_id)
);
alter table group_location_join add constraint FK_TO_LOCATION foreign key (location_id) references location_table;
alter table group_location_join add constraint FK_TO_GROUP foreign key (group_id) references group_table;
alter table group_location_join add constraint FK_TO_FUNCTION foreign key (function_id) references function_table;
Je puis essayé de mettre en place ce qui suit dans mes entités du modèle:
@Entity
@Table(name = "function_table")
public class Function {
@Id
@Column(name = "id", length = 50)
private String id;
}
@Entity
@Table(name = "group_table")
public class Group {
@Id
@Column(name = "id", length = 50)
private String id;
@ManyToOne
@JoinColumn(name = "function_id", referencedColumnName = "id", nullable = false)
private Function function;
@ManyToMany
@JoinTable(name = "group_location_join",
joinColumns = {@JoinColumn(name = "group_id", referencedColumnName = "id"),
@JoinColumn(name = "function_id", referencedColumnName = "function_id")},
inverseJoinColumns = @JoinColumn(name="location_id", referencedColumnName = "id"))
private Set<Location> locations;
}
@Entity
@Table(name = "location_table")
public class Location {
@Id
@Column(name = "id", length = 50)
private String id;
@ManyToMany
@JoinTable(name = "group_location_join",
joinColumns = @JoinColumn(name="location_id", referencedColumnName = "id")
inverseJoinColumns = {@JoinColumn(name = "group_id", referencedColumnName = "id"),
@JoinColumn(name = "function_id", referencedColumnName = "function_id")})
private Set<Group> groups;
}
(de toute évidence, il est plus à ces entités, mais je les Bx_boom que les parties concernées à cette question.)
cela ne fonctionne pas. Quand j'écris un test simple pour créer un Location
associé à un Group
qui est associée à une Function
, la minute où je tente de vider la session pour valider la transaction, Hibernate me donne ceci:
java.lang.ClassCastException: my.package.Group cannot be cast to java.io.Serializable
Je pense que ce qui se passe Hibernate est confus, lève les mains et dit: "Je vais juste le sérialiser, l'envoyer à la base de données, et j'espère qu'il sait ce qui se passe."
Quand j'ajoute implements Serializable
et ajouter un serialVersionUID
à Group
, je puis obtenir ceci:
org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: FUNCTION_ID
Je ne suis pas sûr de savoir comment procéder à ce point, ou si peut-être je l'ai déjà trop avancé vers le bas le mauvais chemin. Peut-être que je ne pense pas au SQL correctement, et il y a un moyen beaucoup plus facile d'assurer cette contrainte qui n'implique pas tout ce ridicule.
Éditer: Dans mon système, les DAO pour les tables impliquées n'ont aucune capacité de sauvegarde. Ce qui signifie que tant que ma contrainte est configurée dans la base de données, mon application ne s'en soucie pas; il ne peut pas insérer des choses qui violent la contrainte parce qu'il ne peut pas insérer des choses du tout.
Edit 2: Je ne l'origine résolu le problème posé, et au lieu simplement ajouté une troisième colonne dans mon schéma de base de données sans toucher le code Java, comme indiqué dans mon premier Modifier section ci-dessus. Mais depuis j'ai expérimenté avec la création d'un objet table de jointure explicite avec une clé composée @Embedded
, et cela semble fonctionner.
Voulez-vous dire une clé composite 'Group'? Parce que je ne le veux absolument pas. Lorsque quelque chose d'autre dans le système fait référence 'Group' par clé primaire, il ne devrait traiter que de la colonne' id'. Si je donne à 'Group' une clé primaire composite, cela changera ce fait; tout ira chercher 'Group's par' id' ET 'function_id'. Je ne veux pas ça. Je veux seulement obtenir 'function_id' dans la table' group_location_join'. –