簡體   English   中英

Hibernate:將基類的實例更改為子類

[英]Hibernate: Change instance of base class to subclass

我想將一個具體的超類更改為其子類之一。 我在下面列舉了一個例子:

@Entity
@Table(name = "employees")
@Inheritance(strategy = InheritanceType.JOINED)
public class Employee {

    @Id
    @Column(name = "id")
    private String id;

    public Employee( String id ) {
        this.id = id;
    }
 ...
}

@Entity
@Table(name = "managers")
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
public class Manager extends Employee {

    public Manager( String id ) {
        super(id);
    }
 ...
}


@Entity
@Table(name = "history")
public class History {
 ...
/**
 * 
 */
@ManyToOne
@JoinColumn(name = "employee_id")
private Employee employee;
 ...
}

我正在使用的三個班級是員工,經理和歷史。 所有經理都是員工,但並非所有員工都是經理。 所有員工(和經理)都有歷史記錄。 員工可能會晉升為管理層。 發生這種情況時,應通過保持員工ID相同來保留員工的歷史記錄。 這樣可以輕松找到經理人的就業歷史。

由於數據庫受到限制,實施促銷操作變得復雜:數據庫不允許刪除舊的Employee並創建具有相同ID的新Manager,而不通過級聯操作刪除所有History對象 - 人力資源部門不允許這樣做,否則我的工作很簡單!

是否可以在不訴諸自定義SQL操作的情況下 Manager(新管理器)行添加附加到現有Employee?

我嘗試了以下解決方案但沒有成功:

public void promote( Employee employee ) {
    /* copy over the ID of the employee to the manager.  Will not work because employee with ID already exists */
    Manager manager = new Manager(employee.getId());
    this.entityManager.persist( manager );
}

... 要么 ...

public void promote( Employee employee ) {
    /* detach the employee then merge.  Will not work: fails, again, with a NonUniqueObject Exception */
    this.entityManager.detach( employee );
    Manager manager = new Manager(employee.getId());
    this.entityManager.merge( manager );
}

我怎么能這樣做? 我甚至在使用detach()merge()的正確軌道上?

這可能在Hibernate / JPA中嗎?

在這一點上任何想法都會有所幫助,因為我很難過!

  • 亞倫

正如你無疑開始看到的那樣,你在這里逆風而行。 不幸的是,看起來你有一個使用繼承來表示角色的經典例子。 Hibernate - 一個Object -Relational Mapper - 和Java--一個面向對象的語言 - 都會在這個問題上打擊你,因為你的對象模型是錯誤的。 我想說你最好的辦法是通過重構和數據遷移來解決它。 最終結果應該是每個人都是員工,而一些員工與一個或多個部門或其他員工之間存在某種“管理”關系。

我遇到了類似的情況,我不相信有缺陷的數據模型是錯誤的,因為數據模型很好地匹配了現實世界的模型。

您可以手動插入子類記錄以獲得所需的結果。 有時必須繞過Hibernate來完成某些事情,所以這就是我在這種情況下所做的解決方法:

sessionFactory.getCurrentSession().createSQLQuery(
            "insert into manager (employee_id, rank) " +
            "values (:employeeId, :rank) ")
            .setParameter("employeeId", employeeId)
            .setParameter("rank", rank)
            .executeUpdate();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM