Repository and service improvements I have a MongoRepository:
@Repository
public interface GooglePlayGameRepository extends MongoRepository&lt;GooglePlayGame, String&gt; {

    Optional&lt;GooglePlayGame&gt; findByTitle(String title);

    List&lt;GooglePlayGame&gt; findByTitleContainsIgnoreCase(String title);

    @Aggregation(&quot;{$sample: {size: ?0} }&quot;)
    List&lt;GooglePlayGame&gt; findRandomGames(Long number);

}

And service:
@Service
public class GooglePlayGameService {

    private final GooglePlayGameRepository googlePlayGameRepository;

    public GooglePlayGameService(GooglePlayGameRepository googlePlayGameRepository) {
        this.googlePlayGameRepository = googlePlayGameRepository;
    }

    public void saveToLibrary(GooglePlayGame googlePlayGame) {
        googlePlayGameRepository.save(googlePlayGame);
    }

    public GooglePlayGame getGameByTitle(String title) throws NoSuchGooglePlayGameFoundException {
        Optional&lt;GooglePlayGame&gt; googlePlayGame = googlePlayGameRepository.findByTitle(title);
        return googlePlayGame.orElseThrow(
                () -&gt; new NoSuchGooglePlayGameFoundException(&quot;Game was not found: &quot; + title)
        );
    }

    public List&lt;GooglePlayGame&gt; findByTitle(String title) {
        List&lt;GooglePlayGame&gt; googlePlayGames = googlePlayGameRepository.findByTitleContainsIgnoreCase(title);
        return googlePlayGames.isEmpty()
                ? Collections.emptyList()
                : googlePlayGames;
    }

    public Long getLibrarySize() {
        return googlePlayGameRepository.count();
    }

    public List&lt;GooglePlayGame&gt; getRandomGames(Long number) {
        return googlePlayGameRepository.findRandomGames(number);
    }

}


What do you think about methods getGameByTitle (returns exact match) and findByTitle (looking for similar matches by title)? Is it good practice to handle Optional in Service layer and just throws Exception? Or should I use Optional as a return type in Service layer too and handle it in other places which will use this service?
About findByTitle: is it necessary to use this construction?
googlePlayGames.isEmpty()
          ? Collections.emptyList()
          : googlePlayGames;

Maybe I should just check it in code like this (not in the service):
if (googlePlayGames.isEmpty()){
   log.error(&quot;Game {} doesn't exist in library&quot;, title);
}

I have another variant for these methods:
public GooglePlayGame getGameByTitle(String title) throws NoSuchGooglePlayGameFoundException {
    return findByTitle(title).stream()
             .findFirst()
             .orElseThrow(NoSuchGooglePlayGameFoundException::new);
 }

public List&lt;GooglePlayGame&gt; findByTitle(String title) {
     List&lt;GooglePlayGame&gt; games = googlePlayGameRepository.findByTitleContainsIgnoreCase(title);
     if (!games.isEmpty()) {
         return games;
     }
     return Collections.emptyList();
 }

Which one is better?
You don't need to make additional save method since save method already exist.

public void saveToLibrary(GooglePlayGame googlePlayGame) {
        googlePlayGameRepository.save(googlePlayGame);
    }


You have two methods one called findByTitle(String title) and findByTitleContainsIgnoreCase

To make other programmer understand whats going on maybe renaming findByTitleContainsIgnoreCase to findListOfGamesByTitlesince you are returning List and also it can be optional since games might not be there at all.
In your service call findListOfGamesByTitle just pass String (title.equalsIgnoreCase())

Why are you throwing exception at method level and also inside the body in getGameByTitle , do you want to pass that exception further ? there is no point doing it.

Yes, you should handle optional in the service layer because next layer is the constructor.


The sentence and the place you mentioned is not understood so please fix it a bit
i am referring to the following -&gt; Maybe I should just check it in code like this (not in the service):