このシナリオでは、ヘッダーレコードを取得し、その詳細を削除して別の方法で詳細を再作成する必要があります。詳細を更新することはあまりにも面倒です。削除すると、レコードが作成され、Springデータで重複するキー違反が発生するJPA
は、私は基本的に持っている:私はこれを実行し、2、3、20、などを渡すとき、
Header
=================================
ID, other columns...
Detail
=================================
ID, HEADER_ID, CUSTOMER_ID
Customer
=================================
ID, other columns...
Constraint: Details must be unique by HEADER_ID and CUSTOMER_ID so:
Detail (VALID)
=================================
1, 123, 10
2, 123, 12
Detail (IN-VALID)
=================================
1, 123, 10
1, 123, 10
OK:今
@Transactional
public void create(Integer id, List<Integer> customerIDs) {
Header header = headerService.findOne(id);
// header is found, has multiple details
// Remove the details
for(Detail detail : header.getDetails()) {
header.getDetails().remove(detail);
}
// Iterate through list of ID's and create Detail with other objects
for(Integer id : customerIDs) {
Customer customer = customerService.findOne(id);
Detail detail = new Detail();
detail.setCustomer(customer);
header.getDetails().add(detail);
}
headerService.save(header);
}
は、データベースは次のような制約があります顧客は、それ以前に存在しない限りすべての
Detail
レコードを作成します。
別の顧客リストを渡すと、最初にALL
の詳細が削除され、次にNEW
の詳細のリストが作成されると思います。
しかし、何が起こっているのは、削除が作成前に尊重されていないようです。エラーは重複するキー制約です。重複キーは上記の「有効」シナリオです。
データベースに手動で詳細情報を入力し、CREATE details
の部分をコメントアウトすると(削除のみを実行すると)、レコードは正常に削除されます。したがって、削除が機能します。作成は機能します。両方とも一緒に働かないことだけです。
私はより多くのコードを提供する必要があります。私はSpring Data JPA
を使用しています。
おかげ
UPDATE
私のエンティティは、基本的には次の注釈を付けています
@Entity
@Table
public class Header {
...
@OneToMany(mappedBy = "header", orphanRemoval = true, cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
private Set<Detail> Details = new HashSet<>();
...
}
@Entity
@Table
public class Detail {
...
@ManyToOne(optional = false)
@JoinColumn(name = "HEADER_ID", referencedColumnName = "ID", nullable = false)
private Header header;
...
}
UPDATE 2
@Klaus Groenbaek
実際、私はこれをもともと言及していませんでしたが、私はそのように初めて行いました。また、私はPERSISTを含むと仮定しているCascading.ALLを使用しています。私はすぐに作成していない場合は、削除が動作することを....私は改めてたい...再び
@Transactional
public void create(Integer id, List<Integer> customerIDs) {
Header header = headerService.findOne(id);
// Remove the details
detailRepository.delete(header.getDetails()); // Does not work
// I've also tried this:
for(Detail detail : header.getDetails()) {
detailRepository.delete(detail);
}
// Iterate through list of ID's and create Detail with other objects
for(Integer id : customerIDs) {
Customer customer = customerService.findOne(id);
Detail detail = new Detail();
detail.setCustomer(customer);
detail.setHeader(header);
detailRepository.save(detail)
}
}
:
ちょうどテストのために、私は次のように私のコードを更新しましたその後。その直前に削除がない場合、作成は動作します。しかし、データベースから重複したキー制約エラーのために一緒になっていても、どちらも機能しません。
カスケード削除の場合と同じシナリオを試しましたが、
どのように詳細をマッピングしたかによって異なります...単に「.remove(...)」と指定すると、DB内の行が常に削除されるわけではありません – Andremoniy
したがって、エンティティにアノテーションを付ける必要があります – Andremoniy
なぜ、近い票を得ていますか?とにかく... @Andremoniyはい、私はすべてカスケードで私のエンティティに注釈を付けました。私はその情報で質問を更新します。 – cbmeeks