Jatinder
Jatinder

Reputation: 84

Why does JPA Repository save method does not update entity details on production?

I am using spring data JPA I am trying to update the entity using the JPARepository method save() to update the entity details. Code I have written to update the entity works fine in development as expected. But the same code does not work on the production server it does not give any error only the code written inside the map() does not work. Below is my code

public Long updateQrCodeUrlByBusinessDetails(Long businessId, String menuUrl, MENU_TYPE menuType) {
        return qrCodeRepo.findByBusinessId(businessId).businessQrCode.stream().map(qr -> {
            qr.setMenuUrl(menuUrl);
            qr.setMenuType(menuType);
            return qrCodeRepo.save(qr);
        }).count();

    }

Upvotes: 1

Views: 2823

Answers (3)

Jatinder
Jatinder

Reputation: 84

After making some changes in code it work as expected on development and production. I just change the object value in the map() and return after that collect the object to list using the Collectors.toList() method and again use forEach() loop and update the entity data. Now code works as expected.

1st option:

public void updateQrCodeUrlByBusinessDetails(Long businessId, String menuUrl, MENU_TYPE menuType) {
        List<BusinessQRCode> businessQrCode = qrCodeRepo.findByBusinessId(businessId);
        businessQrCode.stream().map(qr -> {
            qr.setMenuUrl(menuUrl);
            qr.setMenuType(menuType);
            return qr;
        }).collect(Collectors.toList())
          .forEach(qr -> qrCodeRepo.save(qr));
}

2nd option: (good than 1st)

public void updateQrCodeUrlByBusinessDetails(Long businessId, String menuUrl, MENU_TYPE menuType) {
    List<BusinessQRCode> businessQrCode = qrCodeRepo.findByBusinessId(businessId).stream().map(qr -> {
        qr.setMenuUrl(menuUrl);
        qr.setMenuType(menuType);
        return qr;
    }).collect(Collectors.toList()); 
    qrCodeRepo.saveAll(businessQrCode);

}

Upvotes: 0

Kumar Ashutosh
Kumar Ashutosh

Reputation: 1244

just my two cents.

You should always return Optional from query results. You may have it as:

In repository:

Optional<List<BusinessQRCode>> findByBusinessId(Long businessId);

In Service:

public void updateQrCodeUrlByBusinessDetails(Long businessId, String menuUrl, MENU_TYPE menuType) {

// Fetch iterate, if exist
qrCodeRepo.findByBusinessId(businessId).ifPresent(qrCodes_ -> {

  qrCodes_.forEach(code_-> {
     qr.setMenuUrl(menuUrl);
     qr.setMenuType(menuType);
  });

  qrCodeRepo.saveAll(qrCodes_);

});

Why use map when you are returning same qr. You can skip that part and also the collect function. We already have the list of qrCodes, just iterate them and set the values then save all at once.

Upvotes: 2

luk2302
luk2302

Reputation: 57134

The problem is that count

may choose to not execute the stream pipeline (either sequentially or in parallel) if it is capable of computing the count directly from the stream source. In such cases no source elements will be traversed and no intermediate operations will be evaluated. Behavioral parameters with side-effects, which are strongly discouraged except for harmless cases such as debugging, may be affected

And exactly that happens in your case. The solution is to neither use map or count at all since you do not need / use them for what they are supposed to be used for and instead use a single forEach instead:

public void updateQrCodeUrlByBusinessDetails(Long businessId, String menuUrl, MENU_TYPE menuType) {
    List<BusinessQRCode> businessQrCode = qrCodeRepo.findByBusinessId(businessId);
    businessQrCode.stream().forEach(qr -> {
        qr.setMenuUrl(menuUrl);
        qr.setMenuType(menuType);
        qrCodeRepo.save(qr);
    });
}

Note that you could just do the exact same thing with a for loop with less calls, same amount of lines and without unnecessarily using streams:

public void updateQrCodeUrlByBusinessDetails(Long businessId, String menuUrl, MENU_TYPE menuType) {
    List<BusinessQRCode> businessQrCode = qrCodeRepo.findByBusinessId(businessId);
    for (BusinessQRCode qr : businessQrCode) {
        qr.setMenuUrl(menuUrl);
        qr.setMenuType(menuType);
        qrCodeRepo.save(qr);
    };
}

Upvotes: 6

Related Questions