2017-01-21 5 views
0

現在、プログラムを実行するたびに3つの数値(companyName、groupName、hostName)を受け取るプログラムで作業しています。 3つの値を受け取るたびに、それらを1つのオブジェクト(Datas)にグループ化し、それらをリスト(リスト)に格納しました。1対多リレーションシップ参照のHibernateテーブルの重複エントリを削除する

私の目標は、3つのテーブル(会社、グループ、ホスト)を持つデータベースにすべての値を格納することです。

3つのテーブルが接続されています。CompanyはGroupと1対多、Groupは1対多のHostです。

私は3つのクラス(Company.java、Group.java、Host.java)を作成しました。これは適切な値をとり、コンストラクタを使用してクラスの新しいインスタンスを作成します。

次に、私は、クラスの各インスタンスを休止状態のセッションを使用してデータベースに格納します。

私のコードは次のようになります:

for (Datas data:Datas){ 
    Company company = new Company(data.getCompanyName); 
    Group group = new Group(company, data.getGroupName); 
    Host host = new Host(group, data.getHostName); 

    session.save(company); 
    session.save(group); 
    session.save(host);  
} 

上記のコードは、私が正しい一対多のリレーションシップで私のテーブルにすべての私のデータを保存できるようにしますが、それは私が防ぐことはできません。エントリを複製します。例えば

今、私のテーブルストア物事5件のデータが保存された後にこの方法:

Company 
id (auto-increment) Name 
1     Google 
2     Google 
3     Google 
4     Yahoo 
5     Yahoo 

Group 
id (auto-increment) Company_id Name 
1     1   HR 
2     2   HR 
3     3   OP 
4     4   HR 
5     5   PR 

Host 
id (auto-increment) Group_id Name 
1     1   Jane 
2     2   Harry 
3     3   Molly 
4     4   Garry 
5     5   Neo 

上の表は、技術的に正しいですが、私は本当に重複を排除します。今のCompanyテーブルでは、すべての "Google"と "Yahoo"のエントリはまったく同じものです。 Groupテーブルでは、1番目と2番目のエントリは同じものです。両方とも「HR」という名前を持ち、両方とも会社「Google」を参照しているためです。

3つの会社エントリ「Google」を作成するのではなく、1つだけ作成します。グループテーブルのすべてのエントリは、そのエントリのみを参照します。ホストテーブルのロジックは同じです。

正しい表は次のようになります。

Company 
id (auto-increment) Name 
1     Google 
2     Yahoo 

Group 
id (auto-increment) Company_id Name 
1     1   HR 
2     1   OP 
3     2   HR 
4     2   PR 

Host 
id (auto-increment) Group_id Name 
1     1   Jane 
2     1   Harry 
3     3   Molly 
4     4   Garry 
5     5   Neo 

は、どのように私は私のコードでは、このような調整を行うのですか? 3つのクラスをインスタンス化する前に、データで何かをする必要がありますか?または、クラスのコンストラクタでインスタンス化するときに何かする必要がありますか?または、そのような重複を防ぐために使用できるHibernateアノテーションがありますか?

ありがとうございました。

答えて

1

forループは基本的にビジネス自然キーの値に基づいてデータベースを照会し、その事実に基づいてレコードが存在するかどうかを判断する必要があります。

for (Datas data : datas) { 
    Company company = companyRepository.findByName(data.getCompanyName()); 
    if (company == null) { 
    // new company implies everything else is also new 
    company = new Company(data.getCompanyName()); 
    group = new Group(company, data.getGroupName()); 
    host = new Host(group, data.getHostName()); 
    session.save(company); 
    session.save(group); 
    session.save(host); 
    } 
    else { 
    // since company exists, we need to check whether group/host exist 
    Group group = groupRepository.findByName(data.getGroupName()); 
    if (group == null) { 
     // since group doesn't exist, neither will host 
     group = new Group(company, data.getGroupName()); 
     host = new Host(group, data.getHostName()); 
     session.save(group); 
     session.save(host); 
     // depending on relationships, you may need to link group to company 
     // followed by updating company. 
    } 
    else { 
     // group exists, check if host does 
     Host host = hostRepository.findByName(data.getHostName()); 
     if (host == null) { 
     // host doesn't, create it. 
     host = new Host(group, data.getHostName()); 
     session.save(host); 
     // depending on relationships, you may need to link host to group 
     // followed by updating group. 
     } 
    } 
    } 
} 

#findByName(String)方法を公開し、さまざまなリポジトリクラスがちょうどあなたがエンティティの指定された名前を探し述語を行うクエリを説明するためのものです。

Datas構造体が、既存のレコードとマージする必要がある名前の値よりも詳細な情報を持っている場合は、ロジックにループを追加して、フェッチされた永続オブジェクトに変更を適用する必要があります方法は#findByName(Stringです。

// Simplified example for the Host 
Host host = hostRepository.findByName(data.getHostName()); 
if (host == null) { 
    host = new Host(group, data.getHostName()); 
    host.setSomeOtherAttribute(data.getHostSomeOtherAttribute()); 
    session.save(host); 
} 
else { 
    host.setsomeOtherAttribute(data.getHostSomeOtherAttribute()); 
    session.update(host); 
} 
+0

偉大な答えをありがとう! – 000000000000000000000

関連する問題