fix: throw ResourceNotFoundException instead of returning null, replace full-table-scan list queries with JPQL

This commit is contained in:
2026-05-05 15:20:46 +02:00
parent 9c91da9f30
commit 68783cc892
6 changed files with 171 additions and 62 deletions
@@ -0,0 +1,11 @@
package de.zendric.app.xpensely_server.model.Exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
@@ -3,13 +3,24 @@ package de.zendric.app.xpensely_server.repo;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import de.zendric.app.xpensely_server.model.ExpenseList;
@Repository
public interface ExpenseListRepository extends JpaRepository<ExpenseList, Long> {
List<ExpenseList> findByOwnerId(Long ownerId);
ExpenseList findByInviteCode(String inviteCode);
}
@Query("SELECT el FROM ExpenseList el WHERE el.owner.id = :userId OR el.sharedWith.id = :sharedUserId")
List<ExpenseList> findByOwnerIdOrSharedWithId(@Param("userId") Long userId,
@Param("sharedUserId") Long sharedUserId);
@Query("SELECT el FROM ExpenseList el WHERE el.owner.username = :username OR el.sharedWith.username = :sharedUsername")
List<ExpenseList> findByOwnerUsernameOrSharedWithUsername(@Param("username") String username,
@Param("sharedUsername") String sharedUsername);
}
@@ -7,7 +7,6 @@ import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -18,20 +17,15 @@ import de.zendric.app.xpensely_server.model.XpenselyCustomCategory;
import de.zendric.app.xpensely_server.repo.ExpenseListRepository;
import de.zendric.app.xpensely_server.repo.ExpenseRepository;
import de.zendric.app.xpensely_server.repo.XpenselyCustomCategoryRepository;
import jakarta.persistence.EntityManager;
@Service
@Transactional
public class ExpenseListService {
private ExpenseListRepository repository;
private final ExpenseListRepository repository;
private final ExpenseRepository expenseRepository;
private XpenselyCustomCategoryRepository customCategoryRepository;
private final XpenselyCustomCategoryRepository customCategoryRepository;
@Autowired
private EntityManager entityManager;
@Autowired
public ExpenseListService(ExpenseListRepository repository, ExpenseRepository expenseRepository,
XpenselyCustomCategoryRepository customCategoryRepository) {
this.repository = repository;
@@ -68,38 +62,11 @@ public class ExpenseListService {
}
public List<ExpenseList> findByUserId(Long id) {
List<ExpenseList> allLists = repository.findAll();
List<ExpenseList> userSpecificList = new ArrayList<>();
for (ExpenseList expenseList : allLists) {
AppUser sharedWith = expenseList.getSharedWith();
if (expenseList.getOwner().getId().equals(id)) {
userSpecificList.add(expenseList);
} else {
if (sharedWith != null && sharedWith.getId().equals(id)) {
userSpecificList.add(expenseList);
}
}
}
return userSpecificList;
return repository.findByOwnerIdOrSharedWithId(id, id);
}
public List<ExpenseList> findByUsername(String username) {
List<ExpenseList> allLists = repository.findAll();
List<ExpenseList> userSpecificList = new ArrayList<>();
for (ExpenseList expenseList : allLists) {
AppUser sharedWith = expenseList.getSharedWith();
if (expenseList.getOwner().getUsername().equals(username)) {
userSpecificList.add(expenseList);
} else {
if (sharedWith != null && sharedWith.getUsername().equals(username)) {
userSpecificList.add(expenseList);
}
}
}
return userSpecificList;
return repository.findByOwnerUsernameOrSharedWithUsername(username, username);
}
public Expense addExpenseToList(Long expenseListId, Expense expense) {
@@ -1,11 +1,11 @@
package de.zendric.app.xpensely_server.services;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Service;
import de.zendric.app.xpensely_server.model.AppUser;
import de.zendric.app.xpensely_server.model.Exception.ResourceNotFoundException;
import de.zendric.app.xpensely_server.model.Exception.UsernameAlreadyExistsException;
import de.zendric.app.xpensely_server.repo.UserRepository;
@@ -29,36 +29,24 @@ public class UserService {
}
public AppUser getUser(Long id) {
Optional<AppUser> user = userRepository.findById(id);
if (user.isPresent()) {
return user.get();
} else
return null;
return userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id));
}
public AppUser deleteUserById(Long id) {
Optional<AppUser> user = userRepository.findById(id);
if (user.isPresent()) {
userRepository.deleteById(id);
return user.get();
} else
return null;
AppUser user = userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id));
userRepository.deleteById(id);
return user;
}
public AppUser getUserByName(String username) {
Optional<AppUser> optUser = userRepository.findByUsername(username);
if (optUser.isPresent()) {
return optUser.get();
} else
return null;
return userRepository.findByUsername(username)
.orElseThrow(() -> new ResourceNotFoundException("User not found: " + username));
}
public AppUser getUserByGoogleId(String id) {
Optional<AppUser> optUser = userRepository.findByGoogleId(id);
if (optUser.isPresent()) {
return optUser.get();
} else
return null;
return userRepository.findByGoogleId(id)
.orElseThrow(() -> new ResourceNotFoundException("User not found with Google ID: " + id));
}
}
}