EntityManager.remove()
를 호출EntityManager.find()
를 호출EntityManager.getReference()
를 호출쿼리 메소드 기능은 spring data JPA 가 제공하는 기능으로 메소드 이름만으로 JPQL 쿼리를 생성해서 실행한다.
기본적인 문법
언더바 활용
List<PersonalSchedule> findAllByMember_Id(Long userId);
Hibernate:
select
personalsc0_.id as id1_2_,
personalsc0_.finish_time as finish_t2_2_,
personalsc0_.group_schedule_id as group_sc3_2_,
personalsc0_.member_id as member_i8_2_,
personalsc0_.memo as memo4_2_,
personalsc0_.name as name5_2_,
personalsc0_.start_time as start_ti6_2_,
personalsc0_.weekday as weekday7_2_
from
personal_schedule personalsc0_
left outer join
member member1_
on personalsc0_.member_id=member1_.member_id
where
member1_.member_id=?
apthem dlfmadmfh JPA Named 쿼리를 호출하는 기능으로 @NamedQuery
어노테이션 안에 name, query 속성을 정의하여 메소드에 쿼리를 매핑하는 기능
@Entity
@NamedQuery(
name="findByUsername",
query="select m from Member where m.username = :username"
)
public class Member {
...
}
스프링 데이터 JPA는 선언한 "도메인클래스"."메소드이름" 으로 named query를 먼저 찾고, 없으면 메소드 이름으로 쿼리생성 전략을 사용한다.
@Query 어노테이션을 레포지토리 메소드에 직접 쿼리를 정의하는 방식이다.
public interface MemberRepository extends JpaRespository<Member, Long>{
@Query("select m from Member where m.username = ?1")
Member findByUsername(String username);
//이름기반 파라미터 바인딩
@Query("select m from Member where m.username = ?1")
Member findByUsername(String username);
@Query("select * from member where userinfo = ?0",
nativeQuery = true)
Member findByUserInfo(String userinfo);
}
우리가 자바를 다룰때는 객체를 불러와 객체 그래프로 연관된 객체를 탐색하지만, JPA에서는 그 연관된 객체가 데이터베이스에 저장되어 있으므로, 성능상 이슈로 가벼운 마음으로 탐색을 막하고 다니기는 쉽지 않다.
이때, JPA는 프록시를 사용하여 연관된 객체를 처음부터 db에서 조회해 오는 것이 아니라 실제 사용 시점에 데이터베이스에서 조회해오도록 한다.
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id;
@Column(nullable = false, unique = true)
private String username;
...
@JsonIgnore
@OneToMany(mappedBy = "member")
private List<PersonalSchedule> personalScheduleList;
}
public class PersonalSchedule {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="member_id")
private Member member;
@Column(nullable = false)
private String name;
...
}
이런 1:N 관계의 두 엔티티 member
와 personalSchedule
이 있다고 해보자.
이때 personalSchedule을 조회해 올 일이 있다고 할 때, member 객체까지 조회가 되려면 join 을 해서 member 객체를 조회해 오던지, 따로 쿼리를 날려서 조회해 오던지 해야한다.
하지만 실제로 personalSchedule
을 사용할 때 연관된 member
을 사용하는 경우는 사용하는 방식에 따라 흔할 수도 있고, 흔치 않을 수도 있다.
저 member
을 사용하는게 흔치 않으면, 매번 schedule을 조회할 때마다 member 도 같이 봐주는 것은 성능상 좋지 않다. 이를 위해 JPA는 db 조회를 지연하는 방법을 제공하는데 이를 지연 로딩 이라고 한다.
근데 지연로딩을 사용하려면 실제 entity 객체 대신에 데이터베이스 조회를 지연할 수 있는 가짜 객체가 필요한데, 이를 프록시 객체라고 한다.
Member member = em.find(Member.class, "member1");
Member member = em.getReference(Member.class, "member1");
Member member = em.getReference(Member.class, "member1");
member.getName();
Eager Loading을 사용하려면 @ManyToOne의 fetch 속성을 eager로 설정하면 된다.
public class PersonalSchedule {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.Eager)
@JoinColumn(name="member_id")
private Member member;
@Column(nullable = false)
private String name;
...
}
Hibernate:
select
personalsc0_.id as id1_2_0_,
personalsc0_.finish_time as finish_t2_2_0_,
personalsc0_.group_schedule_id as group_sc3_2_0_,
personalsc0_.member_id as member_i8_2_0_,
personalsc0_.memo as memo4_2_0_,
personalsc0_.name as name5_2_0_,
personalsc0_.start_time as start_ti6_2_0_,
personalsc0_.weekday as weekday7_2_0_,
member1_.member_id as member_i1_1_1_,
member1_.nickname as nickname2_1_1_,
member1_.password as password3_1_1_,
member1_.roles as roles4_1_1_,
member1_.username as username5_1_1_
from
personal_schedule personalsc0_
left outer join
member member1_
on personalsc0_.member_id=member1_.member_id
where
personalsc0_.id=?
기본적으로 @ManyToOne, @OneToOne의 fetch 속성은 즉시로딩이다.
public class PersonalSchedule {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="member_id")
private Member member;
@Column(nullable = false)
private String name;
...
}
Hibernate:
select
personalsc0_.id as id1_2_0_,
personalsc0_.finish_time as finish_t2_2_0_,
personalsc0_.group_schedule_id as group_sc3_2_0_,
personalsc0_.member_id as member_i8_2_0_,
personalsc0_.memo as memo4_2_0_,
personalsc0_.name as name5_2_0_,
personalsc0_.start_time as start_ti6_2_0_,
personalsc0_.weekday as weekday7_2_0_
from
personal_schedule personalsc0_
where
personalsc0_.id=?
Hibernate:
select
member0_.member_id as member_i1_1_0_,
member0_.nickname as nickname2_1_0_,
member0_.password as password3_1_0_,
member0_.roles as roles4_1_0_,
member0_.username as username5_1_0_
from
member member0_
where
member0_.member_id=?
기본적으로 @OneToMany, @ManyToMany의 fetch 속성은 지연로딩이다.
List<PersonalSchedule> findAllByMember_Id(Long userId);
Hibernate:
select
personalsc0_.id as id1_2_,
personalsc0_.finish_time as finish_t2_2_,
personalsc0_.group_schedule_id as group_sc3_2_,
personalsc0_.member_id as member_i8_2_,
personalsc0_.memo as memo4_2_,
personalsc0_.name as name5_2_,
personalsc0_.start_time as start_ti6_2_,
personalsc0_.weekday as weekday7_2_
from
personal_schedule personalsc0_
left outer join
member member1_
on personalsc0_.member_id=member1_.member_id
where
member1_.member_id=?