[Java Spring] 6. 상품 등록/주문/수정/조회

Hayoon·2022년 7월 17일
0

Spring으로 Thymeleaf를 통해 front까지 구현하는 개발을 하니 MVC패턴에서 계속 난관에 부딪힌다.

SQL에서 포함되는 글자를 찾아주는 "LIKE"

관계형 데이터베이스(RDMBS)에서 특정 문자열이 있는지 검색하고 싶을 때 사용하는 문법이다.

return em.createQuery("select o from Order o join o.member m" +
                        " where o.status = :status" +
                        " and m.name like :name", Order.class)
       .setParameter("status", orderSearch.getOrderStatus())
       .setParameter("name", orderSearch.getMemberName())

MySQL or MariaDB의 Query구문이다. 조건절에 LIKE를 붙이고 앞뒤로 %를 붙여 중간에 name이라는 글자가 포함된 모든 컬럼을 가져오게 된다. JPA가 지원하는 JPQL문으로 변형된 것 같다.

.setParameter 연속 작성 가능
-> JPQL API가 메소드 체인 방식으로 설계되어 있다.

이름 기준 파라미터(Named Parameters)
파라미터를 이름으로 구분
파라미터 앞에 : 사용 ex) :username

Static Method

정적 메소드는 클래스가 메모리에 올라갈 때 정적 메소드가 자동적으로 생성된다. 그렇기에 정적 메소드는 인스턴스를 생성하지 않아도 호출을 할 수 있다. 정적 메소드는 유틸리티 함수를 만드는데 유용하게 사용된다.

@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Book extends Item {
    private String author;
    private String isbn;

    public static Book createBook(String author, String isbn, String name, int price, int stockQuantity) {
        Book book = new Book();
        book.setName(name);
        book.setPrice(price);
        book.setIsbn(isbn);
        book.setAuthor(author);
        book.setStockQuantity(stockQuantity);
        return book;
    }
}

@Setter(lombok)을 이용하여 도메인 값을 변경할 경우 DB에러가 발생한다고 한다. 따라서, PROTECTED 접근제한자로 정적 생성 메서드를 만들어 값을 수정하는데 제한을 건다.

@RequestMapping, @PostMapping, @GetMapping

3개의 Annotation 모두 Http Methods 방식이다.
@RequestMapping은 method를 생략하면 GET 방식과 POST 방식을 모두 처리해준다.
@RequestMapping는 @RequestMapping("경로")로 적어줄 수 있다.
결국 @GetMapping과 @PostMapping을 사용하는 이유는 @RequestMapping에 굳이 method를 명시하는 이유와 같다고 볼 수 있다.

굳이 method를 명시하는 것이고 그 연장선에서 @GetMapping과 @PostMapping이라는 어노테이션이 추가된 이유는 다음과 같다.
만약 @RequestMapping("/exam/code")으로 GET 방식의 요청을 받았다면 POST 방식의 요청은 다른 url을 써야한다. 이렇게 되면 보기에도 코드를 관리하기에도 좋지 못하다.
따라서 GET Method 방식은 @GetMapping, POST Method 방식은 @PostMapping으로 구분지은 것이다.

변경 감지와 병합(merge)

영속성 컨텍스트가 더는 관리하지 않는 엔티티를 준영속 엔티티라고 하는데, 이를 수정하는 방법은 2가지이다.

1. 변경 감지 사용

@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
	Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한다.
	findItem.setPrice(itemParam.getPrice()); //데이터를 수정한다. 
}

영속성 컨텍스트에서 엔티티를 다시 조회한 후에 데이터를 수정하는 방법.
트랜잭션 안에서 엔티티를 다시 조회, 변경할 값 선택 트랜잭션 커밋 시점에 변경 감지(Dirty Checking)이 동작해서 데이터베이스에 UPDATE SQL 실행.

2. 병합 사용

@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티 
	Item mergeItem = em.merge(item);
}

병합이 사용하기에 좀 더 간단하게 보이므로 간단한 도메인에 적용하기에 적합하다. 하지만, 변경 감지 기능을 사용하면 원하는 속성만 선택해서 변경할 수 있지만, 병합을 사용하면 모든 속성이 변경된다. 병합시 값이 없으면 null 로 업데이트 할 위험도 있다. (병합은 모든 필드를 교체한다.)
** @Transactional 안에서 수정(조회)해야 영속성 상태로 값을 수정할 수 있다.

트랜잭션이 있는 서비스 계층에 식별자( id )와 변경할 데이터를 명확하게 전달(파라미터 or dto). Transacntion있는 서비스 계층에서 영속 상태의 엔티티를 조회하고, 엔티티의 데이터를 직접 변경.
트랜잭션 커밋 시점에 변경 감지가 실행됩니다. 라고 강조하셨다.

출처:
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1/dashboard

profile
Junior Developer

0개의 댓글