springBoot_개념_Day_22
1.
페이징 처리하는 서비스를 보면 @Transactional 이 붙어있다. 이게 무엇일까?
간단하게 말하면, 트랜잭션은 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미한다. 하지만 문장만으로는 이해가 안된다. 이해를 위해 예시를 들자면, A사람이 B사람에게 5만원을 송금하는 과정에서 이 과정
을 위해
A 사람의 통장 : 5만원 출금
B 사람의 통장 : 5만원 입금
이 발생하게 된다. 근데 중간에 오류가 발생한다면?
A사람은 분명히 5만원이 출금되었는데, B사람의 통장에는 입금된게 없는 상황이 발생될 수 있다. 이처럼, 예상하지 못한 상황에서 오류가 발생하여 하여 데이터의 부정합이 발생하는 경우, 다시 원상복귀 해야 하는 상황에 대비 하기 위해 Transactional 을 사용한다. 비정상 처리되어 데이터의 부정합이 발생한다면 원래 상태로 원상 복귀하고, 정상적으로 프로그램이 진행되었다면 데이터에 최종적으로 적용하게 되어 데이터의 부정합을 방지할게 되는 것이다.
[출처사이트 : https://velog.io/@sweet_sumin/Transactional%EC%9D%84-%EC%93%B0%EB%8A%94-%EC%9D%B4%EC%9C%A0%EB%8A%94]
2.쿼리dSL
QueryDSL이란?
DSL는 Domain Specific Language의 약자로, 특정 영역에 특화된 언어를 의미한다. 그런 의미에서 QueryDSL은 쿼리생성에 특화된 프레임워크를 의미한다. 그럼 QueryDSL이 필요한 이유는 무엇일까?
JPA는 객체지향어플리케이션과 관계형DB 사이의 패러다임 불일치를 해결하는 프레임워크이다. 개발자는 객체지향 관점으로 개발하고 JPA프레임워크는 자동으로 SQL쿼리문을 생성한다. SQL문이 자동으로 생성되니 개발자는 SQL 관점 프로그래밍을 하지 않아도 된다. 그러나 완전한 분리는 불가능하다. 복잡한 쿼리 생성을 위해, JPA는 JPQL을 지원한다.
JPQL은 SQL문과 상당히 유사하다. 객체지향적 관점을 유지하고 있는 SQL문 정도로 보면된다.
그러나 여기에는 크게 두 가지 문제가 있다.
1) 타입안정성이 떨어진다.
#작성된 JPQL문
String jpql = "SELECT p.category, AVG(p.price) FROM Product p " +
"GROUP BY p.category " +
"HAVING AVG(p.price) > :averagePrice";
JPQL은 문자열이다.
문자열이기에 개발자는 JPQL문법이 틀려도 이를 알아차리지 못한다. 그래서 런타임 중에 메소드가 호출되어 JPQL이 파싱되어야 문법오류를 발견할 수 있다. @Query 어노테이션을 사용하면 프로그램이 올라가는 과정에 문법 오류를 발견 할수 있지만, 이것도 결국은 프로그램을 실행해야만 오류를 발견할 수 있다. 즉, JPQL을 파싱하는 프로세스가 동작해야만 문법오류를 발견할 수 있고 컴파일 과정에서는 어떤 오류도 발견할 수 없다. 한마디로 타입안정성이 떨어진다.
2) 직관적인 동적쿼리 작성이 어렵다.
JPQL은 문자열이다.
동적쿼리를 작성하려면 문자열을 조작하는 방식으로 로직을 구성해야 한다. 그러다보니 문자열과 문자열 사이에 if-else문이나 for문 같은 코드가 들어가 가독성을 떨어트린다.
String jpqlQuery = "select m from Member m";
if(id != null){ //id가 NULL이 아니면
jpql += "where id = :id"; // WHERE 조건문 추가
}
TypedQuery<Member> query = em.createQuery(jpqlQuery, Member.class);
if(id != null){ //id가 NULL이 아니면
query = query.setParameter("id", id); // 파라미터 추가
}
이외에도, JPA는 동적쿼리 작성을 위한 JPA 표준기술인 Criteria도 제공하지만 전혀 직관적이지 못하다. QueryDSL은 JPA가 지원하는 표준기술은 아니지만 타입안정성을 보장하고 직관적인 동적쿼리 작성이 가능하다. 이런 이유로 실무에서 JPA와 연계되어, 가장 많이 사용되는 프레임워크 중 하나이다.
QueryDSL 동작원리
기존 JPQL이 수행되는 원리
개발자(클라이언트)가 JPQL을 문자열로 직접 작성하면, 타입안정성을 체크할 수 없고 직관적인 동적쿼리도 작성할 수 없다. QueryDSL은 JPQL을 대신 생성하여 이런 문제를 해결한다.
[출처사이트 : https://lordofkangs.tistory.com/456]
3.lmpl
Impl 클래스를 사용하는 이유
여기서 관습적인 추상화 구조라는 제목의 의미 부터 알아야 한다.
관습이라 한 이유는 대부분의 스프링 프로젝트에서 Servcie나 DAO를 구현 할 때,
service.java를 인터페이스로, serviceImpl를 구현체 클래스로 만들어서 사용하기 때문이다.
이미지를 넣어서 변경되었나…
#쿼리셀렉트
#
테스트
이미지들을 확인.
#
상품하나당 이미지가 여러개가 필요할수있습니다.
그중에 대표이미지를 필요할수가 있는데, order값을 0으로 처리할것입니다.
ProductRepository
ㅡ조인을 사용했습니다.
1.delFlag = false면 사용x, 삭제되지않음
2.pi가 0번으로 잡았다는 것은 0번이 대표이미지,
page<Object[]배열> 타입으로 받아올겁니다.
#ProductRepositoryTest
#쿼리DSL에서 처리한것을 주의 깊게 보십시오
#Test의 결과
#ProductService
컨트롤러 > 서비스 > DTO > ENtity > DB접근 >
그 중 , 우리는 지금 서비스계층을 처리하려고합니다.
ProductRepository이 자료를 PruductDTO 형태로 변환할겁니다.
전체데이터계수같은 것들을 이용해서 페이지 처리합니다.
각 오브젝트내용이, 각프로덕트 이미지를 처리할겁니다.
#ProductServiceImpl
#
ProductSeriveTest
#
productController
테스트확인
#
등록기능만들기
정상적으로 활용할수있는지 테스팅하는 용도입니다.
실제서비스와 테스트를 구부하는 것의 중요성
결과
#조회기능 - controller에서
#삭제하는기능 - controoler에서