분류 전체보기 954

37. JPQL

JPA는 다양한 방식으로 쿼리방법을 지원 JPQL JPA Criteria QueryDSL 네이티브 SQL JDBC API 직접사용, MyBatis, SpringJdbcTemplate와 함께 JPA Criteria 자바코드로 짜서 JPQL로 빌드해주는 제너레이터 네이티브 SQL은 JPQL써도 가끔 정말 DB종속적인 쿼리를 짜야할 때가 있음. 표준 SQL을 벗어나는. 거의 JPQL로 해결이 되긴 하는데, 정말 가끔 안될 때가 있다. 그 때 네이티브SQL이나 MyBatis나 스프링JDBCTemplate 같은 걸 쓰면 된다. JPQL은 엔티티중심적 언어. 테이블은 매핑만 하는 거고, JPQL은 엔티티 대상으로 작성하는 언어임. 결국 문제는 검색쿼리인데, JPQL은 검색도 테이블이 아닌 엔티티 객체를 대상으로 검..

JPA/JPA 기본 2023.10.30

36. 값타입 실전

할만한 게 이제 address. 저거 한곳에 모아서 관리하기 괜찮아 보임. 근데 이미 하지 않았나..? 여튼 다시 해봄 @Embeddable public class Address { private String city; private String street; private String zipcode; } getter, setter는 getter는 public, setter는 private 그러므로 생성자는 기본생성자에, 필드들 다 받는거. 또 그다음 equals() 오버라이드. 인텔리제이가 자동 생성 해 주는거. 근데 이거 할 때, 저거 getters 사용하라고 체크해주는 게 좋음. 저거 체크 안하면 this. 해서 이렇게 접근하는데, 그러면 프록시일경우 제대로 접근 못함. 프록시는 원본을 째로 가지고..

JPA/JPA 기본 2023.10.30

35. 값타입 컬렉션

값타입 컬렉션은 값타입을 컬렉션에 담아서 쓰는거다. 기본값타입이나 임베디드를 컬렉션에 담아서 쓰는 걸 말하는 건가.. 지금까지 엔티티는 컬렉션에 넣어서 한 적은 있는데.. 일단. RDB 테이블에서는 컬렉션을 할 수 있는 구조는 없다. (json 하면서 그런 것들에 대한 걸 지원하는 DB도 있긴 하지만) 그래서 저렇게 테이블을 따로 나눈 듯 하다. 그래서 그냥 개념적으로 보면 일대다랑 같다. 보면은 다 PK이다. 뭐 저렇게 식별자 같은 개념을 넣어서 걔를 PK로 쓰면 그거는 값타입이 아니라 엔티티라고.. 그냥 이럴경우는 엔티티로 설계하면 되는 거 아닌가..? 여튼 그래서 값타입은 이렇게 이 값들을 테이블에 값들만 저장되고 이걸 묶어서 PK로 구성을 하면 된다고 하는데... 기본자료구조 하위에 있는 인터페이..

JPA/JPA 기본 2023.10.29

34. 값타입 비교

값타입은 아무래도 인스턴스가 달라도 그 안에 값이 같으면 같은 것으로 봐야 함. 예를 들면 테이블에서 같은 주소를 가지고 있으면 그건 같은 곳에 사는 거니까.. 근데 임베디드 타입, 얘네들은 클래스기 때문에 == 했을 때 인스턴스의 주소를 비교하기 때문에.. 내부의 값이 같다고 해도 다른 거라고 나옴. 그래서, 값타입 비교 시 동일성 비교 : 인스턴스의 참조를 비교, == 사용 과 동등성 비교 : 인스턴스의 값을 비교, equals() 등 이 둘을 구분해서 사용해야 함. 그래서, 값타입은 equals() 메소드를 재정의 해야 함. 거의 모든 필드를 지정해서 재정의 해야함. 참고로, equals() 자체의 기본이 ==비교라 재정의 해야 함. 보통 equals() 재정의 할 때는 자동으로 만들어 주는 거 쓰..

JPA/JPA 기본 2023.10.29

33. 값타입과 불변 객체

값타입은 복잡한 객체 세상을 조금이라도 단순화하려고 만든 개념. 따라서, 값타입은 단순하고 안전하게 다룰 수 있어야 함. 우리가 int, String 같은 건 써도 크게 신경을 안쓰지만, 객체는 신경쓴다. 왜냐하면 객체는 주소를 넘기는 것 이기 때문에. 근데, 앞서 봤겠지만, 임베디드는 자바입장에서는 클래스임. 그래서 사실 공유가 가능하게 됨. 그래서 이 임베디드를 여러 엔티티에서 공유하게 될 수도 있어서 위험함. Address address = new Address("city1", "street1", "zip1"); Member member1 = new Member(); member1.setName("memberA"); member1.setHomeAddress(address); member1.setPe..

