2

我有一个表层次结构

Job{jobId, title} 与一对多关系

Task{taskId, jobId(FK), task_title} 与一对多关系

子任务{subTaskId, TaskId(FK), subtask_title}。

现在我有一个表的子集,这些表扩展了这些主表,例如

TechinalJob{jobId(FK), Technical_Details},

TechinalTask​​{taskId(FK), Technical_Task_Details},

TechinalSubTask{subTaskId(FK), Technical_SubTask_Details}。

同样,我将有管理作业/任务/子任务。

但问题是我在技术工作/任务/子任务或管理工作之间没有关系。这种关系是通过原始工作/任务/子任务来实现的。我在 Techincal Jobs/Tasks/SubTasks 或管理中也没有主键。因此,如果我必须在 TechinalJob 和 TechincalTask​​ 之间创建双向一对多关系,我必须通过 Job/Task/SubTask 表结构执行以下操作。如何使用 Hibernate 继承来实现这一点。

2015 年 3 月 25 日更新:

在尝试了Zielu建议的ver2之后。这是修改后的代码

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

    @Id
    private int jobId;

    @OneToMany(mappedBy="job")  
    protected Set<? extends Task> tasks;
    public Set<? extends Task> getTasks(
        return tasks;
    );

}

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

    @Id
    private int taskId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "jobId", updatable=false, insertable=false)
    public Job job;

    public Job getJob() {
        return job;
    }

    public void setJob(Job job)   {
        this.job= job;
    }
}

@Entity
@Table(name = "TechinalJob")    
@PrimaryKeyJoinColumn(name="jobId")  
public class TechincalJob extends Job { 

   @OneToMany(mappedBy="job") 
   Set<TechincalTask> tasks;

   @Override
   public Set<TechnicalTask> getTasks() {
       return (Set<TechnicalTask>)tasks;
   };

   @Column(name="Technical_Details")
   private Integer Technical_Details;

}

@Entity
@Table(name = "TechincalTask")    
@PrimaryKeyJoinColumn(name="taskId")  
public class TechincalTask extends Task {

    public TechincalJob getJob() {
        return (TechincalJob)job;
    }

    @Column(name="Technical_Task_Details")
    private Integer Technical_Task_Details;

}

当我尝试这个时,我得到一个异常说 Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: TechinalTask​​.job in TechincalJob.tasks。尽管我正在扩展 Task 并确保 Task 中的工作是公开的,但它无法在 TechnicalTask​​ 中找到工作。

提前致谢..

4

2 回答 2

3

这取决于您要达到的目标。

您提到在 DB 中扩展表,但没有像 SQL 中的子表这样的 Java 概念,所以让我们从 Java 的角度来看它。如果我写了一些对您来说显而易见的事情,请提前道歉(最接近您的解决方案的是第 1 点的末尾)。

  1. 你有 Job 及其子类。每个作业都有任务列表。任务也有它的子类。TechnicalJobs 中始终包含 TechnicalTask​​。

所以你会有代码:

//ver1    
class Job {

    public abstract Set<? extends Task> getTasks();
}

class TechnicalJob extends Job {
    Set<TechnicalTask> tasks = new HashSet<>();
    @Override
    public Set<TechnicalTask> getTasks() {
        return tasks;
    };
}

或者

//ver2
class Job {
    Set<? extends Task> tasks = new HashSet<>();
    public Set<? extends Task> getTasks(
        return tasks;
    );
}

class TechnicalJob extends Job {
    @Override
    public Set<TechnicalTask> getTasks() {
        return (Set<TechnicalTask>)tasks;
    };
}

你会像这样使用它:

TechnicalJob tj = ...;
Job jn = jt;
for (Task t : jn.getTasks()) t.doSomething();
for (TechnicalTask t: jt.getTasks()) t.doSomethingTechnical();

现在,您提到的 DB 结构看起来更像是 ver2,您在表中有 Task 的关系列,它将“转换”到 Job 中的 Set<> tasks 字段(您可以定义一个连接表 JobTask 来代替,这将是完全等价的的任务字段)。

因此,您的子作业、子任务中不需要额外的映射。简单的:

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

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    int jobId;

    @OneToMany(mappedBy="job")  
    Set<Task> tasks;

    public Set<? extends Task> getTasks() {
        if (tasks == null) tasks = new HashSet<>();
        return tasks;
    }
}
@Entity
@Table(name = "TechinalJob")    
public class TechinalJob extends Job {  

    @Override
    public Set<TechincalTask> getTasks() {
        return (Set<TechincalTask>)super.getTasks();
    }
}

您通过类​​型化的访问方法提供类型安全(仅TechnicalTasks进入TechnicalJob),例如addTask(TechnicalTask task)TechnicalJob. 它模仿您的数据库结构,其中没有什么可以阻止您在任务表中拥有一行,该行链接到 TechnicalJob 但也与管理任务中的记录连接,因此它不是真正的 TechnicalTask​​。

