2

この質問の図で概説されているものと非常によく似た状況があります: JPA. JoinTable と 2 つの JoinColumnsですが、問題は異なります。

FunctionGroup、およびの3 つのテーブルがありLocationます。Location現在、と をGroup使用して結合テーブルをセットアップしてい@JoinTableます。@ManyToMany両側にあり、完璧に機能します。

同じ をLocation持つ複数の に no を関連付ける必要がないという制約を追加しようとしています。そこで、次のように、SQL スキーマの結合テーブルに列を追加し、列と列全体に一意性制約を追加しました。GroupFunctionFunctionLocationFunction

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 は次のように表示します。GroupFunction

java.lang.ClassCastException: my.package.Group cannot be cast to java.io.Serializable

何が起こっているのかというと、Hibernate が混乱し、手を投げ出して、「シリアル化してデータベースに送信し、何が起こっているのかを理解してくれることを願っています」と言っているのだと思います。

を追加implements Serializableして追加するserialVersionUIDGroup、次のようになります。

org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: FUNCTION_ID

この時点でどのように進めればよいのか、あるいはすでに間違った道を進みすぎているのかどうか、よくわかりません。SQL について正しく考えていないのかもしれませんが、このばかげたことをすべて含まない、この制約を確実にするためのはるかに簡単な方法があります。

編集:私のシステムでは、関連するテーブルの DAO には保存機能がありません。つまり、制約がデータベースに設定されている限り、アプリケーションは気にしません。何も挿入できないため、制約に違反するものを挿入することはできません。

編集 2:上記の問題を最初に解決したことはなく、代わりに、上記の最初の編集セクションで述べたように、Java コードに触れずにデータベース スキーマに 3 番目の列を追加しただけです。@Embeddedしかし、それ以来、複合キーを使用して明示的な結合テーブル オブジェクトを作成して実験してきましたが、うまくいくようです。

4

1 に答える 1

1

複合主キーを作成しようとしています。@EmbeddableHibernate では、注釈を使用してそれを行うことができます。以下の例では、2 つのエンティティに対して複合キーを使用する方法を見つけることができます。

この例を進めて、独自のバージョンの主キーを作成できると思います。

ManyToMany を複合主キーと注釈でマッピングする:

于 2013-02-15T18:16:06.330 に答える