JPARepository를 이용한 데이터조회 예제

LikeGhost·2023년 8월 6일
0

JPA를 이용하면, 간단한 CRUD 기능은 JpaRepository 인터페이스에서 메서드시그니처를 작성하거나 JPQL문을 작성하지 않아도 동작을 실행시킬 수 있다.

하지만 기본적인 CRUD 외의 특정한 데이터 처리를 하려면 JpaRepository에 기능에 맞는 메서드시그니처를 작성하거나 JPQL문을 작성해줘야 한다.

이번에 몇가지 데이터조회 예제를 작성한다.


※ 예제에 사용할 테이블/테이블정보

예제에 사용할 Notice테이블의 정보와 테이블안의 데이터다.

※ 예제에 사용할 엔티티클래스

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "NOTICE")
@Table(name = "NOTICE")
public class Content {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long noticeId;

    @Column(length = 100, nullable = false, updatable = true)
    private String title;

    @Column(length = 3000)
    private String content;

    @Column(length = 1000)
    private String attachFile;

    @ManyToOne
    @JoinColumn(name = "CATEGORY_ID")
    private Category category;

    @ManyToOne
    @JoinColumn(name = "MEMBER_ID")
    private Member member;

    @CreatedDate
    @Column(name = "created_at", updatable = false)
    private LocalDateTime createdAt = LocalDateTime.now();

    @LastModifiedDate
    @Column(name = "modified_at")
    private LocalDateTime modifiedAt = LocalDateTime.now();
}

엔티티클래스명은 Content이지만 실제 DB의 테이블명은 notice이므로
@Entity와 @Table 의 name을 NOTICE로 지정했다.

@ManyToOne
@JoinColumn(name = "CATEGORY_ID")
private Category category;

@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;

이것은 Content 엔티티클래스가 Category 엔티티클래스 및 Member 엔티티클래스와 다대일 관계를 형성한다는 것을 의미한다.
그리고 각각 엔티티의 ID(CATEGORY_ID, MEMBER_ID) 로 조인하는 것을 의미한다.

※ 예제에 사용할 JpaRepository

public interface ContentRepository extends JpaRepository<Content, Long> {


}

Content 엔티티로 사용할 JpaRepository 인터페이스다.
JpaRepository<Content, Long> 의 첫번째 제네렉파라미터는 해당 JpaRepository의 엔티티클래스를 의미하고 두번째 제네릭파라미터는 이 엔티티클래스의 식별자멤버(@Id)의 타입을 의미한다.


1. 테이블의 특정컬럼으로 데이터 조회

테이블에서 특정컬럼을 where 조건으로 두고 데이터를 조회한다.

위의 그림처럼 title이라는 컬럼을 조건으로 데이터를 조회하려할 때는 JpaRepository에 아래와 같이 입력한다.

이와같이 입력하면 title 이라는 컬럼을 조건으로 데이터를 가져온다.

이렇게 위 워크밴치와 같은 조건으로 요청을 하면 워크밴치의 요청결과와 같은 데이터를 조회하게 된다.

[
    {
        "noticeId": 1,
        "title": "제목1",
        "content": "내용내용1",
        "attachFile": "첨부1",
        "memberId": 1,
        "categoryId": 1,
        "createdAt": "2023-07-03T15:58:30",
        "modifiedAt": null
    },
    {
        "noticeId": 5,
        "title": "제목1",
        "content": "내용내용5",
        "attachFile": "5첨부2",
        "memberId": 3,
        "categoryId": 1,
        "createdAt": "2023-07-03T16:00:02",
        "modifiedAt": null
    }
]

2. 2개의 컬럼조건으로 데이터 조회

where에서 2개의 컬럼조건으로 데이터 조회한다.

위와 같이 where 절에서 2개의 컬럼 조건을 쓸 경우 JpaRepository에 아래와 같이 입력한다.

By+첫번째조건멤버+And+두번째조건멤버
이런식으로 메서드명을 적는다.

이렇게 같은 조건으로 데이터요청시 아래와 같이 결과를 얻는다.

[
    {
        "noticeId": 5,
        "title": "제목1",
        "content": "내용내용5",
        "attachFile": "5첨부2",
        "memberId": 3,
        "categoryId": 1,
        "createdAt": "2023-07-03T16:00:02",
        "modifiedAt": null
    }
]

3. 특정컬럼값 하나 조회

특정컬럼값 하나를 조회한다.

위와 같이 attach_file 컬럼값 하나를 조회하고자 할 때
아래와 같이 작성한다.

find+조회할멤버+By+조건멤버
이런식으로 작성한다.

[ ※ 예제에서는 이미 row개수가 1개만 나올 것을 알아서 Content find... 로 작성했는데,
원래는 2개 이상 row 개수가 나올 수 있으므로 List< Content > find... 식으로 작성해주는게 맞다. ]

이렇게 메서드명을 작성하고 요청을 하면 이 findAttachFileByNoticeId메서드를 요청을 한 Content 타입 변수에는 AttachFile멤버에 select결과데이터가 들어간다. AttachFile내용을 요청했으므로 AttachFile 외 멤버는 Null 상태일 것이다.
그래서 서비스단계에서 아래와 같이 작성하여 해당멤버만 get하여 반환하거나...

    public String findContentsBySpeci(long noticeId){

        Content findAttachFile = contentRepository.findAttachFileByNoticeId(noticeId);
        String result = findAttachFile.getAttachFile();

        return result;

    }

별도처리를 하여 반환해주면 된다.

이런 방법으로 요청을 하면 "첨부2" 라는 결과를 얻는다.


