2016-08-01 17 views
1

虽然有很多的信息,围绕如何建模,在JPA(2),一个一对一的关系OR具有自然键的实体,我一直没能找到一个明确的/简单的答案如何,我们兼得的情况下,即一比一的关系,其中父表具有天然的关键建模。很显然,我可能错过了这样的教程;如果是的话,指点我也可以作为答案。如何在“父”表具有复合PK时在JPA中建立一对一关系?

而且,多次使用JPA和菜鸟如我,需要的不只是最基本的模式多一点的那一刻,一个能快速打中人墙。

因此,需要考虑以下DB模式:

enter image description here

会有什么相应的JPA注解对象模型? (我不放过你。我已经试过,因为我不想影响答案做的事情家伙...)

性能建议也欢迎(例如,“一到多能更快地执行”等等)!如在示出的following article

谢谢,

+0

父对象有复合PK等方面具有'@ IdClass'。 Child对象具有用'@ Id'和Parent引用标注的单个字段。不知道这是如何“非标准”。谁知道“T_CHILD_C_PK”是什么。你把FK放在一边或另一边,所以我必须假定它是P_NK_1和P_NK_2儿童 –

+0

事实上,前面的图表不太清楚,谢谢。我已经用(希望)更清晰的图像更新了该帖子。父表(T_PARENT)具有由2个字段(PARENT_PK1,PARENT_PK2)组成的自然键,并且正由子表T_CHILD引用。 –

+0

你的架构更加清晰了,但事实是,如果你只是有一个'@ OneToOne'在孩子回父那么简单映射(在儿童中的“父”关系场给出了孩子2个FK列表)。 –

回答

5

映射复合键并不困难。

复合标识符建出来两种数值列的这样的映射如下所示:

Embeddable 
public class EmployeeId implements Serializable { 

    private Long companyId; 

    private Long employeeId; 

    public EmployeeId() { 
    } 

    public EmployeeId(Long companyId, Long employeeId) { 
     this.companyId = companyId; 
     this.employeeId = employeeId; 
    } 

    public Long getCompanyId() { 
     return companyId; 
    } 

    public Long getEmployeeId() { 
     return employeeId; 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (!(o instanceof EmployeeId)) return false; 
     EmployeeId that = (EmployeeId) o; 
     return Objects.equals(getCompanyId(), that.getCompanyId()) && 
       Objects.equals(getEmployeeId(), that.getEmployeeId()); 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(getCompanyId(), getEmployeeId()); 
    } 
} 

父类,如下所示:

@Entity(name = "Employee") 
public static class Employee { 

    @EmbeddedId 
    private EmployeeId id; 

    private String name; 

    @OneToOne(mappedBy = "employee") 
    private EmployeeDetails details; 

    public EmployeeId getId() { 
     return id; 
    } 

    public void setId(EmployeeId id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public EmployeeDetails getDetails() { 
     return details; 
    } 

    public void setDetails(EmployeeDetails details) { 
     this.details = details; 
    } 
} 

而像这样的子:

@Entity(name = "EmployeeDetails") 
public static class EmployeeDetails { 

    @EmbeddedId 
    private EmployeeId id; 

    @MapsId 
    @OneToOne 
    private Employee employee; 

    private String details; 

    public EmployeeId getId() { 
     return id; 
    } 

    public void setId(EmployeeId id) { 
     this.id = id; 
    } 

    public Employee getEmployee() { 
     return employee; 
    } 

    public void setEmployee(Employee employee) { 
     this.employee = employee; 
     this.id = employee.getId(); 
    } 

    public String getDetails() { 
     return details; 
    } 

    public void setDetails(String details) { 
     this.details = details; 
    } 
} 

而且一切正常:

doInJPA(entityManager -> { 
    Employee employee = new Employee(); 
    employee.setId(new EmployeeId(1L, 100L)); 
    employee.setName("Vlad Mihalcea"); 
    entityManager.persist(employee); 
}); 

doInJPA(entityManager -> { 
    Employee employee = entityManager.find(Employee.class, new EmployeeId(1L, 100L)); 
    EmployeeDetails employeeDetails = new EmployeeDetails(); 
    employeeDetails.setEmployee(employee); 
    employeeDetails.setDetails("High-Performance Java Persistence"); 
    entityManager.persist(employeeDetails); 
}); 

doInJPA(entityManager -> { 
    EmployeeDetails employeeDetails = entityManager.find(EmployeeDetails.class, new EmployeeId(1L, 100L)); 
    assertNotNull(employeeDetails); 
}); 
doInJPA(entityManager -> { 
    Phone phone = entityManager.find(Phone.class, "012-345-6789"); 
    assertNotNull(phone); 
    assertEquals(new EmployeeId(1L, 100L), phone.getEmployee().getId()); 
}); 

代码可在GitHub

+0

谢谢Vlad!我想要得到的是“父”类(在你的例子中为'Employee')中的成员/属性,它允许我访问子(“EmployeeDetails”)。就像这样:'public class Employee {... public EmployeeDetails getDetails(){...} ...' –

+1

查看我更新的答案。 –

+0

真棒 - 再次感谢! –

相关问题