0

私はHibernateでJPAを使用しています。

UserクラスとFlagクラスがあります:

class User
{
    // ...
}

class Flag
{
    @OneToOne(optional=false)
    private User user;

}

UserクラスのFlagオブジェクトへの参照は必要ありません(これが重要なポイントです)。しかし、ユーザーを削除するときは、関連するフラグ(存在する場合)も削除したいのですが、外部キー制約なしで例外に失敗します!

次のように、ユーザー内にフラグへの参照を追加できることはわかっています。

class User
{
    @OneToOne(optional=true, cascade=CascadeType.ALL, mappedBy="user")
    @org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private Flag flag;
}

そして、ユーザーを削除すると、Flagオブジェクトが削除されます。

しかし、ユーザーにフラグを参照せずにフラグをカスケード削除することは可能ですか?

そうでない場合、そのようなオブジェクトを削除する正しい方法はどうでしょうか?

4

2 に答える 2

1

この場合、削除を自動的にカスケードすることはできません。独自の削除を実装する必要があります。

ユーザーを削除するときは、最初に次のようなクエリを実行します。

delete from Flag F where F.userId = :userId
于 2012-08-13T04:24:36.650 に答える
0

使用しているデータベースがわからなかったので、MySQLと想定します。

これらは私たちのテーブルです。user_iduser_flag_idの間の1対1のマッピング、およびondeleteカスケードonupdateカスケード句に注意してください。

CREATE TABLE `user` (
  `user_id` int(11) NOT NULL DEFAULT '0',
  `user_name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB;

CREATE TABLE `user_flag` (
  `user_flag_id` int(11) NOT NULL DEFAULT '0',
  `user_flag_name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`user_flag_id`),
  CONSTRAINT `fk_user_id` FOREIGN KEY (`user_flag_id`) REFERENCES `user` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;

これらを前提として、次のようなマッピングを作成できます。

@Entity(name = "user")
@Table(schema = "test", name = "user")
public final class User {

  @Id
  @Column(name = "user_id")
  public int id;

  @Basic
  @Column(name = "user_name")
  public String name;
}

@Entity(name = "user_flag")
@Table(schema = "test", name = "user_flag")
public final class UserFlag {

  @Id
  @Column(name = "user_flag_id")
  public int id;

  @Basic
  @Column(name = "user_flag_name")
  public String name;

  @OneToOne
  @JoinColumn(name = "user_flag_id", referencedColumnName = "user_id")
  public User user;
}

次のデータがあると仮定します。

+---------+-----------+
| user_id | user_name |
+---------+-----------+
|       1 | Joe       |
|       2 | Jane      |
|       3 | Jacob     |
+---------+-----------+

+--------------+----------------+
| user_flag_id | user_flag_name |
+--------------+----------------+
|            1 | Joe's flag     |
|            3 | Jacob's flag   |
+--------------+----------------+

次のコードは、面倒なことなく、ユーザーを削除すると、関連するフラグが削除されることを示しています(ただし、その逆はありません)。

@Test
public void test() {
  EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
  EntityManager em = emf.createEntityManager();
  EntityTransaction et = em.getTransaction();

  // prints out our three users, Joe, Jane and Jacob
  for (User u : em.createQuery(String.format("select u from %s u", User.class.getName()), User.class)
      .getResultList())
    System.out.format("User{id=%s, name=%s}\n", u.id, u.name);

  // prints out Joe's and Jacob's flags
  for (UserFlag uf : em.createQuery(String.format("select uf from %s uf", UserFlag.class.getName()), UserFlag.class)
      .getResultList())
    System.out.format("UserFlag{id=%s, name=%s}\n", uf.id, uf.name);

  et.begin();
  User jacob = em.find(User.class, 3);
  em.remove(jacob);
  et.commit();

  // prints out our remaining users, Joe and Jane
  for (User u : em.createQuery(String.format("select u from %s u", User.class.getName()), User.class)
      .getResultList())
    System.out.format("User{id=%s, name=%s}\n", u.id, u.name);

  // prints out Joe's flag
  for (UserFlag uf : em.createQuery(String.format("select uf from %s uf", UserFlag.class.getName()), UserFlag.class)
      .getResultList())
    System.out.format("UserFlag{id=%s, name=%s}\n", uf.id, uf.name);

  em.close();
  emf.close();
}

この例では、選択したエンジンがInnoDBであることを前提としています。ただし、MyISAMを使用したい場合は、トリガーを使用して、onupdateカスケードondeleteカスケード句をシミュレートできます。

于 2012-08-13T18:39:35.777 に答える