[dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: eci.server.ItemModule.entity.item.Item.materials; nested exception is org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: eci.server.ItemModule.entity.item.Item.materials] with root cause
문제 발생 코드
/**
* postupdaterequest 받아서 update 수행
*
* @param req
* @return 새로 수정된 이미지
*/
public FileUpdatedResult update(
ItemUpdateRequest req,
ColorRepository colorRepository,
MemberRepository memberRepository,
MaterialRepository materialRepository,
ManufactureRepository manufactureRepository
) {
AtomicInteger k = new AtomicInteger();
//TODO update할 때 사용자가 기존 값 없애고 보낼 수도 있자나 => fix needed
//isBlank 랑 isNull로 판단해서 기존 값 / req 값 채워넣기
this.name = req.getName();
this.type = req.getType();
this.width = req.getWidth();
this.height = req.getHeight();
this.weight = req.getWeight();
this.color = req.getColorId()==null?null:colorRepository.findById(Long.valueOf(req.getColorId()))
.orElseThrow(ColorNotFoundException::new);
this.materials = req.getMaterials()==null?null:
req.getMaterials().stream().map(
i ->
materialRepository.
findById(i).orElseThrow(MaterialNotFoundException::new)
).collect(
toList()
)
.stream().map(
r -> new ItemMaterial(
this, r)
)
.collect(toList());
////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~이 부분에서 에러 발생!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
this.manufactures =
req.getManufactures().stream().map(
i ->
manufactureRepository.
findById(i).orElseThrow(ManufactureNotFoundException::new)
).collect(
toList()
).stream().map(
//다대다 관계를 만드는 구간
r -> new ItemManufacture(
this, r, req.getPartnumbers().
get(k.getAndIncrement())
)
)
.collect(toList());
ImageUpdatedResult resultImage =
findImageUpdatedResult(
req.getAddedImages(),
req.getDeletedImages()
);
addImages(resultImage.getAddedImages());
deleteImages(resultImage.getDeletedImages());
AttachmentUpdatedResult resultAttachment =
findAttachmentUpdatedResult(
req.getAddedAttachments(),
req.getDeletedAttachments()
);
addUpdatedAttachments(req, resultAttachment.getAddedAttachments());
deleteAttachments(resultAttachment.getDeletedAttachments());
FileUpdatedResult fileUpdatedResult = new FileUpdatedResult(resultAttachment,resultImage);
this.modifier =
memberRepository.findById(
req.getModifierId()
).orElseThrow(MemberNotFoundException::new);//05 -22 생성자 추가
return fileUpdatedResult;
}
////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~이 부분에서 에러 발생!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
this.materials = req.getMaterials()==null?null:
req.getMaterials().stream().map(
i ->
materialRepository.
findById(i).orElseThrow(MaterialNotFoundException::new)
).collect(
toList()
)
.stream().map(
r -> new ItemMaterial(
this, r)
)
.collect(toList());
////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~이 부분에서 에러 발생!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
this.manufactures =
req.getManufactures().stream().map(
i ->
manufactureRepository.
findById(i).orElseThrow(ManufactureNotFoundException::new)
).collect(
toList()
).stream().map(
//다대다 관계를 만드는 구간
r -> new ItemManufacture(
this, r, req.getPartnumbers().
get(k.getAndIncrement())
)
)
.collect(toList());
if (req.getMaterials().size()>0) {
this.materials.clear();
this.materials.addAll(
req.getMaterials().stream().map(
i ->
materialRepository.
findById(i).orElseThrow(MaterialNotFoundException::new)
).collect(
toList()
)
.stream().map(
r -> new ItemMaterial(
this, r)
)
.collect(toList())
);
}
if(req.getManufactures().size()>0){
this.manufactures.clear();
this.manufactures.addAll(
req.getManufactures().stream().map(
i ->
manufactureRepository.
findById(i).orElseThrow(ManufactureNotFoundException::new)
).collect(
toList()
).stream().map(
//다대다 관계를 만드는 구간
r -> new ItemManufacture(
this, r, req.getPartnumbers().
get(k.getAndIncrement())
)
)
.collect(toList())
);
}
1) https://blog.leocat.kr/notes/2016/04/26/hibernate-no-longer-referencece
list를 바꾸고 싶으면 새 list를 만들어서 set하지 말고, 내용(content)을 지우고 새로 넣자.
holder.getNames().clear();
holder.getNames().addAll(names);
writer : Manu
The method:
public void setChildren(Set<SonEntity> aSet) {
this.sonEntities = aSet;
}
works if the parentEntity is detached and again if we update it.
But if the entity is not detached from per context, (i.e. find and update operations are in the same transaction) the below method works.
public void setChildren(Set<SonEntity> aSet) {
//this.sonEntities = aSet; //This will override the set that Hibernate is tracking.
this.sonEntities.clear();
if (aSet != null) {
this.sonEntities.addAll(aSet);
}
}