Service란?
“비즈니스 로직을 담당하는 계층”
비즈니스 로직이란?
업무 규칙!
- "재고가 부족하면 주문 불가"는 DB 규칙이 아니라 비즈니스 규칙이다.
Service의 역할
- 비즈니스 로직 처리
- 트랜잭션 관리
- 여러 Repository에 접근
- 중복되는 비즈니스 로직 정리하여 재사용
프로젝트 구현
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class OrderService {
private final OrderRepository orderRepository;
private final ProductRepository productRepository;
@Transactional
public OrderResponse create(OrderRequest request) {
Product product = productRepository.findById(request.productId())
.orElseThrow(() -> new IllegalArgumentException("상품이 존재하지 않습니다."));
product.decreaseStock(request.quantity());
Order order = new Order(product, request.quantity());
Order savedOrder = orderRepository.save(order);
return OrderResponse.from(savedOrder);
}
public OrderResponse findById(Long id) {
Order order = orderRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("주문이 존재하지 않습니다."));
return OrderResponse.from(order);
}
public List<OrderResponse> findAll() {
return orderRepository.findAllWithProduct()
.stream()
.map(OrderResponse::from)
.toList();
}
}
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ProductService {
private final ProductRepository productRepository;
@Transactional
public ProductResponse create(ProductRequest request) {
Product product = new Product(
request.name(),
request.price(),
request.stock()
);
Product savedProduct = productRepository.save(product);
return ProductResponse.from(savedProduct);
}
public ProductResponse findById(Long id) {
Product product = productRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("상품이 존재하지 않습니다."));
return ProductResponse.from(product);
}
public List<ProductResponse> findAll() {
return productRepository.findAll()
.stream()
.map(ProductResponse::from)
.toList();
}
@Transactional
public ProductResponse update(Long id, ProductRequest request) {
Product product = productRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("상품이 존재하지 않습니다."));
product.update(
request.name(),
request.price(),
request.stock()
);
return ProductResponse.from(product);
}
@Transactional
public void delete(Long id) {
productRepository.deleteById(id);
}
}
코드 설명
@Transactional(readOnly = true)
해당 메서드에 트랜잭션 처리.
(readOnly = true)
- 조회 전용 트랜잭션.
- JPA는 영속성 관리, 지연 로딩, 캐시 사용 등의 이유로 조회에도 트랜잭션 안에서 실행함
참고 :
https://adjh54.tistory.com/378
[Java] @Transactional 어노테이션 상세 이해하기 : Checked, Unchecked Exception Rollback
해당 글에서는 @Transactional 어노테이션에 대해 상세한 이해를 돕기 위해 작성한 글입니다. 💡 [참고] 다양한 Annotation에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.구분링크Spring Web
adjh54.tistory.com
https://ssdragon.tistory.com/116
@Transactional은 조회만 할 때 있어야할까?
스프링 부트 프로젝트를 진행하면서 트랜잭션 어노테이션을 적지 않은곳에서 조회가 잘되고 있었다. 하지만 어느 곳에서는 읽기 전용 트랜잭션인 `@Transactional(readOnly = true)`를 적어 성능 최적화
ssdragon.tistory.com
[기술 면접] JPA 즉시 로딩과 지연 로딩의 차이
JPA에서는 데이터를 조회할 때 즉시 로딩(EAGER)과 지연 로딩(LAZY) 두 가지 방식이 있다. 이 두 가지 방식을 간단하게 설명하면 즉시 로딩은 데이터를 조회할 때 연관된 데이터까지 한 번에 불러오
velog.io
'Spring > - [시리즈] 간단한 CRUD 구현하기' 카테고리의 다른 글
| CRUD 구현 8 - Postman을 이용한 테스트 (0) | 2026.05.15 |
|---|---|
| CRUD 구현 7 - Controller 구현 (0) | 2026.05.15 |
| CRUD 구현 5 - DTO (Data Transfer Object) 구현 (0) | 2026.05.15 |
| CRUD 구현 4 - Repository 구현 (0) | 2026.05.14 |
| CRUD 구현 3 - Entity 구현 (0) | 2026.05.14 |