2017-02-06 8 views
0

双方向OneToMany関係では、親が持つ子をすべて呼び出さずに子を削除するにはどうすればよいですか?JPA双方向OneToMany relashionship - 子削除禁止

私のアプリケーションは少し大きいので、問題を再現するためのサンプルプロジェクトを作成しました。私は2つのエンティティ、親と子を持っています。

親:

package com.example.entity; 

import javax.persistence.*; 
import java.util.List; 

@Entity 
public class Parent { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @OneToMany(
     mappedBy  = "parent", 
     cascade  = CascadeType.ALL, 
     fetch   = FetchType.LAZY, 
     orphanRemoval = true 
    ) 
    private List<Child> children; 
} 

ゲッターとセッターが示されていません!

子供:

package com.example.entity; 

import javax.persistence.*; 

@Entity 
public class Child { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "parent_id") 
    private Parent parent; 
} 

ゲッターとセッターが示されていません!

私も2 Repositorysあります

ChildRepository:

package com.example.dao; 

import com.example.entity.Child; 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.stereotype.Repository; 

@Repository 
public interface ChildRepository extends JpaRepository<Child, Long> {} 

ParentRepsitory:はまったく同じに見えますが。

は今、私は問題を再現するために、テストを作成しました:

RepositoryTest:

package com.example; 

import com.example.dao.ChildRepository; 
import com.example.dao.ParentRepository; 
import com.example.entity.Child; 
import com.example.entity.Parent; 
import org.junit.Assert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.context.SpringBootTest; 
import org.springframework.test.context.junit4.SpringRunner; 

import javax.transaction.Transactional; 
import java.util.Arrays; 

@RunWith(SpringRunner.class) 
@SpringBootTest 
public class RepositoryTest { 
    @Autowired 
    private ChildRepository childRepository; 

    @Autowired 
    private ParentRepository parentRepository; 

    @Test 
    @Transactional 
    public void test() { 
     Parent parent = new Parent(); 
     Child child1 = new Child(); 
     Child child2 = new Child(); 

     parent.setChildren(Arrays.asList(child1, child2)); 

     Assert.assertEquals(0, parentRepository.count()); 
     Assert.assertEquals(0, childRepository.count()); 

     parentRepository.save(parent); 

     Assert.assertEquals(1, parentRepository.count()); 
     Assert.assertEquals(2, childRepository.count()); 

     childRepository.delete(child1); 

     Assert.assertEquals(1, parentRepository.count()); 
     Assert.assertEquals(1, childRepository.count()); 
    } 
} 

Childが削除されることはありませんし、カウントはまだ2になりますが!私は多かれ少なかれ同じ問題について多くの質問を読んできましたが、答えは常に同じでした:

parent.getChildren().remove(child1); 
parentRepository.save(parent); 

それはできないのですか?私の親に数千人の子供がいたら、データベースからすべてを削除して削除する必要がありますか?エンティティが削除されていない場合、それらのすべての中で最も面倒なことは、なぜ地獄には何も投げられないのですか?それから、それを行う正しい方法は何ですか?親のリストからリストを削除し、常に子を手動で呼び出して、外部キーがないようにします。私は今朝食からこれを解決しようとしています。私はサークル内を移動しています。

編集:追加Hibernateのログ:

Hibernate: select count(*) as col_0_0_ from parent parent0_ 
Hibernate: select count(*) as col_0_0_ from child child0_ 
Hibernate: insert into parent (id) values (default) 
Hibernate: insert into child (id, parent_id) values (default, ?) 
Hibernate: insert into child (id, parent_id) values (default, ?) 
Hibernate: select count(*) as col_0_0_ from parent parent0_ 
Hibernate: select count(*) as col_0_0_ from child child0_ 
Hibernate: select count(*) as col_0_0_ from parent parent0_ 
Hibernate: select count(*) as col_0_0_ from child child0_ 
+1

問題は、1つのトランザクションで実行していることです。トランザクションを終了し、削除が有効であることをDBで確認します。 – ByeBye

+0

@ByeBye nopeはすぐにテストしました。追加されたhibernateログからわかるように、delete istは決して解雇されませんでした。 – daputzy

+0

あなたのchild1エンティティはこれと新しく作成された接続がないためです。 'childRepository.delete(child1)'の瞬間にはただの空のエンティティです。 – ByeBye

答えて

0

子が切り離され、そのインスタンス(永続オブジェクトではなく)、あなたがデバッグする場合、それはそのIDを持っていないはずです。

私の質問は、なぜそれを削除するために新しいオブジェクトを作成したのですか?あなたがそれを永続化する前に削除される子を決定することができたら、それを追加(Arrays.asList(child1, child2))から除外しないのはなぜですか?

またはそれが永続化した後にしか判断できない場合は、その子の永続インスタンスを取得する方法があることを意味します。この種の問題を解決することなくこのオブジェクトを削除できます。

関連する問題