JPA/JPA 기본 2023.10.29

32. 임베디드 타입

임베디드 타입 새로운 값 타입을 직접 정의할 수 있다. 주로 기본값 타입을 모아서 만들어서 복합 값 타입이라고도 한다. 신기한 점은, int나 String 같이 추적되는 것이 아니라 바꾸면 끝나는 그런거다. 예시 이렇게 회원 엔티티 있을 때, 뭔가 공통적으로 묶어서 할 수 있다. 예를 들어 이렇게. 아예 주소와 날짜는 묶어서 취급한다. 그냥 클래스 하나 더 만들어서 취급하는 거랑 비슷하긴 하다. 이렇게 임베디드 타입 사용법은 @Embeddable : 값 타입을 정의한 곳 @Embedded : 값 타입을 사용한 곳. 기본 생성자 필수임. 임베디드 타입 장점 재사용 가능 높은 응집도 메소드 만들 수 있음. 임베디드를 포함한 모든 값 타입은, 값타입을 소유한 엔티티의 생명주기에 의존. 엔티티의 생명주기에 의존..

JPA/JPA 기본 2023.10.29

31. 기본값 타입

JPA의 데이터 타입 분류 엔티티 기본 타입 이렇게 최상위에서는 2가지 있고, 엔티티타입은 내가 엔티티의 뭔가를 변경해도 추적이 가능하다. 엔티티는 객체니 주소로 추적이 가능. 값타입은 그냥 값 타입이다. 값이 100에서 200으로 바뀌면 그냥 완전히 새로 바뀌는 거지 추적 불가. 그냥 객체로 콜바이 레퍼런스 콜 바이 벨류 그런 시선으로 보면 될 듯 하다. 값타입을 약간 더 세세하게 분류해 보자면 기본값타입 - 기본타입 (int, double 등) - 래퍼 클래스(Integer, Long 등) - String 임베디드 타입 - 복합값 타입, 그러니까 클래스 같은것들. 컬렉션 타입 - 리스트 등 이렇게 3가지이고, 기본값 타입은 생명주기를 엔티티에 의존하고(엔티티 삭제하면 얘가 가지고 있던 기본값타입 다 ..

JPA/JPA 기본 2023.10.29

30. 실전 연관관계 관리

뭐 일단 기본은, ManyToOne 쪽이 주인이라는 것과, 일단 그렇게 단방향으로 다 설계하고, 필요에 따라서 양방향, 그리고, 또 중요한 것이 모두 지연로딩으로. @xToOne은 기본이 즉시로딩이므로, fetch=FetchType.LAZY 해서 모두 지연로딩으로 바꿔줘야 한다. 뭐 그냥 다 지연로딩으로 하면 된다. 이번같은 경우 주문이랑 배송이랑은 거의 짝꿍이고, 생명주기도 같아보이므로, 영속성 전파를 사용할 것이다. 주문과 주문상품도, 주문에 완전히 종속적이기에, 고아객체와 영속성 전파를 모두 사용하는 것도 괜찮아 보인다. @Entity @Table(name="ORDERS") public class Order extends BaseEntity{ @Id @GeneratedValue @Column(nam..

JPA/JPA 기본 2023.10.29

29. 영속성 전이와 고아 객체

영속성(persist) 전이는 말 그대로 특정 엔티티 persist 하면 연관된 엔티티들도 persist 하는 말 그대로 영속성을 전이시키는 거임. 그러니까, Member에 필드로 Team이 있으면, 이 영속성 전이 기능을 사용하면 member만 persist 해도 Team도 persist 되는거임. 코드 @Entity public class Parent { @Id @GeneratedValue private Long id; private String name; @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL) private List children = new ArrayList(); } 간단하다. 그냥 같이 persist 하고 싶은 연관관계에 casc..

JPA/JPA 기본 2023.10.28

28. 즉시로딩, 지연로딩

지연로딩 LAZY 사용방법 @Entity public class Member { public Member() { } @Id @GeneratedValue @Column(name = "MEMBER_ID") private Long id; @Column(name="USERNAME", nullable = false) private String name; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "TEAM_ID") private Team team; @OneToOne Locker locker; } 연관관계에서, fetch = FetchType.LAZY 해 놓으면 프록시로, team을 프록시로 일단 가져온다. Team team1 = new Team(); team1..

JPA/JPA 기본 2023.10.28