在休眠状态下使用单表策略时,将超类的实例更新为子类的实例

时间:2019-05-13 09:45:48

标签: mysql hibernate spring-boot spring-data-jpa single-table-inheritance

我正在开发一个项目管理系统,该系统具有三个用户,即员工,经理和HRM。雇员和经理位于具有多对多递归关系的同一个实体中(我们称其为Employee实体)。 Employee实体和HRM实体继承了User实体。这里使用的休眠继承策略是单表。    最初,在注册用户时,他被保存为User(用户类型为Repository)的实例。当他分配给特定项目时,我想将用户实例更新为员工实例或Manager实例。如何使用spring数据jpa来实现。我正在使用Spring Boot进行项目。

我已经使用java类创建了实体,并映射了每个实体。 我没有在下面的代码中提供Project和Tasks类。如有必要,我可以提供。

以下是User类。

@Entity
@Table(name = "users")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
        name="User_Type",
        discriminatorType=DiscriminatorType.STRING
        )
public class User{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="user_id")
    private Long id;

    private String name;

    private String email;

    private String password;

    private String mobilenumber;

    private String gender;

    private String resetToken;

    @ManyToMany(fetch = FetchType.LAZY, cascade={CascadeType.ALL})
    @JoinTable(name = "user_roles", 
        joinColumns = @JoinColumn(name = "user_id"), 
        inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles = new HashSet<>();//roles refer to the employee,manager and HRM roles

//public getters and setters

以下是继承的Employee类

@Entity
@DiscriminatorValue("Employee")
public class Employee extends User {
    @ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
    @JoinTable(name = "employee_project",
    joinColumns = @JoinColumn(name = "user_id"),
    inverseJoinColumns = @JoinColumn(name = "project_id")
    )
    private Set<Project> project = new HashSet<>();

    @ManyToMany
    @JoinTable(name = "employee_tasks",
    joinColumns = @JoinColumn(name = "user_id"),
    inverseJoinColumns = @JoinColumn(name = "task_id")
    )
    private Set<Task> tasks = new HashSet<>();

    @ManyToMany
    @JoinTable(name = "rm_employee",
    joinColumns = @JoinColumn(name = "user_id"),
    inverseJoinColumns = @JoinColumn(name = "rm_id")
    )
    private Set<Employee> managers = new HashSet<>();

    @ManyToMany
    @JoinTable(name = "rm_employee",
    joinColumns = @JoinColumn(name = "rm_id"),
    inverseJoinColumns = @JoinColumn(name = "user_id")
    )
    private Set<Employee> employees = new HashSet<>();

//public getters and setters

我尝试了以下方法,将User实例转换为Employee实例,从而导致CastException。

Optional<User> optional = userRepo.findById(id);

Employee employee = (Employee)optional.get();

以下是er模型的草图

1 个答案:

答案 0 :(得分:0)

我能够不用继承就解决问题。实际上,我不得不避免继承,因为就Java而言,类型不能从一种更改为另一种。在此示例中,用户类型无法按您希望的那样转换为雇员或经理。因此解决方案是为Manager和Employee创建两个单独的类(这不应像我在问题中所做的那样扩展User类)。这两个应标注为Entity,并应具有ID字段。您可以在两个类中都有一个具有上述Id字段的构造函数,并且无论何时将用户分配给项目,都可以使用此构造函数,具体取决于他是经理还是雇员来创建经理或雇员的相应实例。

员工类别如下

public class Employee{

    @Id
    private Long employeeId;

    @ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
    @JoinTable(name = "employee_project",
    joinColumns = @JoinColumn(name = "employee_id"),
    inverseJoinColumns = @JoinColumn(name = "project_id")
    )
    private Set<Project> project = new HashSet<>();

    @ManyToMany
    @JoinTable(name = "employee_rm",
    joinColumns = @JoinColumn(name = "employee_id"),
    inverseJoinColumns = @JoinColumn(name = "rm_id")
    )
    private Set<Manager> managers = new HashSet<>();

    @ManyToMany
    @JoinTable(name = "employee_tasks",
    joinColumns = @JoinColumn(name = "employee_id"),
    inverseJoinColumns = @JoinColumn(name = "task_id")
    )
    private Set<Task> tasks = new HashSet<>();

    public Employee() {}

    public Employee(Set<Project> project, Set<Manager> managers, Set<Task> tasks, Long employeeId ) {
        super();
        this.project = project;
        this.managers = managers;
        this.tasks = tasks;
        this.employeeId=employeeId;
    }
//with public getters and setters

和Managers类如下

@Entity
public class Manager {

    @Id
    private Long managerId ;

    @ManyToMany
    @JoinTable(name = "manager_employee",
    joinColumns = @JoinColumn(name = "manager_id"),
    inverseJoinColumns = @JoinColumn(name = "user_id")
    )
    private Set<Employee> employees = new HashSet<>();

    @OneToOne
    @JoinColumn(name="project_id")
    private Project project;

    public Manager() {}

    public Manager(Long managerId) {
        super();
        this.managerId = managerId;
    }
//public getters and setters