双方向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つのトランザクションで実行していることです。トランザクションを終了し、削除が有効であることをDBで確認します。 – ByeBye
@ByeBye nopeはすぐにテストしました。追加されたhibernateログからわかるように、delete istは決して解雇されませんでした。 – daputzy
あなたのchild1エンティティはこれと新しく作成された接続がないためです。 'childRepository.delete(child1)'の瞬間にはただの空のエンティティです。 – ByeBye