この質問の図で概説されているものと非常によく似た状況があります: JPA. JoinTable と 2 つの JoinColumnsですが、問題は異なります。
Function
、Group
、およびの3 つのテーブルがありLocation
ます。Location
現在、と をGroup
使用して結合テーブルをセットアップしてい@JoinTable
ます。@ManyToMany
両側にあり、完璧に機能します。
同じ をLocation
持つ複数の に no を関連付ける必要がないという制約を追加しようとしています。そこで、次のように、SQL スキーマの結合テーブルに列を追加し、列と列全体に一意性制約を追加しました。Group
Function
Function
Location
Function
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;
次に、モデル エンティティで次の設定を試みました。
@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;
}
(明らかに、これらのエンティティには他にもありますが、この質問に関連する部分だけに絞り込みました。)
これは動作しません。に関連付けられたにLocation
関連付けられたを作成する簡単なテストを作成すると、トランザクションをコミットするためにセッションをフラッシュしようとすると、Hibernate は次のように表示します。Group
Function
java.lang.ClassCastException: my.package.Group cannot be cast to java.io.Serializable
何が起こっているのかというと、Hibernate が混乱し、手を投げ出して、「シリアル化してデータベースに送信し、何が起こっているのかを理解してくれることを願っています」と言っているのだと思います。
を追加implements Serializable
して追加するserialVersionUID
とGroup
、次のようになります。
org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: FUNCTION_ID
この時点でどのように進めればよいのか、あるいはすでに間違った道を進みすぎているのかどうか、よくわかりません。SQL について正しく考えていないのかもしれませんが、このばかげたことをすべて含まない、この制約を確実にするためのはるかに簡単な方法があります。
編集:私のシステムでは、関連するテーブルの DAO には保存機能がありません。つまり、制約がデータベースに設定されている限り、アプリケーションは気にしません。何も挿入できないため、制約に違反するものを挿入することはできません。
編集 2:上記の問題を最初に解決したことはなく、代わりに、上記の最初の編集セクションで述べたように、Java コードに触れずにデータベース スキーマに 3 番目の列を追加しただけです。@Embedded
しかし、それ以来、複合キーを使用して明示的な結合テーブル オブジェクトを作成して実験してきましたが、うまくいくようです。