Hibernate保存其他行而不是更新,并且需要保存两次

时间:2019-02-01 11:16:11

标签: java hibernate

注意:为简单起见,我更改了一些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) 其次,每次保存时,我都会在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,为什么懒惰不起作用?使用它时出错。

1 个答案:

答案 0 :(得分:0)

检查是否在ID中设置了Entity。 如果ID中有entity,并且该ID在数据库表中也存在,则休眠将更新该记录;但是,如果在实体对象中没有ID /存在ID, Hibernate始终将该对象视为新记录,并将新记录添加到表中,而不是更新。