JPA findBy method always goes to orElseThrow

return specRepo.findByIdentificationType(idType)
                .orElseThrow(() -> new ResourceNotFoundException("...")));

Is the reason.

Java is quite eager in execution and always calls the orElse method to prepare just in case it would need it.

The order of your execution is somehow:

  1. specRepo.findByIdentificationType(idType)
  2. orElse cannot be executed as it's argument is not evaluated yet
  3. specRepo.findById(idType)
  4. .orElseThrow(() -> new ResourceNotFoundException("..."))
  5. The result of 3 and 4 becomes an object o
  6. orElse(o)

Instead of using orElse one should prefer orElseGet.

return specRepo.findByIdentificationType(idType)
            .orElseGet(() -> specRepo.findById(idType)
                .orElseThrow(() -> new ResourceNotFoundException("...")));

It will only be called when needed.

We have two scenarios here:

  1. specRepo returns an non-empty Optional.
  2. specRepo returns empty object.

In scenario 1, idType is a valid identificationType thus is not an id, so the findById will throw an exception. In scenario 2, idType is not a valid identificationType and if it is a legal id the method should result in exception being thrown.


While this answers diagnoses the problem and describes what is the reason of such behavior, @Abinash Ghosh answer provides the simplest and imo best solution of the problem.

In general, avoid using orElse. In this case, add the findByIdentificationTypeOrId(String it, String id) to your repository.

@xenteros is right that is the problem. You can use findByIdentificationTypeOrId to get data in one query

return specRepo.findByIdentifcationTypeOrId(idType, idType)
                .orElseThrow(() -> new ResourceNotFoundException("...")));

and repository like

public interface IdentificationSpecRepository extends CrudRepository<IdentificationMaster, String>{

    Optional<IdentificationMaster> findByIdentificationTypeOrId(String identificationType, String id);