如果您负责架构,由于您已经在使用继承策略 JOIN,您可以考虑使用 Ver1 方法,因此在 Job/Task 类中没有映射(只有抽象 getter)。并在各个子类中进行映射。这将提供更好的类型控制,但 joinColumn 将位于任务子表中。

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

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    int jobId;
    public abstract Set<? extends Task> getTasks();
}
@Entity
@Table(name = "Task")    
@Inheritance(strategy=InheritanceType.JOINED)  
public class Task { 

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    int taskId;
}

@Entity
@Table(name = "TechinalJob")    
@PrimaryKeyJoinColumn(name="jobId")  
public class TechinalJob extends Job {  

    @OneToMany(mappedBy="job")
    Set<TechincalTask> tasks;
}

@Entity
@Table(name = "TechincalTask")    
public class TechincalTask extends Task {   

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "jobId")
    TechinalJob job;
}

最后建立在它之上,最接近你试图实现的匹配 == 任务表中的 joinColumn,特定工作中任务的子类型。Task 映射到 Job,但 Job 不映射到 Task,只有 subJobs 有映射:

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

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    int jobId;

    public abstract Set<? extends Task> getTasks();
}

@Entity
@Table(name = "TechinalJob")    
@PrimaryKeyJoinColumn(name="jobId")  
public class TechinalJob extends Job {  

    @OneToMany(mappedBy="job") //you need the mapped by, it was missing in your code
    Set<TechincalTask> tasks;

    @Column(name="Technical_Details")
    Integer Technical_Details;

    @Override
    public Set<TechincalTask> getTasks() {
        if (tasks == null) tasks = new HashSet<>();   
        return tasks;
    }
}

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

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    int taskId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "jobId")
    Job job;   
}

@Entity
@Table(name = "TechincalTask")    
@PrimaryKeyJoinColumn(name="taskId")  
public class TechincalTask extends Task {   

    //you don't define relationship to Job it comes from the parrent

    @Column(name="Technical_Task_Details")
    Integer Technical_Task_Details;

    public TechnicalJob getJob() {
        return (TechnicalJob)job;

}

编辑 上面的代码适用于 EclipseLink 但不适用于 Hibernate。正如 Adithye 注意到的那样,由于缺少映射目标而引发了异常。

  1. 您有工作及其子任务,每个工作都有任务列表,每个子工作都有一般任务列表和另一个专门任务列表,例如技术任务。你的 Java 代码有点像 Job 有 Taks 和 TechnicalJobs 有 Tasks(继承自 Job)和它自己的 TechnicalTask​​s 集合。

在这种情况下,它们必须映射到不同的连接表,否则两个集合将保存相同的值。

于 2015-03-24T20:02:21.257 回答
0

谢谢Zielu,感谢您为帮助我所做的所有努力。我终于找到了解决方案。但它不是通过hibernate继承..我使用了SecondaryTable和java继承的组合。我这样做的方法是通过创建超类@MappedSuperClass 并使子对象使用父表作为@Table 和子表作为@SecondaryTable

@MappedSuperClass
public class Job <J extends Job, T extends Task,> {  

    @Id
    private int jobId;

    @OneToMany(mappedBy="job")  
    protected Set<T> tasks;
    public Set<T> getTasks(
        return tasks;
    );

}

@MappedSuperClass
public class Task <T extends Task, J extends Job> {  

    @Id
    private int taskId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "jobId", updatable=false, insertable=false)
    public J job;
    public J getJob() {
        return job;
    }

}

@Entity
@Table("Job")
@SecondaryTable("TechinalJob")    
public class TechnicalJob extends Job<TechnicalJob, TechnicalTask> {  

   //get all relations from parent and additional columns
}

@Entity
@Table("Task")
@SecondaryTable("TechinalTask")
public class TechnicalTask extends Task<TechnicalTask, TechnicalJob> {  

   //get all relations from parent and additional columns

}

并为 Task 和 TechnicalTask​​ 编写一个通用查询,我计划使用 Criteria。在我的 DAO 中,我会有类似的东西

public class JobDAO <J extends Job> {

    protected Class<? extends Job> jobClass = Job.class;

    public List<J> getJobs(int id) {
        return (List<T>)(entityManager.unwrap(Session.class)).createCriteria(jobClass, "j").list();
    }
}

public class TaskDAO <T extends Task> {
    public List<T> getTasks
}

public class TechnicalJobDAO extends JobDAO<TechnicalJob> {

    @PostConstruct
    public void init() {
        jobClass = TechnicalJob.class;
    }
    //get all parents methods
}

public class TechnicalTaskDAO extends TaskDAO<TechnicalTaskk> {
    //get all parents methods
}

hibernate 中的隐式多态性是我不使用 HQL 查询的另一个原因,尽管它们很优雅。现在我失去了直接在 Job 和 Task 上查询,但是由于隐式多态性,即使我使用 Hibernate Table 每个子类继承也行不通。

谢谢..

于 2015-04-08T14:00:57.187 回答