注意:为了简化起见,我更改了一些variables
名称,并去掉了不必要的代码来显示我的问题。
我有两个存储库:
@Repository
public interface CFolderRepository extends CrudRepository<CFolder, Long>, QuerydslPredicateExecutor<CFolder> {}
@Repository
public interface CRepository extends JpaRepository<C, Long>, CFinder, QuerydslPredicateExecutor<C> {}
类别C
为:
@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
为:
@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
为:
@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)第二,每次我保存时,我都会在C
对象内将额外的FolderDocument
对象固定到CFolder
对象。我想清除此集合并保存新集合。
我不确定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
获取,为什么懒惰不工作?使用它时出错。
检查是否在该Entity
中设置ID
。如果entity
中存在/设置了ID
,并且该ID也存在于DB表中,则hibernate将更新该记录。但是,如果实体对象中不存在/设置ID,则hibernate始终将该对象视为新记录,并将新记录添加到表中,而不是更新。