0

I have an entity class in Hibernate JPA spring boot app using lombok. While analysing the code , I could not find any save() code. Does the setter automatically generates the Hibernate queries and saves them to DB.

@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString(callSuper = true)
@Entity
@Table(name = "operation", schema = "ssp")
public class Operation extends CommonEntity{
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ToString.Exclude
    @ManyToOne
    @JoinColumn(name = "router_ref_id")
    private Router router;

    @ToString.Exclude
    @OneToMany(mappedBy = "operation", cascade = CascadeType.ALL)
    @OrderBy("sequence")
    private List<OperationQr> qrList;

    @ToString.Exclude
    @OneToMany(mappedBy = "operation", cascade = CascadeType.ALL)
    private Set<OperationDependency> operationDependencies;

    @ToString.Exclude
    @OneToMany(mappedBy = "operation", cascade = CascadeType.ALL)
    @OrderBy("sequence")
    private Set<OperationDocument> opnDocumentList;

    @ToString.Exclude
    @OneToOne
    @JoinColumn(name = "operation_interface")
    private OperationInterface operationInterface;

    @Column(name = "router_operation_id")
    private Integer routerOperationId;

    @Column(name = "tenant_id")
    private String tenantId;

    @Column(name = "external_system_sequence")
    private String externalSystemSequence;

The code which saves the Operation and its parts are :

private Operation saveDetails(OperationDetailsViewModel newOperationData, String sso, Router router, Operation operation) {
    copyProperties(newOperationData, operation);
    
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();

    Optional<XRefWorkcenterRequirementProfile> requirementProfile = workCenterService.getRequirementProfileFor( router, newOperationData.getWorkCenter().getId() );
    
    operation.setRequrementProfile(requirementProfile.isPresent() ? requirementProfile.get().getProfileId() : null);
    
    if (isOperationInterfaceChanged(operation.getOperationInterface(), newOperationData.getOperationInterface())) {
        OperationInterface newOperationInterface = operationInterfaceService.getOperationInterface(
                router.getEnterprise(), router.getBusinessUnit(), router.getPlant(), newOperationData.getOperationInterface().getId());
        operation.setOperationInterface(newOperationInterface);
    qualityResultService.removeOldQr(operation);
    List<OperationQr> qrList = qualityResultService.createQrList(sso, operation, newOperationData.getGlobalQr());
    qrList.addAll(qualityResultService.createQrList(sso, operation, newOperationData.getLocalQr()));
    operation.setQrList(qrList);

    Set<OperationDependency> operationDependencies = operationDependenciesService.createDependencies( sso, operation, newOperationData.getDependencies() );
    operationDependencySetValidator.validateDependencySet( operationDependencies );
    operationDependenciesService.removeOldDependencies( operation );
    operation.setOperationDependencies( operationDependencies );

    documentService.removeOldOperationDocuments(operation);
    operation.setOpnDocumentList(documentService.createDocuments(sso, operation, newOperationData.getDocuments()));

    purchaseDetailService.updatePurchaseDetail(sso, operation, newOperationData.getPurchaseDetails());
    addCustomFields( sso, operation, newOperationData ) ;

    OperationUtils.setEntityUpdateData( operation, sso );
    
    stopWatch.stop();
    LOGGER.info("..........SaveOperationDetails.......... Total time = " + stopWatch.getTotalTimeMillis() + " ms");

    return operation;
}

saveDetails() is wrapped in another method which is @Transactional

 @Transactional
    public Operation addOperation( OperationDetailsViewModel newOperationData, int indexToAdd, String sso, String changeRequestNumber ) {
        Router router = getEditableRouter( newOperationData.getRouterId(), sso, changeRequestNumber );
        Operation operation = prepareNewOperation(sso, router);
        OperationUtils.addOperationToIndexWithResequencing( router.getOperationsList(), operation, indexToAdd );
        return saveDetails(newOperationData, sso, router, operation);
    }




private Operation mergeOperation(OperationDetailsViewModel operationDetailsViewModel, int i, String sso,
    String changeRequestNumber, Router router, RouterLock routerLock) {
    Operation operation;

    if(operationDetailsViewModel.getId() == null) {
        operation = saveOperationDetailsService
            .addOperation(operationDetailsViewModel, i, sso, changeRequestNumber);
    }
    else {
        operation = saveOperationDetailsService
            .updateOperation(operationDetailsViewModel, sso, changeRequestNumber, router, routerLock);
    }

    return operation;
}




  public static void addOperationToIndexWithResequencing(List<Operation> operations,
      Operation newOperationWithoutSequence, int indexToAdd) {
    operations.sort(Comparator.comparing(Operation::getSequence));

    if (indexToAdd < operations.size()) {
      operations.add(indexToAdd, newOperationWithoutSequence);
    } else {
      operations.add(newOperationWithoutSequence);
    }

    resequenceOperations(operations);
  }
Mario Codes
  • 689
  • 8
  • 15
sromit
  • 900
  • 3
  • 16
  • 43
  • Do you mean save() method which is used to persist data in table? – wak786 Sep 29 '20 at 19:25
  • No - lombok does not generate any hibernate calls. Presumably, `saveDetails(...)` is wrapped in a transaction, and an update to the **existing entity** is handled by the transaction manager (not lombok). – Andrew S Sep 29 '20 at 19:26
  • yes..I cannot find any code related to that. – sromit Sep 29 '20 at 19:26
  • does @Transactional which is called by the addOperation() generates those queries? – sromit Sep 29 '20 at 19:31
  • does prepareNewOperation has any code which is loading Operation entity from the Repository ? – SKumar Sep 29 '20 at 19:36
  • @Transactional is to enable transaction management. If something fails during the transaction, db state is rolled back to a state as it was before the transaction started. – wak786 Sep 29 '20 at 19:37
  • prepareNewOperation() just contains some setters just like saveDetails()..nothing of OperationRepository.save() related – sromit Sep 29 '20 at 19:39
  • No, this line gives you Operation entity.`return saveDetails(newOperationData, sso, router, operation);` – wak786 Sep 29 '20 at 19:42
  • ok..fine..but after getting the entity where is the actual save happening..this entity is then thrown to relevant caller – sromit Sep 29 '20 at 19:47

2 Answers2

1

"Does the setter automatically generates the Hibernate queries and saves them to DB. - NO

Basically save() is present on CrudRepository. JpaRepository extends the CrudRepository. Hence it inherits all the methods from CrudRepository. Check the docs link.

https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html

https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html

wak786
  • 1,562
  • 1
  • 8
  • 12
1

If Operation entity is a managed entity (it is retrieved from some jpa repository, for example findOne etc), then explicit save or persist call is not needed. It gets automatically saved at the end of a transaction.

I believe, you must be having a repository call somewhere here -

Operation operation = prepareNewOperation(sso, router);
OperationUtils.addOperationToIndexWithResequencing( router.getOperationsList(), operation, indexToAdd );

Similar answer here - https://stackoverflow.com/a/46708295/11244881

SKumar
  • 1,940
  • 1
  • 7
  • 12
  • I gave both the codes..it still setter in those methods – sromit Sep 29 '20 at 19:55
  • But I agree with the point mentioned in that post..this opertaion is being pulled via findone() call and all the setters are done after that – sromit Sep 29 '20 at 20:00