JPA中的实体之间的引用

时间:2012-10-26 06:13:10

标签: java java-ee jpa

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

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

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

我不知道我是否使用了很多参考文献。你怎么决定这个?

2 个答案:

答案 0 :(得分:0)

JPA提供商确实支持多对多关系。所以你可以按照你提到的那样列出&用适当的ManyToMany注释和标记来标记它加入专栏名称& JAP将为您完成剩余的工作。 BTW哪个JPA提供商你有???像hibernate,IBatis等?

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

答案 1 :(得分:0)

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

示例:

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.ALLManager

  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);
    
  4. 假设CascadeType.PERSIST实体中包含CascadeType.ALLManager

    1. 如果您想保留Manager,其项目可能是新的和现有的记录。
    2. Project的新实例将成为新记录。
    3. Project(按查询)的现有实例将被引用。

      /*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);
      
    4. 我的建议是使用CascadeType.REFRESH,无论您创建Manager还是Project,都会通过查询从数据库中检索引用。