0

我的应用程序中有一个 Question 实体和一个 QuestionCategory 实体。在数据库中,这是一个多对多的关系。我可能需要一些帮助。

我应该在引用 QuestionCategory 和 visa verca 的问题中创建列表引用吗?然后 JPA 可以根据您从哪个实体开始自动获取类别或问题。

或者您是否应该在它们之间没有引用,然后使用 JPQL 作为命名查询来检索属于该类别的问题,或者根据您所追求的问题检索属于这些问题的类别?

我不知道我是否使用了很多引用。你如何决定这个?

4

2 回答 2

0

中没有Bidirectional关系ManyToMany。主要的事情是注意使用CascadeType. 根据您的CascadeType类型使用情况,可能会出现不必要的问题。在我的例子中,ManagerProjectManyToMay关系。

例子 :

管理器.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);
        }
    }
}

项目.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);
        }
    }
}   

多对多测试.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.REMOVECascadeType.ALL包含在Manager实体中。

  1. 有两个经理 m1 和 m2。m1 有三个项目 p1、p2 和 p3。m2 有两个项目 p1 和 p2。
  2. 如果 m1 已被移除,相关项目 p1、p2 和 p3 将自动移除。
  3. 在这里,问题是没有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.PERSISTCascadeType.ALL包含在Manager实体中。

  1. 如果您想保留一个Manager,它的项目可能是新的和现有的记录。
  2. 对于新的实例Project将是新的记录。
  3. 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,无论您创建什么ManagerProject引用都将通过查询从数据库中检索。

于 2012-10-26T09:23:55.380 回答
0

JPA 提供者确实支持多对多关系。因此,您可以按您提到的那样放置列表并用适当的 ManyToMany 注释标记它并加入列名,JAP 将为您完成剩下的工作。顺便说一句,您拥有哪个 JPA 提供商???像hibernate,IBatis等??

代码示例:http ://www.roseindia.net/jpa/eclipsejpaexamples/jparelationship/many-to-many.shtml

于 2012-10-26T06:34:35.513 回答