gpt4 book ai didi

java - 一旦外键是主键的一部分,如何使用复合键映射自连接

转载 作者:行者123 更新时间:2023-11-30 11:35:25 25 4
gpt4 key购买 nike

我遇到了以下问题:我必须将我的 Employee 类映射到以下数据库模式(其中 id1 和 id2 是复合主键):

--------------------------
| id1 | id2 | ManagerId2 |
--------------------------
| 1 | 1 | NULL | <--- Have no manager / Can be manager of many
--------------------------
| 1 | 2 | 1 | <--- Is manager / Has manager 1-1
--------------------------
| 1 | 3 | 1 | <--- Is manager / Has manager 1-1
--------------------------

我知道外键必须具有与其引用的主键相同的列(相同数量的列)。关键是一旦 Employeeid1 = 1 插入,它必须只引用 id1 = 1 的经理。一种保持完整性并避免出现以下情况的方法:

---------------------------------------
| id1 | id2 | ManagerId1 | ManagerId2 |
---------------------------------------
| 1 | 1 | NULL | NULL | <--- Have no manager / Can be manager of many
---------------------------------------
| 2 | 1 | NULL | NULL | <--- Have no manager / Can be manager of many
---------------------------------------
| 1 | 2 | 2 | 1 | <--- THIS IS NOT ALLOWED
---------------------------------------
| 1 | 3 | 2 | 1 | <--- NOR THIS
---------------------------------------

到目前为止,我得到的最好的是以下映射(尽管它按预期创建了表,但它只是不填充 ManagerId2 字段):

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

public Employee(){
}

@EmbeddedId
private EmployeeId id;
public void setId(EmployeeId id) {
this.id = id;
}
public EmployeeId getId() {
return id;
}

@ManyToOne(cascade={CascadeType.ALL})
@JoinColumns({
@JoinColumn(name = "id1", referencedColumnName = "id1", insertable=false, updatable=false), //its fine to have this attribute not insertable nor updatable
@JoinColumn(name = "id2_manager", referencedColumnName = "id2", insertable=false, updatable=false) //but I must be able to update this one!
})
private Employee manager;
public Employee getManager() {
return manager;
}
public void setManager(Employee manager) {
this.manager = manager;
}
}

@Embeddable
public class EmployeeId implements Serializable{

public EmployeeId() {

}

public EmployeeId(int id1, int id2) {
this.id1 = id1;
this.id2 = id2;
}

private int id1;

private int id2;

public int getId1() {
return id;
}

public void setId(int id1) {
this.id1 = id1;
}

public int getId2() {
return id2;
}

public void setId2(int id2) {
this.id2 = id2;
}

//hashCode and equals properly overriden
}

看了一整天,我似乎什么也找不到!有人可以告诉我我做错了什么,或者指出任何好的资源吗?

PS.: 我无法更改数据库架构,这不是一个选项

最佳答案

我不确定如何使用注释来做到这一点,但我找到了一个可能对您有所帮助的解决方法。

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

@EmbeddedId
private EmployeeId id;

private Integer id2_manager;

@PrePersist
@PreUpdate
public void prePersistUpdate() {
if (manager != null)
id2_manager = manager.getId().getId2();
}

public Employee() {
}

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

public EmployeeId getId() {
return id;
}

@ManyToOne(cascade = { CascadeType.ALL })
@JoinColumns({ @JoinColumn(name = "id1", referencedColumnName = "id1", insertable = false, updatable = false),
@JoinColumn(name = "id2_manager", referencedColumnName = "id2", insertable = false, updatable = false, nullable = true) })
private Employee manager;

public Employee getManager() {
return manager;
}

public void setManager(Employee manager) {
this.manager = manager;
}
}

测试

    static EntityManagerFactory emf;
static EntityManager em;

public static void main(String[] args) {

emf = Persistence.createEntityManagerFactory("unit");
em = emf.createEntityManager();

Employee manager = new Employee();
manager.setId(new EmployeeId(1, 1));

Employee e1 = new Employee();
e1.setId(new EmployeeId(1,2));
e1.setManager(manager);


em.getTransaction().begin();

em.persist(manager);
em.persist(e1);

em.getTransaction().commit();

Employee e2 = em.find(Employee.class, new EmployeeId(1, 2));

System.out.println(e2.getManager().getId().getId1() + "-" + e2.getManager().getId().getId2());
// prints 1-1

}

关于java - 一旦外键是主键的一部分,如何使用复合键映射自连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15145110/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com