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が挿入されると、。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:dbスキーマを変更できません。オプションではありません

4

1 に答える 1

1

注釈を使用してこれを行う方法はわかりませんが、iveは役立つ可能性のある回避策を見つけました。

@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 に答える