Service 계층
: Controller와 교류하기 위해 Repository에서 값을 불러옴
@Service
: 서비스 계층임을 명시
@Transactional
: 항상 트랜잭션 안에서 데이터를 변경해야함. readOnly 디폴트값 = false
@RequiredArgsConstructor
: 생성자 주입방식
구현 필드 :
private final 특정Repository repository : @Autowired를 사용해도 되지만, 생성자 어노테이션으로 자동 주입.
구현 메소드 :
- join(Member member) : 레포지토리에 저장
- findMembers() : 전체 멤버 get
- findOne(Long memberId) : 하나의 멤버 get by id
- validateDuplicateMember(Member member) : 중복 검사 예외처리
@Service
@Transactional(readOnly = true)//항상 트랜잭션 안에서 데이터 변경해야함!!!
@RequiredArgsConstructor//생성자주입 방식.
public class MemberService {
/**
* 회원 가입
*/
//@Autowired//없어도 요즘은 스프링이 자동으로 생성자로 주입
private final MemberRepository memberRepository;//final 필수!!
//회원가입
@Transactional//readOnly=false 디폴트값.
public Long join(Member member){
validateDuplicateMember(member);//멤버 중복잇는지 확인하는 메소드
memberRepository.save(member);
return member.getId();
}
//중복멤버확인
private void validateDuplicateMember(Member member) {
List<Member> findMembers = memberRepository.findByName(member.getName());
if(!findMembers.isEmpty()){
throw new IllegalStateException("이미 존재하는 회원입니다.");
}
}
//회원조회
public List<Member> findMembers(){
return memberRepository.findAll();
}
public Member findOne(Long memberId){
return memberRepository.findOne(memberId);
}
}
ItemService & OrderService
ItemService.java
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ItemService {
private final ItemRepository itemRepository;
@Transactional
public void saveItem(Item item){
itemRepository.save(item);
}
public List<Item> findItems(){
return itemRepository.findAll();
}
public Item findOne(Long itemId){
return itemRepository.findOne(itemId);
}
}
saveItem(Item item), findItems(), findOne(Long itemId)
위 메소드들은 ItemRepository에 있는 것들을 그대로 가져오는것에 불과한 메소드이다.
OrderService.java
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class OrderService {
private final OrderRepository orderRepository;
private final MemberRepository memberRepository;//회원 id 넘어와야함
private final ItemRepository itemRepository;//상품 id 넘어와야함
/**
* 주문
*/
@Transactional
public Long order(Long memberId, Long itemId, int count){
//엔티티조회
Member member = memberRepository.findOne(memberId);
Item item = itemRepository.findOne(itemId);
//배송정보 생성
Delivery delivery = new Delivery();
delivery.setAddress(member.getAddress());//회원 배송지주소
//주문상품 생성
OrderItem orderItem = OrderItem.createOrderItem(item, item.getPrice(), count);
//주문 생성
Order order = Order.createOrder(member, delivery, orderItem);
//주문 저장
orderRepository.save(order);//cascade옵션때문에 자동으로 delivery와 orderItems가 자동으로 저장됨.
return order.getId();
}
/**
* 주문 취소
*/
@Transactional
public void cancelOrder(Long orderId){
//주문 엔티티조회
Order order = orderRepository.findOne(orderId);
//주문취소
order.cancel();
}
//검색
/*
public List<Order> findOrders(OrderSearch orderSearch){
return orderRepository.findAll(orderSearch);
}
*/
}
이 부분이 조금 복잡하다.
주문을 생성하려면 OrderRepository를 가져오고,
order(Long memberId, Long itemId, int count) 메소드 :
Member의 Id와 Item의 Id를 가져와서 주문을 해야한다.
-> 배송(Delivery) 생성 : 회원id 넣어줌
-> 주문상품(OrderItem) 생성 => 주문(Order)에 넣어주어 생성
-> OrderRepository 저장
cancelOrder(Long orderId) 메소드 :
orderRepository에서 취소할 주문(order)를 가져와서 order객체의 cancel()메소드를 실행(수량 감소).
Repository 계층
@Repository
: 레포지토리 계층임을 명시
@RequiredArgsConstructor
: EntityManager(영속성 컨텍스트)에 생성자 주입(자동 주입 - @PersistenceContext, @Autowired 없어도됨)
구현 필드 :
private final EntityManager em : 영속성(영구히 데이터 저장) 관리
구현 메소드 :
- save(Member member) : 영속성 컨텍스트에 저장
- findOne(Long id) : 하나의 멤버 get by id
- findAll() : 전체 멤버 get
- findByName(String name) : 멤버 이름으로 찾기
@Repository
@RequiredArgsConstructor
public class MemberRepository {
//@PersistenceContext//jpa에서 영속성 컨텍스트에 주입시켜주고 관리.
//@Autowired//spring boot 면 이걸로 대체가능 + RequiredArgs생성자로 대체.
private final EntityManager em;//final 필수
public void save(Member member){//저장
em.persist(member);
}
public Member findOne(Long id){//단건 조회
return em.find(Member.class, id);//(타입,PK)
}
public List<Member> findAll(){//전체 조회 :JPQL 사용('엔티티'를 조회)
return em.createQuery("select m from Member m", Member.class)
.getResultList();
}
public List<Member> findByName(String name){
return em.createQuery("select m from Member m where m.name = :name", Member.class)
.setParameter("name", name)
.getResultList();
}
}
ItemRepository & OrderRepository
ItemRepository.java
@Repository
@RequiredArgsConstructor
public class ItemRepository {
private final EntityManager em;
public void save(Item item) {
if (item.getId() == null) {//jpa저장 전까지 id값이 없음.
em.persist(item);//그러므로 저장하는거임
} else {//이미 db에 등록되어있으면
em.merge(item);//합쳐
}
}
public Item findOne(Long id) {
return em.find(Item.class, id);
}
public List<Item> findAll(){
return em.createQuery("select i from Item i", Item.class)
.getResultList();
}
}
OrderRepository.java
@Repository
@RequiredArgsConstructor
public class OrderRepository {
private EntityManager em;
public void save(Order order){
em.persist(order);
}
public Order findOne(Long id){
return em.find(Order.class, id);
}
// public List<Order> findAll(OrderSearch orderSearch){}
}
'Spring > SpringBoot' 카테고리의 다른 글
SpringBoot Swagger 에러 : Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException (0) | 2022.05.01 |
---|---|
#6 SpringBoot View- (ThymeLeaf, BootStrap 설정) (0) | 2022.04.10 |
#4 Spring JPA 지연로딩 + 주의사항 (0) | 2022.04.03 |
#3 엔티티 생성 + JPA관계형DB 설계 (0) | 2022.04.03 |
#2 application.yml vs properties, SpringBoot쿼리 파라미터 (0) | 2022.04.03 |