스프링 강의 요약-(5)

이진우·2023년 7월 1일
0

스프링 강의 요약

목록 보기
6/13

아래는 김영한 강사님의 JPA 표준을 듣고 정리한 내용이다.

임베디드 타입

기본 값타입을 모아서 만들어진다. int,String 과 같은 값 타입이라서 복사만 한다.
비슷한 성격을 모아서 클래스를 만들고 @Embeddable은 만든 클래스에, @Embedded 는 값 타입을 사용하는 곳에 붙여준다
기본생성자가 필수이다.
해당 값 타입만 사용하는 의미있는 메소드를 만들 수 있다
값 타입이라서 엔티티의 생명주기에 의존
테이블과 달리 객체는 데이터 뿐만 아니라 메소드가 있기에 묶었을 떄 장점이 크다
한 엔티티에서 같은 값 타입을 사용하면 @AttributeOverrides,@AttributeOverride 를 사용햐서 컬럼명을 바꾸어서 사용가능

값타입은 불변으로!

임베디드 타입 같은 값 타입을 여러 엔티티에서 공유할 경우 member.getAddress().setCity("new City")등으로 하면 위험하다
엔티티에 들어간 값이 다 바뀌기 때문이다. 이러한 상황을 방지하려면 복사를 해야 하는데 값 타입이 기본 타입이 아니라 객체 타입이라서 =으로 복사하다가 참조가 공유될 수 있다
그렇기 때문에 set을 없앰으로써 불변 객체로 만들고 그래도 수정이 필요하면 새로 인스턴스를 생성해서 만들어야 함

값 타입 컬렉션

데이터베이스에선...

컬렉션이 적용이 안되므로 1대 다로 별도의 db테이블을 따로 만들어 관리한다. 단 식별자 ID를 도입하면 값타입이 아니라 Entity가 되어버리므로 이 점을 주의한다

사용법

ex
@ElementCollection
@CollectionTable(name="FAVORITE_FOODS",
JoinColumns=@JoinColumn(name="MEMBER_ID"))
private Set<String> favoriteFoods=new HashSet<>;

조회

기본적으로 컬렉션을 지연로딩으로 가지고 온다

수정

주인엔티티의 연관된 모든 데이터를 삭제하고, 값타입 컬렉션에 있는 현재 값을 모두 다시 저장해서 쓰지 말아야 한다

결론은

값 타입 컬렉션 대신에 엔티티로 일대다를 고려하고 Cascade+고아 객체 제거를 활용해서 값타입 컬렉션처럼 사용해야 함
값타입 컬렉션이 진짜 단순할 때 값 타입 컬렉션을 쓴다,값이 바뀌어도 update 칠 필요 없을때 selection box 같은 곳에서 활용
식별자가 필요하고, 지속해서 값을 추적,변경해야 한다면 그것은 값타입이 아닌 엔티티이다

JPQL 개요

JPA가 지원하는 쿼리 방법은?

1)JPQL:표준 문법으로 거의 대부분 해결
2)JPA Criteria,QueryDSL: 자바 코드로 짜서 JPQL을 빌드 해주는 제너레이터 클래스의 모음
3)Native SQL:표준 SQL 벗어날떄 Native 쿼리 직접 날린다(Oracle의 connectBY같이)
4)JDBC API 직접 사용

JPQL

필요성

테이블이 아닌 엔티티 객체를 대상으로 검색할때 유용하다
모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능하고
필요한 데이터만 DB에서 가져오려면 검색 조건이 포함된 SQL 필요

JPQL 사용예

List<Member> result=em.createQuery("select m from Member m where m.name like '%kim%'".getResultList();

Criteria

동적쿼리가 어려워서 자바 표준이 지원하는 문법이지만 복잡하고 실용성이 없어서 QueryDSL 사용 권장

NativeSQL

사용예

List<Member> resultList=em.createNativeQuery("select ID,AGE FROM MEMBER WHERE NAME='kim'",Member.class).getResultList());

참고

JPQL 날릴 떄 em.persist()한 것을 미리 저장을 해놓는다. JPA와 관련된 것은 가능이다
그러나 DB 커넥션을 획득하고 그것으로 쿼리를 날리면(JPA랑 관련 X) 미리 저장을 하지 않음

JPQL-기본

update문?

JPA는 트랜잭션 내에서 값을 바꾸면 자동으로 update 쳐주지만, 한건 한건만 바꿀 수 있다.
이 경우 한방에 여러개를 update 치기 위해서(예를 들어 전사원 연봉 10프로 증가) update 문을 가진 JPQL을 사용할 수 있다.

TypedQuery VS Query

TypeQuery는 반환타입이 명확할때 사용, Query는 반환 타입이 명확하지 않을 때 사용
TypedQuery는 select m From member m 같은 경우
Query는 select m.username, m.age 같은 경우

파라미터바인딩의 예

List<Member> resultList=em.createQuery("select m from Member m 
where m.username=:username",Member.class).
setParameter("username","leee").getResultList();

결과조회 방법

  • getResultList
  • 결과가 하나 이상일 때, NullpointerException 걱정 안해도 됨
  • getSingleResult
  • 결과가 정확히 하나일때만 사용,나머지 경우에 예외 터진다.

    프로젝션

    프로젝션이란 select 절에 조회할 대상을 지정하는 것을 뜻한다

    연관된 엔티티를 프로젝션할때

    select m.team from Member m 보다는
    select t from Member m join m.team t가 join이 잘 보이기에 좋다

    distinct 중복 제거 예제

    select distinct m.username,m.age from Member m

    여러값을 조회할때

    QueryType,Object[]타입으로 조회가능하지만
    DTO로 조회하는 것이 훨씬 좋다.

    사용예

    List<MemberDTO> result=em.createQuery("select 
    new JPQL.MemberDTO(m.USERNAME,m.age) from Member m,MemberDTO.class)
    .getResultList();

    주의점

    꼭 Dto 클래스에 생성자 쓰기!

    페이징 사용법

    사용예
    List<Member> result=em.createQuery("select m from Member m
     order by m.age desc",Member.class)
    .setParameter(1)//0부터 시작하는 startPosition
    .setMaxResults(20)//조회할 데이터 수
    .getresultList();

    조인

    종류

  • 내부조인: 조인조건을 만족하는 두 테이블의 공통된 값을 기반으로 join을 수행하는 것을 내부 join이라고 하며 멤버는 있고 팀이 없다면 출력하지 않는다
  • 외부 조인: 조인 조건을 만족하지 않는 레코드도 결과에 포함한다. 외부 join은 팀이 없어도 멤버는 조인이 가능하다
  • 세타조인: 연관관계 전혀 없는지 비교할때 사용한다
  • ON절 활용하여

    1)조인대상 필터링
    2)연관관계 없는 엔티티를 외부조인이 가능하다
    profile
    기록을 통해 실력을 쌓아가자

    0개의 댓글