티스토리 뷰
package study.datajpa.entity;
import jakarta.persistence.*;
import lombok.*;
@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED) // 기본생성자 만들기, 기본생성자는 JPA 스펙으로 private는 안된다.
@ToString(of = {"id", "username", "age"}) //toString을 만들 때에는 가급적이면 연관관계객체는 넣지 않는것이 좋다(서로 부르면서 무한루프 된다.)
@NamedQuery(
name="Member.findByUsername",
query="select m from Member m where m.username =: username"
)
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
private String username;
private int age;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
public Member(String username) { this.username = username; }
public Member(String username, int age) {
this.username = username;
this.age = age;
}
public Member(String username, int age, Team team) {
this.username = username;
this.age = age;
if(team != null) {
changeTeam(team);
}
}
public void changeTeam(Team team){
this.team = team;
team.getMembers().add(this);
}
}
- 엔티티 상단에 NamedQuery를 작성해서 미리 쿼리를 만들 수 있다(JPQL).
사용하는 방식은 이렇다.
public List<Member> findByusername(String username) {
return em.createNamedQuery("Member.findByUsername", Member.class).setParameter("username", username).getResultList();
}
미리 만들어 둔 NamedQuery를 name에 맞춰 작성한다.
이렇게 사용하는 방식도 있겠지만 JPARepository 인터페이스에서도 가능하다.
1 번 방법
public interface MemberRepository extends JpaRepository<Member,Long> {
List<Member> findByUsernameAndAgeGreaterThan(String username, int age);
List<Member> findTop3HelloBy();
@Query(name="Member.findByUsername")
List<Member> findByUsername(@Param("username")String username);
}
가장아래 코드를 보면 @Query 어노테이션의 name 값으로 엔티티에 미리 작성해둔 값을 가져올 수 있다.
@Param은 setParameter를 뜻하니 꼭 붙여줘야 한다.
- 참고: 이 때 메소드명은 중요하지 않다. 아무렇게 작명해도 괜찮다.
하지만 놀라운 방법도 있다.
2번 방법
public interface MemberRepository extends JpaRepository<Member,Long> {
List<Member> findByUsernameAndAgeGreaterThan(String username, int age);
List<Member> findTop3HelloBy();
//@Query(name="Member.findByUsername")
List<Member> findByUsername(@Param("username")String username);
}
이렇게 @Query를 지워도 작동한다. 그 이유는 extends를 할 때에 JpaRepository<엔티티명,아이디타입> 을 작성해줬을 때에 엔티티명을 기준으로 메소드명을 조합해 NamedQuery를 찾기 때문이다.
(예 : Member.findByUsername을 찾게 된다.)
하지만 실무에서는 사실 이 방법은 잘 사용하지 않는다. 더 막강한 기능이 있기 때문이다.
NamedQuery의 큰 장점
- namedQuery는 쿼리가 잘 못 되었을 경우 컴파일 시점에서 오류가 뜬다. 그러므로 개발자가 가장 먼저 오류를 잡을 수 있는 기회를 제공한다.
3번 방법 (막강한 방법)
public interface MemberRepository extends JpaRepository<Member,Long> {
List<Member> findByUsernameAndAgeGreaterThan(String username, int age);
List<Member> findTop3HelloBy();
//@Query(name="Member.findByUsername")
List<Member> findByUsername(@Param("username")String username);
@Query("select m from Member m where m.username = :username and m.age = :age")
List<Member> findUser(@Param("username")String username, @Param("age")int age);
}
이렇게 인터페이스 메소드 위에 직접 JPQL 작성이 가능하다.
- 이 경우에도 쿼리가 틀렸을 경우 오류가 난다. 즉 개발단계에서 개발자가 미리 보정이 가능하다.
'dev_공부일지 > spring data JPA' 카테고리의 다른 글
변환 타입 (중요, null체크) , 페이징과 정렬 (0) | 2024.03.05 |
---|---|
@Query 값 DTO 조회하기 , 파라미터 바인딩 (0) | 2024.03.05 |
메소드 이름으로 쿼리 생성 (0) | 2024.03.05 |
JpaRepository의 정체 (0) | 2024.03.05 |
기본 및 설정 (0) | 2024.03.04 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 항해플러스
- 인터셉터
- exception
- rejectValue
- 항해99
- SpringBoot
- 스프링공부
- filter
- 컨트
- Java
- ArgumentResolver
- reject
- 로그인
- HTTP
- react실행
- thymleaf
- 예외처리
- 리터럴
- BindingResult
- JPA
- React
- 백엔드 개발자 공부
- 향해플러스백엔드
- 향해플러스
- 백엔드 개발자 역량
- jpa api
- 향해99
- hypertexttransferprotocol
- Intercepter
- 스프링부트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
글 보관함