Примечание: для простоты я изменил некоторые variables
имена и избавился от ненужного кода, чтобы показать мою проблему.
У меня есть два хранилища:
@Repository
public interface CFolderRepository extends CrudRepository<CFolder, Long>, QuerydslPredicateExecutor<CFolder> {}
@Repository
public interface CRepository extends JpaRepository<C, Long>, CFinder, QuerydslPredicateExecutor<C> {}
Класс C
is:
@FilterDef(name = "INS_COMPANY_FILTER", parameters = {@ParamDef(name = "insCompanies", type = "string")})
@Filter(name = "INS_COMPANY_FILTER", condition = " INS_COMPANY in (:insCompanies) ")
@NoArgsConstructor
@AllArgsConstructor
@Audited
@AuditOverrides({@AuditOverride(forClass = EntityLog.class),
@AuditOverride(forClass = MultitenantEntityBase.class)})
@Entity
@Table(name = "INS_C")
@Getter
public class C extends MultitenantEntityBase {
@OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "C_FOLDER_ID")
private CFolder cFolder;
public void addFolder(List<String> clsUrl){
this.cFolder = CFolder.createFolder(clsUrl);
}
}
CFolder
is:
@Getter
@NoArgsConstructor
@Audited
@AuditOverride(forClass = EntityLog.class)
@Entity
@Table(name = "C_FOLDER")
@AllArgsConstructor
public class CFolder extends EntityBase {
@Column(name = "CREATION_FOLDER_DATE_TIME", nullable = false)
private LocalDateTime creationFolderDateTime;
@Column(name = "UPDATED_FOLDER_DATE_TIME")
private LocalDateTime updatedFolderDateTime;
@Column(name = "FOLDER_CREATED_BY", nullable = false)
private String folderCreatedBy;
@Column(name = "FOLDER_UPDATED_BY")
private String folderUpdatedBy;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "cFolder", fetch = FetchType.EAGER)
@NotAudited
private Set<FolderDocument> folderDocuments = new HashSet<>();
public static CFolder createFolder(List<String> clsUrl){
CFolder cFolder = new CFolder(LocalDateTime.now(), null, SecurityHelper.getUsernameOfAuthenticatedUser(), null, new HashSet<>());
createFolderDocuments(clsUrl, cFolder);
return cFolder;
}
public void updateFolder(List<String> clsUrl){
this.updatedFolderDateTime = LocalDateTime.now();
this.folderUpdatedBy = SecurityHelper.getUsernameOfAuthenticatedUser();
this.folderDocuments.clear();
createFolderDocuments(clsUrl, this);
}
private static void createFolderDocuments(List<String> clsUrl, CFolder cFolder) {
int documentNumber = 0;
for (String url : clsUrl) {
documentNumber++;
cFolder.folderDocuments.add(new FolderDocument(cFolder, documentNumber, url));
}
}
}
FolderDocument
is:
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Audited
@AuditOverride(forClass = EntityLog.class)
@Entity
@Table(name = "FOLDER_DOCUMENT")
public class FolderDocument extends EntityBase {
@ManyToOne
@JoinColumn(name = "C_FOLDER_ID", nullable = false)
private CFolder cFolder;
@Column(name = "DOCUMENT_NUMBER", nullable = false)
private int documentNumber;
@Column(name = "URL", nullable = false)
private String url;
}
И, наконец, у нас есть service
, в которомЯ использую эти entities
и пытаюсь сохранить / загрузить их в / из базы данных:
@Service
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class CFolderService {
private final CRepository cRepository;
private final CommunicationClServiceClient communicationServiceClient;
private final CFolderRepository cFolderRepository;
public List<ClDocumentDto> getClCaseFolder(Long cId) {
C insCase = cRepository.findCById(cId);
List<ClDocumentDto> clDocumentsDto = getClDocuments(insCase.getCNumber()); // here, the object has one cFolder, but many FolderDocument inside of it
return clDocumentsDto;
}
@Transactional
public void updateCFolder(Long cId) {
C insC = cRepository.findCById(cId);
List<ClDocumentDto> clDocumentsDto = getClDocuments(insC.getCNumber());
List<String> clsUrl = clDocumentsDto.stream().filter(c -> "ACTIVE".equals(c.getCommunicationStatus())).map(ClDocumentDto::getUrl).collect(Collectors.toList());
if (Objects.isNull(insC.getCFolder())) {
insC.addFolder(clsUrl);
} else {
insC.getCFolder().updateFolder(clsUrl);
}
cFolderRepository.save(insC.getCFolder()); // here it saves additional FolderDocument instead of updateing it
cRepository.save(insC); // need second save, so can get these collection in getClaimCaseFolder successfully
}
}
У меня есть две проблемы внутри.В примере я пытался очистить объекты, найденные в базе данных, и создать новые.
1) Во-первых, мне нужно выполнить две операции save
, чтобы успешно восстановить объект в методе getClCaseFolder
(за пределами транзакции).
2) Во-вторых, каждый раз, когда я сохраняю, я получаю дополнительный FolderDocument
объект, прикрепленный к CFolder
объекту внутри C
объекта.Я хочу очистить эту коллекцию и сохранить новую.
Я не уверен, почему hibernate
не обновляет этот объект?
РЕДАКТИРОВАТЬ:
Я думаю, что я делаю что-то вроде: cRepository.save(insC);
вместо this.folderDocuments.clear();
Я могу сделать:
for(Iterator<FolderDocument> featureIterator = this.folderDocuments.iterator();
featureIterator.hasNext(); ) {
FolderDocument feature = featureIterator .next();
feature.setCFolder(null);
featureIterator.remove();
}
Но я получаю eager
выборку,почему ленивый не будет работать?При его использовании произошла ошибка.