목록JPA (20)
Hansel

엔티티를 생성,변경 할때 변경한 사람과 시간을 추적하고자 할때 사용하는 기능이 있다. 기본적으로 등록일, 수정일, (등록자, 수정자) 등은 꽤나 자주 사용하게 되는 필드들이다. 이러한 필드를 편리하게 구현하기 위한 다양한 방법들이 존재한다. BaseEntitiy 활용하기 BaseEntity 클래스를 만들어 이 클래스를 다양한 엔티티들이 상속받도록 하는 방법이다. => MappedSuperclass 어노테이션을 사용한다. => 등록일과 수정일 자동화 가능하다. 주의사항 => EnableJpaAuditing 넣어야함 위 방법을 조금 더 간소화할 수 있다. @CreatedDate @LastModifiedDate @EntitiyListeners 이 세가지 어노테이션으로 코드가 매우 짧아졌다. 해당 객체를 생성한..

여러개의 데이터를 수정하고자 할때 일반적으로 데이터의 값을 변경하는 과정은 해당 엔티티를 가져와 값을 변경시키면 JPA가 Commit 시점에 변경을 감지하여 DB에 반영한다. 하지만 다량의 데이터를 한번에 수정하고자 할때는 위의 방법으로 하기엔 비효율적이다. 그럴땐 벌크 연산을 통해 다량의 데이터를 수정할 수 있다. 위의 쿼리는 파라미터로 넘긴 age보다 큰 age 값을 가진 Member는 모두 age + 1을 하겠다는 쿼리이다. 메소드가 int형인건 변경된 데이터가 몇개인지를 반환하기 때문이다. 하지만 위 함수는 영속성 컨텍스트와 관련된 문제가 있다. 벌크 연산의 문제점 위 코드에선 총 4개의 데이터가 값이 변경된다. 하지만 변경하고 곧바로 값을 확인해보면 변경된 값이 아닌 이전의 값이 반환될 것이다...

스프링 데이터 JPA를 통한 정렬과 페이징 스프링 데이터 JPA를 사용하지 않은 리포지토리에선 setFirst와 setMax를 통해 offset과 limit를 설정하고 수에 맞게 데이터를 가져왔다. 하지만 스프링 데이터 JPA를 사용하면 더 간편한 방법으로 더 효율적인 결과를 얻을 수 있다. 페이징을 하기 위해선 어떤 필드를 이용해 데이터를 가져올지, 그리고 페이징 조건을 파라미터로 넣어야한다. pageable로 보낼 변수는 PageRequest를 통해 작성한다. 사진을 보면 알 수 있듯이 인텔리제이에서 친절하게 알려주고 있다. 사진에서는 0페이지에서 3개만큼의 데이터를 원하고 있으니 3개의 데이터가 반환되었다. 임시로 넣은 데이터가 총 6개인데 그럼 0페이지와 1페이지에선 각각 3개의 데이터가 있을것이..