4. JPQL 사용

JpaRepository에서 메서드시그니처 말고도 JPQL방법으로 조회할 수도 있다.

메서드 위에 @Query 입력 후 value 값에는 쿼리내용을 적는다.
먼저 from 절에 사용할 테이블(NOTICE)를 적고 alias(n)을 적는다. 그리고
select 문에 alias(n)을 적고 where 절에는 alias(n)의 멤버noticeId을 조건으로 사용하기 위해 n.noticeId 라고 적는다.
메서드시그니처의 파라미터 (@Param("noticeId") long noticeId) 는,
long noticeId 파라미터 값을 JPQL에서 @Param()의 명칭의 값으로 사용하겠다는 것을 의미한다. 다시 말해서 long noticeId 값이 @Param("noticeId") 의 noticeId 로 전달되고 이 noticeId는 다시 JPQL의 :noticeId 로 전달된다.
nativeQuery = false 의 경우는 false 가 default이므로 이 문장을 생략할 수 있다.

이는 SQL문으로
select n.* from notice n where n.notice = :noticeId 와 동일한다.


5. Like 조회

JPQL을 사용하여 Like 조건으로 데이터를 조회한다.

위와 같이 데이터를 조회하고자 할 경우 아래와 같이 작성한다.

where like가 '%첨부2%' 인 것처럼
JPQL에도 like %:attachFile% 이런식으로 적어준다.

조건을 '첨부2'로 시작하는 값을 조회할 경우
:attachFile%

조건을 '첨부2'로 끝나는 값을 조회할 경우
%:attachFile

이렇게 사용할 수도 있다.

요청을 하면 아래와 같은 결과를 얻는다.

[
    {
        "noticeId": 2,
        "title": "제목2",
        "content": "내용내용2",
        "attachFile": "첨부2",
        "memberId": 2,
        "categoryId": 1,
        "createdAt": "2023-07-03T15:59:01",
        "modifiedAt": null
    },
    {
        "noticeId": 4,
        "title": "제목4",
        "content": "내용내용4",
        "attachFile": "6첨부2텐",
        "memberId": 2,
        "categoryId": 2,
        "createdAt": "2023-07-03T15:59:46",
        "modifiedAt": null
    },
    {
        "noticeId": 5,
        "title": "제목1",
        "content": "내용내용5",
        "attachFile": "5첨부2",
        "memberId": 3,
        "categoryId": 1,
        "createdAt": "2023-07-03T16:00:02",
        "modifiedAt": null
    },
    {
        "noticeId": 7,
        "title": "제목222",
        "content": "내용내용222",
        "attachFile": "첨부222",
        "memberId": 2,
        "categoryId": 2,
        "createdAt": "2023-07-04T23:16:44",
        "modifiedAt": "2023-07-04T23:16:44"
    }
]

6. 출력순서

조회데이터에 대해서 컬럼별로 출력순서를 정한다.

위 결과를 보면 category_id 오름차순으로 우선정렬하고, category_id가 동등할 경우 2차적으로 member_id 내림차순으로 정렬했다.

위 정렬방법을 구현할 경우 아래와 같이 작성한다.

find...+OrderBy+첫번째정렬대상멤버+Asc(오름차순) 혹은 Desc(내림차순)+(이후 정렬이 필요한 경우 멤버+Asc 혹은 Desc 로 작성해나감)

이렇게 입력하면 1차적으로 CategoryId 로 오름차순정렬하고 2차적으로 MemberId로 내림차순정렬을 한다.
멤버를 적을 때 CategoryId, MemberId로 적지 않고 Category, Member 로 적었는데, 이는 Content 엔티티 클래스에서 category, member 로 멤버를 선언했고 category_id, member_id를 joincolumn으로 두었기 때문에 categoryId, memberId 대신 멤버인 category, member 로 적은 것이다.

이렇게 요청한 결과를 보면 아래와 같다.

[
    {
        "noticeId": 5,
        "title": "제목1",
        "content": "내용내용5",
        "attachFile": "5첨부2",
        "memberId": 3,
        "categoryId": 1,
        "createdAt": "2023-07-03T16:00:02",
        "modifiedAt": null
    },
    {
        "noticeId": 2,
        "title": "제목2",
        "content": "내용내용2",
        "attachFile": "첨부2",
        "memberId": 2,
        "categoryId": 1,
        "createdAt": "2023-07-03T15:59:01",
        "modifiedAt": null
    },
    {
        "noticeId": 1,
        "title": "제목1",
        "content": "내용내용1",
        "attachFile": "첨부1",
        "memberId": 1,
        "categoryId": 1,
        "createdAt": "2023-07-03T15:58:30",
        "modifiedAt": null
    },
    {
        "noticeId": 4,
        "title": "제목4",
        "content": "내용내용4",
        "attachFile": "6첨부2텐",
        "memberId": 2,
        "categoryId": 2,
        "createdAt": "2023-07-03T15:59:46",
        "modifiedAt": null
    },
    {
        "noticeId": 7,
        "title": "제목222",
        "content": "내용내용222",
        "attachFile": "첨부222",
        "memberId": 2,
        "categoryId": 2,
        "createdAt": "2023-07-04T23:16:44",
        "modifiedAt": "2023-07-04T23:16:44"
    },
    {
        "noticeId": 3,
        "title": "제목3",
        "content": "내용내용3",
        "attachFile": "첨부3",
        "memberId": 1,
        "categoryId": 2,
        "createdAt": "2023-07-03T15:59:28",
        "modifiedAt": null
    }
]
profile
One Week One Write

0개의 댓글

관련 채용 정보