2016-03-24 46 views
0

如何为包含同一对象的两个实体在数据库中存储相同的表行? 以下说明我的无效尝试。jpa坚持与两个所有者相同的对象

@Entity 
public class Employee 
    { 
    @ManyToOne(cascade=CascadeType.ALL) 
    private Department department; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 
    private String name; 
    ... 
    <Getters and setters for all members here> 
    ... 
    } 

@Entity 
public class Department 
    { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 
    private String name; 
    @OneToMany(mappedBy="department") 
    private Collection<Employee> employees; 
    ... 
    <Getters and setters for all members here> 
    ... 
    } 

在Servlet我尝试以下方法:

Department department=new Department(); 
department.setName("HR"); 
Employee employee1=new Employee(); 
employee1.setName("Bob"); 
employee1.setDepartment(department); 
Employee employee2=new Employee(); 
employee2.setName("Anna"); 
employee2.setDepartment(department); 
... 
em.persist(employee1); 
em.persist(employee2); 

当我这样做,我得到的时候和Employee2是坚持,对部门的主键是已经在数据库中,因为它试图添加错误第二次是同一个部门。

如何让两位员工指向数据库中的同一行。

我是否需要通过将员工添加到部门来实现这一目标而从反面工作?

我觉得我在这里错过了一些基本的东西。

+0

什么是确切的例外,发布它 – Ramanlfc

+0

我没有看到被添加到Department.employees的Employee对象。 –

+0

错过了看东西的JPA提供程序的日志... –

回答

2

我认为如果是外键,你需要在Employee类中添加连接列关系(使用@JoinColumn)并使用部门ID。请参阅此link了解更多信息。

+0

但是,在这种情况下缺少的** @ JoinColumn **注释不能成为问题,因为持久性提供程序将使用默认值即** DEPARTMENT_ID **,其中** department **是拥有实体(** Employee **)中的属性,而** id **是目标实体(**部门**)中的主键。 – ujulu

+0

默认情况下JoinTable将仅在单向关系的情况下可用。不是在双向关系的情况下。请参阅此链接(http://stackoverflow.com/questions/8572554/onetomany-what-are-the-differences-between-join-table-and-foreign-key) – ypp

+0

我不是说** JoinTable * *但** JoinColumn **。有关详细说明,请参阅JPA 2.0规范部分** 2.10.2 **。 – ujulu

0

经过测试一些例子,我确定至少有两种方法来实现这一点。

第一种方法似乎最直接的方法就是不使用级联(从关系中删除级联= CascadeType.ALL)并首先插入部门。

Department department=new Department(); 
department.setName("HR"); 
Employee employee1=new Employee(); 
employee1.setName("Bob"); 
Employee employee2=new Employee(); 
employee2.setName("Anna"); 
... 
em.persist(department); 
employee1.setDepartment(department); 
em.persist(employee1); 
employee2.setDepartment(department); 
em.persist(employee2); 

这样做的原因是Employee中的ManyToOne关系将外键存储到Department表中。必须先坚持部门,否则在添加员工时外部密钥不存在。

实现此目的的另一种方法是将级联放在反面。

在部门级的变化

@OneToMany(mappedby="department") 

@OneToMany(mappedby="department",cascade=CascadeType.ALL) 

然后下面的工作:

Department department=new Department(); 
department.setName("HR"); 
Employee employee1=new Employee(); 
employee1.setName("Bob"); 
employee1.setDepartment(department); 
Employee employee2=new Employee(); 
employee2.setName("Anna"); 
employee2.setDepartment(department); 
... 
department.addEmployee(employee1); 
department.addEmployee(employee2); 
em.persist(department); 

这两个会导致两个数据库中的表

department 
ID NAME 
3 HR 

employee 
ID NAME DEPARTMENT_ID 
20 Bob  3 
21 Anna 3 

注意:确切的ID号可能会有所不同,因为它们是在这里自动生成的。

另一种方法是让部门的所有者和员工成为反向关系并执行类似的操作。