2011-09-17 4 views
6

구체적인 수퍼 클래스를 서브 클래스 중 하나로 변경하고 싶습니다. 아래 예제를 포함 시켰습니다 :최대 절전 모드 : 기본 클래스의 인스턴스를 서브 클래스로 변경하십시오.

@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를 동일하게 유지해야합니다. 이렇게하면 고용을 통한 관리자의 기록을 쉽게 찾을 수 있습니다.

승격 작업을 구현하는 것은 데이터베이스에 대한 제약으로 인해 복잡합니다. 데이터베이스는 이전 직원을 제거하고 계단식 작업으로 모든 History 개체를 제거하지 않고 동일한 ID로 새 Manager를 만드는 것을 허용하지 않습니다. 그렇지 않으면 내 일이 쉬울거야!

은 추가 에 가능 또는 사용자 정의 SQL 작업에 의존하지 않고 기존 직원에 관리자 (새 매니저) 행 첨부? 이 작업이 완료

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()?

최대 절전 모드/JPA에서 가능합니까?

지금 당장 나는 어떤 아이디어가 도움이 될 것입니다. 당신은 의심의 여지가보기 시작되지 것으로

  • 아론

답변

6

, 여기에 바람에 노를하고 있습니다. 유감스럽게도 using inheritance to represent role이라는 고전적인 사례가있는 것 같습니다. 객체 모델이 잘못되어 Hibernate-객체 -Relational Mapper -와 Java - 객체 -oriented language -이 모두에서 당신과 싸울 것입니다. 최선의 방법은 리팩터링 및 데이터 마이그레이션으로 해결하는 것입니다. 최종 결과는 모든 사람이 직원이되어야하며 일부 직원은 하나 이상의 부서 또는 다른 직원과 "일종의"관계를 맺고 있어야합니다.

+0

이 일반적인 OO의 flub 처리의 인 - 최대 절전 모드 방법이없는 최대 절전 모드 있나요? 이 문제는 객체 - 정체성 문제로 묘사 될 수 있습니다. 나는 하나의 트랜잭션에 대해 Hequenate()와 == semanticists를 보존하는 것을 잊어 버리고 Hibenate에게 말할 수 있기를 원합니다. !=, then은 equal()이되어 서브 클래스에 대한 INSERT를 수행하도록 지시합니다. 나는 그것이 퍼시스턴스 VM 상태를 다소 불일치하게 만들 것이라는 것을 이해합니다. 애플리케이션은 실제로 그것을 위해 설계되었습니다 (캐싱 등 없음). 다른 아이디어? –

+0

@Aaron : 매핑 된 직원 -> 기록 관계가 있습니까? 그렇다면 Manager 객체를 만들고 이전 Employee의 모든 속성을 새 Manager에 복사 한 다음 Manager 기록에서 History 객체를 설정하고 Employee의 기록을 null로 설정하여 본질적으로 Employee 인스턴스에서 Manager 인스턴스까지의 내역. –

+0

감사합니다. 네, 그렇게해야 할 것 같아요 (또는 비슷한 :(). 원래 낮은 수준의 최대 절전 모드/jpa 방법 중 하나가 정체성의 변화를 관리하는 데 도움이 될 것이라고 생각했지만 - 작동하지 않을 것이라고 생각했습니다. . –

1

비슷한 상황이 발생했으며 데이터 모델이 실제 모델과 매우 잘 어울린다고해서 결함있는 데이터 모델이 비난 받아야한다고 생각하지 않습니다.

하위 클래스 레코드를 수동으로 삽입하여 원하는 결과를 얻을 수 있습니다. 때로는 뭔가 완료하려면 최대 절전 모드 주위에 가서 필요한, 그래서 이것은 내가 해결 방법으로이 경우에 무슨 짓을 :

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