학습하고 있는 내용이므로 오류가 있을 수 있습니다.
JPA 를 사용하면 쿼리문을 더 쉽고 간단하게 날릴 수 있다.
기본적인 CRUD 부분만 보자.
우선 JPA 를 사용하여 Repository의 쿼리문을 사용하려면 Repository 인터페이스에서 JpaRepository를 상속받아야 한다.
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByName(String name);
}
@Service
public class UserServiceV2 {
private final UserRepository userRepository;
public UserServiceV2(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 아래 있는 함수가 시작될 때 start transaction; 을 해준다.(트랜잭션을 시작)
// 함수가 예외 없이 잘 끝났다면 commit
// 혹시라도 문제가 있다면 rollback 해준다.
@Transactional
public void saveUser(UserCreateRequest request) {
User u = userRepository.save(new User(request.getName(), request.getAge()));
}
@Transactional(readOnly = true)
public List<UserResponse> getUsers() {
return userRepository.findAll().stream()
.map(user -> new UserResponse(user.getId(), user.getName(), user.getAge()))
.collect(Collectors.toList());
}
@Transactional
public void updateUser(UserUpdateRequest request) {
// select * form user where id = ?;
// Optional<User> 로 리턴된다.
User user = userRepository.findById(request.getId())
.orElseThrow(IllegalArgumentException::new);
user.updateName(request.getName());
// userRepository.save(user);
}
@Transactional
public void deleteUser(String name) {
// SELECT * FROM user WHERE name = ?
User user = userRepository.findByName(name)
.orElseThrow(IllegalArgumentException::new);
userRepository.delete(user);
}
}
우선 트랙잭션은 "모든 라인이 오류 없이 끝나면 commit 하는 기능" 을 말한다. 만약 메서드 내의 중간에서 오류가 발생한다면 트랜잭션으로 감싸져 있는 모든 라인이 commit 되지 않는다. 이러한 기능을 @Transactional 이란 어노테이션을 붙임으로써 사용한다.
이렇게 트랜잭션이 사용되면 "영속성 컨텍스트"도 사용된다.
영속성 컨텍스트는 세가지의 특징을 가진다.
변경 감지 --> 컨텍스트 안에서 불러오게 된 엔티티는 명시적으로 save 하지 않아도 자동으로 저장된다. 따라서 위의 UpdateUser 부분에서 userRepository.save 부분을 주석처리하여도 가능한 것이다. 이미 불러온 엔티티의 변경이 감지 되었기 때문.
쓰기 지연 --> 트랜잭션 내의 모든 라인을 실행한 뒤 마지막에 commit 시킬 때 한 번만 쿼리를 날린다. 계속 쿼리를 모든 라인에서 날리는 것보다 효율적이기 때문.
1차 캐싱 --> 트랜잭션 안에서 같은 데이터가 두 번 이상 불러오거나 실행되도록 하면 처음에 불렸을 떄 정보를 저장했다가 보여준다. 효율성을 위해.
ex) findByName 에서
find -> 한개의 값만 찾는다.
By -> 뒤에 있는 값을 기준으로 where 문을 실행한다.
따라서 SELECT * FROM user WHERE name = ?