0

私はそれが欲しいものは単純ですが、私の問題の解決策を見つけることができません。私はplayframework1.2.3を使用しており、JPAとしてHibernateを使用しています。ですから、playframeworkは問題とは何の関係もないと思います。

私はいくつかのクラスを持っています(私は無関係なフィールドを省略します)

public class User {
  ...
}

public class Task {
  public DataContainer dataContainer;
}

public class DataContainer  {
  public Session session;
  public User user;
}

public class Session  {
  ...
}

したがって、タスクからDataContainerへ、およびDataContainerからSesssionへの関連付けがあり、DataContainerはユーザーに属しています。DataContainersは常に同じユーザーを持つことができますが、セッションはインスタンスごとに異なる必要があります。また、タスクのDataContainerもインスタンスごとに異なる必要があります。DataContainerはSesesionを持つことも、持たないこともできます(これは最適です)。私は一方向の関連付けのみを使用します。それで十分なはずです。

つまり、すべてのタスクに1つのDataContainerが必要です。すべてのDataContainer には、1人または同じユーザーが必要であり、 1つのセッションを持つことができます。

DBスキーマを作成するには、JPAアノテーションを使用します。

@Entity
public class User extends Model {
  ...
}

@Entity
public class Task extends Model {
  @OneToOne(optional = false, cascade = CascadeType.ALL)
  public DataContainer dataContainer;
}

@Entity
public class DataContainer extends Model  {
  @OneToOne(optional = true, cascade = CascadeType.ALL)
  public Session session;

  @ManyToOne(optional = false, cascade = CascadeType.ALL)
  public User user;
}

@Entity
public class Session extends Model {
  ...
}

ところで:モデルはプレイクラスであり、ロングタイプとしてプライマリIDを提供します。

エンティティごとにオブジェクトを作成して「それらを接続する」とは、関連付けを意味し、正常に機能します。しかし、セッションを削除しようとすると、DataContainerが削除したいセッションを参照しているため、制約違反の例外が発生します。

DataContainerのセッション(フィールド)をそれぞれnullに設定し、データベースで外部キー(session_id)を設定解除する必要があります。オプションなので、これで問題ありません。

わかりませんが、複数の問題があると思います。正しい注釈を使用してい@OneToOneますか?

私はインターネット上でいくつかの追加の注釈と属性を見つけました: @JoinColumnそしてmappedBy逆の関係のための属性。しかし、双方向ではないので、私はそれを持っていません。または、双方向の関連付けです。本質的に?

もう1つの試みは、更新または削除時にs@OnDelete(action = OnDeleteAction.CASCADE)から変更された制約を使用することでした。NO ACTION

ADD CONSTRAINT fk4745c17e6a46a56 FOREIGN KEY (session_id)
      REFERENCES annotation_session (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE CASCADE;

ただし、この場合、セッションを削除すると、DataContainerとUserが削除されます。それは私にとって間違っています。


編集: 私はpostgresql 9を使用していますが、jdbcのものはプレイに含まれています、私の唯一のdbconfigは
db=postgres://app:app@localhost:5432/app

4

2 に答える 2

3

OneToOneまたはManyToOneのどちらを使用する必要がありますか?状況を最もよく表している関連を使用してください。複数のDataContainerが同じセッションを持っている場合、それはManyToOneです。1つのDataContainerのみが特定のセッションを持つ可能性がある場合、それはOneToOneです。

ここで、セッションを削除しても、DataContainerがそれを参照している場合は、もちろん例外が発生します。これがFKの目的です。存在しないセッションを参照するDataContainerを使用できないようにします。したがって、セッションを削除するには、最初に、セッションを参照しているすべてのデータコンテナを更新する必要があります。

アソシエーションは単方向であるため、これを行うにはクエリが必要です。

select dc from DataContainer dc where dc.session = :session

このクエリを実行し、結果を繰り返し処理して、セッションをnullに設定します。次に、セッションを削除します。

アソシエーションが双方向の場合は、次のようにすることができます。

for DataContainer dc : session.getDataContainers() {
    dc.setSession(null);
}

更新クエリを使用して、1つのクエリですべてを実行することもできます。ただし、これらの変更は、セッションですでにロードされているDataContainerには行われないことに注意してください。

update DataContainer dc set dc.session = null where dc.session = :session
于 2012-06-08T16:36:39.153 に答える
0

よくわかりませんが、データベースは何を使用していますか? hibernateによって自動的にロードされますか、それとも独自のDDLクエリを使用して作成していますか? その場合は、制約がデータベース レベルで確立されているかどうかを確認してください。DataContainer テーブルの sessionId 外部キーが null 可能であることを確認してください。

于 2012-06-08T16:13:03.887 に答える