쿼리 메소드 매우 유용한 기능이다. 메소드의 이름을 통해 다양한 쿼리를 생성할 수 있다. https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation Spring Data JPA - Reference Documentation Example 109. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("d..

스프링 데이터 JPA 스프링 데이터 jpa는 jpa 기반의 리포지토리를 매우 쉽게 사용하도록 돕는 인터페이스이다. 생성하는 방법은 매우 간단하다. JpaRepository를 상속받는 인터페이스를 작성하면 되는데 태그 안에 클래스명과 PK의 타입을 명시해주면 된다. 구현체가 없는데 어떻게 동작을 하지? 스프링 데이터 JPA가 구현체를 만들어서 해당 인터페이스에 인젝션을 해준다. 기존에 사용하던 Repository 어노테이션이 필요 없다. 주요 메서드 save : 저장, 이미 저장한건 병합 delete : 엔티티 삭제 findById : 엔티티 하나 조회 findAll : 모든 엔티티 조회. findBy필드명 : 필드명으로 검색 스프링 데이터 JPA를 사용하면 이제 save나 단순 find 등의 메서드는 작..

경로 표현식 => '.' 을 사용해 객체 그래프를 탐색하는 것을 의미한다. JPQL 쿼리문에서 select m.username , select m.team.name 등과 같은 방식으로 탐색하는 것을 말한다. 경로 표현식은 상태 필드, 단일값 연관 경로, 컬렉션 값 연관 경로로 나뉜다. 1. 상태 필드 상태 필드는 경로 탐색의 끝이다. 위 쿼리문을 보면 m.username에서 더 깊이 들어갈 수 없다. username과 age는 상태 필드이다. 2. 단일값 연관 경로 (ManyToOne || OneToOne) 위 쿼리문은 멤버와 연관된 팀의 이름을 가져온다. Member와 관계가 형성된 Team은 관계 상 One에 해당되기 때문에 단일 값 연관 경로가 되는 것이다. 객체상으로는 단순 조회로 보이지만 db상..

jpa를 사용하면서 특정 데이터를 조회하고 싶을땐 엔티티 매니저의 find 메서드를 사용해 조회할 수 있다. 하지만 특정 조건이 있고 다수의 데이터를 조회하고 싶을땐 query를 작성해야한다. => JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공한다. SQL과의 차이는? JPQL : 엔티티 객체를 대상으로 쿼리 SQL : 데이터베이스 테이블을 대상으로 쿼리 동적 쿼리는? 쿼리문이 항상 고정적일 수는 없다. 필드에 따라 다른 결과를 가져와야 하는데 위의 쿼리문으로는 그 방법이 불가능하다. 1. Criteria Criteria는 문자가 아닌 자바코드로 JPQL을 작성할 수 있으며 JPA의 공식 기능이다. 보이는 쿼리문 자체는 이해하기 어렵지 않지만 문제는 작성할때 저런 복잡한 방법을 잘 ..

값 타입 컬렉션의 정의 : 값 타입을 컬렉션에 담아 쓰는것 , 값 타입 하나 이상 저장할때 사용 1.매핑방법 @ElementCollection @CollectionTable //db의 테이블 명 2. 값 타입을 따로 persist 하지 않아도 된다. 사진에서는 member와 같은 라이프 사이클을 따라간다. 3. 값타입 컬렉션들은 기본적으로 지연로딩이다. 4. 값 타입 수정은? 값 타입은 불변적이어야 한다 => 통으로 갈아낀다. 하지만 컬렉션은 remove 사용시 equals에 의존한다. 따라서 equals의 오버라이드가 매우 중요하다. 예상과는 다른 쿼리 하지만 위에서 행한 값타입 수정의 쿼리 동작 방식이 좀 의아하다. delete 쿼리 한번(remove) 그리고 insert 한번(add)이면 될 듯 한..

임베디드 타입을 여러 엔티티에서 공유하면 위험하다. 회원1과 회원2 모두 임베디드 타입인 주소를 참조한다 가정하자. 이 경우 회원1의 주소를 NEW Address() 로 초기화하면 회원들이 가지고 있는 주소는 모두 초기화 되어버린다. 따라서 => 객체가 아닌 값을 복사 해서 사용해야한다. => 하지만 객체의 공유 참조를 피할 방법이 없기 때문에 (=를 통한 대입, 혹은 SETTER 등) 위험한건 여전하다. => 따라서 생성자로만 값을 설정하고 SETTER를 만들지 않으면 된다. => 불변객체 그럼 값을 바꾸고 싶다면 어떻게 해야할까? => 새로 해당 객체를 생성해서 통으로 바꿔야한다. 결론 : 값 타입은 불변으로 만들어야 안전하다. 값 타입 비교 임베디드 타입은 db상에선 단순한 필드지만 결국 하나의 객..

JPA의 타입 분류 엔티티타입 : @Entity로 정의하는 객체, 데이터가 변해도 식별자로 추적 가능(엔티티의 필드 값이 변경되어도 식별자로 인식 가능하다) 값 타입 : 자바의 기본 타입이나 식별자가 없고 값만 있으므로 변경시 추적이 불가능하다. 값타입의 분류 기본값타입 : (int, double, Integer, Long, String) 임베디드 타입 : embedded type, 복합 값 타입(클래스) 컬렉션 타입 값 타입의 특징 생명 주기를 엔티티에 의존한다. 엔티티가 삭제되면 그에 해당하는 필드도 함께 사라진다. 값 타입은 공유하면 안된다. 필드 변경시 다른 엔티티의 필드가 따라서 변경되면 안된다. 임베디드 타입 1. 임베디드 타입은? : 단순한 엔티티의 값일 뿐이다. : 하지만 객체와 세밀한 매..