Alex Rivera | Logout

Hibernate: Change instance of base class to subclass

Asked 2011-09-17T19:00:59.173
9

I would like to change a concrete superclass to one of its subclass. I've included an example below:

@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;
 ...
}

The three classes I'm working with are Employee, Manager and History. All Managers are Employees, but not all Employees are Managers. All Employees (and Managers) have a History. Employees may be promoted to Management. When this happens an Employee's history should be retained by keeping their Employee ID the same. This will allow a Manager's History through employment to be easily found.

Implementing the promotion operation is complicated by constraints withing the database: the database will not allow removing the old Employee and creating a new Manager with the same ID without removing all of the History objects by cascading operation - which Human Resources won't allow, otherwise my job would be easy!

Is it possible to add or attach the Manager (new managers) row to an existing Employee without resorting to custom SQL operation?

I've tried the following solutions without success:

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 );
}

... or ...

publi
Edit
Report

1 Answer

2

I ran into a similar situation and I don't believe a flawed data model is to blame since the data model matches the real world model quite well.

You can insert the subclass record manually to achieve the desired result. Sometimes it's requisite to go around Hibernate to get something done, so this is what I did in this case as a workaround:

sessionFactory.getCurrentSession().createSQLQuery(
            "insert into manager (employee_id, rank) " +
            "values (:employeeId, :rank) ")
            .setParameter("employeeId", employeeId)
            .setParameter("rank", rank)
            .executeUpdate();
answered 2012-06-15T01:54:50.110

Your Answer