Bidirectional
に関係はありませんManyToMany
。主なものは、の使用に注意することですCascadeType
。タイプの使用状況に基づいて、CascadeType
不要な問題が発生する可能性があります。私の例では、Manager
とProject
はManyToMay
関係です。
例 :
Manager.java
@Entity
public class Manager implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@ManyToMany(mappedBy = "managers", cascade = CascadeType.REFRESH)
private List<Project> projects;
public Manager() {
projects = new ArrayList<Project>();
}
public Manager(String name) {
this.name = name;
projects = new ArrayList<Project>();
}
//getter and setter
public void add(Project project) {
if (!projects.contains(project)) {
projects.add(project);
}
if (!project.getManagers().contains(this)) {
project.getManagers().add(this);
}
}
}
Project.java
@Entity
public class Project implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@ManyToMany
@JoinTable(name = "PROJ_DEP", joinColumns = @JoinColumn(name = "PROJ_ID"), inverseJoinColumns = @JoinColumn(name = "DEPT_ID"))
private List<Manager> managers;
public Project() {
managers = new ArrayList<Manager>();
}
public Project(String name) {
this.name = name;
managers = new ArrayList<Manager>();
}
//getter and setter
public void add(Manager manager) {
if (!managers.contains(manager)) {
managers.add(manager);
}
if (!manager.getProjects().contains(this)) {
manager.getProjects().add(this);
}
}
}
ManyToManyTest.java
public class ManyToManyTest {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Project p1 = new Project("Project 1");
Project p2 = new Project("Project 2");
Project p3 = new Project("Project 3");
Manager m1 = new Manager("Jon");
m1.add(p1);
m1.add(p2);
m1.add(p3);
Manager m2 = new Manager("Kone");
m2.add(p2);
m2.add(p3);
em.persist(m1);
em.persist(m2);
System.out.println("Success..");
em.getTransaction().commit();
em.close();
}
}
想定するCascadeType.REMOVE
か、エンティティCascadeType.ALL
に含める。Manager
- 2 つのマネージャ m1 と m2 があります。m1 には 3 つのプロジェクト p1、p2、および p3 があります。m2 には 2 つのプロジェクト p1 と p2 があります。
- m1 が削除された場合、関連するプロジェクト p1、p2、および p3 が自動的に削除されます。
ここで、問題はm2のプロジェクト実績がないことです。
/*Kone's projects record will be loss.*/
Manager m = (Manager)em.createQuery("SELECT m FROM Manager m WHERE m.name = 'Jon' ").getSingleResult();
em.remove(m);
想定するCascadeType.PERSIST
か、エンティティCascadeType.ALL
に含める。Manager
- を保持したい場合
Manager
、そのプロジェクトは新規および既存のレコードである可能性があります。
- の新しいインスタンスの場合、
Project
新しいレコードになります。
Project
(By query)の既存のインスタンスが参照されます。
/*When m3 has persisted, p2 will be new record in Project table. p1 will be just reference.*/
Project p1 = (Project)em.createQuery("SELECT m FROM Project m WHERE m.name = 'Project 1' ").getSingleResult();
Project p2 = new Project("Project 1");
Manager m3 = new Manager("Nexz");
em.persist(m3);
私の提案はCascadeType.REFRESH
、あなたが作成したもの、Manager
またはProject
参照がクエリによってデータベースから取得されるものは何でも使用することです。