Hibernate сохраняет дополнительную строку вместо обновления и требует двух сохранений - PullRequest
0 голосов
/ 01 февраля 2019

Примечание: для простоты я изменил некоторые 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 выборку,почему ленивый не будет работать?При его использовании произошла ошибка.

1 Ответ

0 голосов
/ 01 февраля 2019

Проверьте, устанавливаете ли вы ID в этом Entity или нет.Если ID присутствует / установлен в entity и этот ID также присутствует в таблице БД, то hibernate обновит эту запись , но если ID не присутствует / не установлен в объекте Entity, Hibernate всегда обрабатывает этообъект как новая запись и добавить новую запись в таблицу вместо обновления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...