2

次のようなテーブル階層があります

Job{jobId, title} との 1 対多の関係を持つ Job{jobId, title}

Task{taskId, jobId(FK), task_title} との 1 対多の関係

SubTask{subTaskId, TaskId(FK), subtask_title}.

今、私はこれらの上記のプライマリテーブルを拡張するテーブルのサブセットを持っています

TechinalJob{jobId(FK), Technical_Details},

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

TechinalSubTask{subTaskId(FK), Technical_SubTask_Details}.

同様に、管理ジョブ/タスク/サブタスクがあります。

しかし、キャッチは、私は技術職/タスク/サブタスクまたは管理職の間に関係船を持っていないということです..関係は元のジョブ/タスク/サブタスクを介しています. 技術職/タスク/サブタスクまたは管理職にも主キーがありません。したがって、TechinalJob と TechincalTask​​ の間に双方向の 1 対多の関係を作成する必要がある場合は、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: TechincalJob.tasks の TechinalTask​​.jobという例外が発生しました。タスクを拡張し、タスクのジョブが公開されていることを確認していますが、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型付きアクセスメソッド(TechnicalJoたとえば. これは DB 構造を模倣しており、TechnicalJob にリンクされているが、管理タスクのレコードとも結合されている Task テーブルに行が存在することを妨げるものは何もないため、実際には TechnicalTask​​ ではありません。addTask(TechnicalTask task)TechnicalJob

スキーマを担当している場合は、すでに継承戦略 JOIN を使用しているため、Ver1 アプローチを使用することを検討してください。そのため、Job/Task クラスでのマッピングはありません (抽象ゲッターのみ)。そして、個々のサブクラスでのマッピング。これにより、型の制御が向上しますが、joinColumn は Task サブテーブルになります。

@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、特定のジョブのタスクのサブタイプ。タスクはジョブにマップされますが、ジョブはタスクにマップされず、サブジョブのみがマッピングされます。

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

}

EDIT 上記のコードは EclipseLink では機能しますが、 Hibernate では機能しません。Adithye が気付いたように、マッピング ターゲットがないために例外がスローされます。

  1. ジョブとそのサブクラスがあり、各ジョブにはタスクのリストがあり、各サブジョブには一般的なタスクのリストと、TechnicalTask​​s などの特殊なタスクの別のリストがあります。JobにはTaksがあり、TechnicalJobsにはTask(Jobから継承された)と独自のtechnicalTask​​sコレクションがあるため、Javaコードの種類は示唆されていました。

その場合、異なる結合テーブルにマップする必要があります。そうしないと、両方のコレクションが同じ値を保持します。

于 2015-03-24T20:02:21.257 に答える
0

Zieluに感謝します。私を助けてくれたあなたの努力に感謝します..私は最終的に解決策を見つけました. しかし、休止状態の継承によるものではありません。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 クエリを使用しなかったもう 1 つの理由でした。現在、Job と Task を直接クエリすることはできませんが、暗黙のポリモーフィズムのために、サブクラスの継承ごとに Hibernate Table を使用したとしても、それは機能しませんでした。

ありがとう..

于 2015-04-08T14:00:57.187 に答える