2

我遇到了以下问题:我必须将我的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 
--------------------------

我知道外键必须具有与其引用的主键相同的列(相同的列数)。关键是,一旦Employee插入 an ,id1 = 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.:我无法更改数据库架构,这不是一个选项

4

1 回答 1

1

我不确定如何使用注释来执行此操作,但我找到了一种可能对您有所帮助的解决方法。

@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

    }
于 2013-03-01T12:47:58.650 回答