티스토리 뷰

반응형

Spring Boot로 Rest API를 작업을 하면서 DB 관련 작업을 할 때, JPA를 이용하신 적 있나요? 저 또한 JPA를 이용해서 수많은 API를 만들었습니다.

 

JPA에 대해 간단히 소개해 드리자면, Java에서 DB를 객체로 관리하기 위해 사용되는 ORM입니다.

객체를 이용하여 Data를 관리하기 때문에 프로그래밍 단에서 제어가 가능해지고 개발자는 비즈니스 로직에 집중할 수 있으며, 배우기만 하면 빠른 개발이 가능하다고 합니다. 

 

그리고 Query Method라고 특정 규칙을 이용한 Method Name을 설정함으로써, 쿼리를 작성 안 할 수 있다는 큰 장점이 있지만, 복잡한 쿼리 및 Join 등을 이용할 시에는 @Query라는 어노테이션을 사용하거나, QueryDsl을 이용해야 하는데, 이거에 대한 학습이 필요합니다.

 

그리고 이 글을 쓰는 이유가 바로 JPA를 이용하면 영속성(Spring 영속성)을 이용하여 Data 관리를 해야 하는데,

Entity가 아닌 내가 원하는 DTO로 Data를 받고 싶을 때, 어떻게 해야 하는지 찾아보다가 발견하여 정리하기 위해 글을 작성하는 겁니다.

 

우선 방법은 여러 가지가 있습니다. 제가 아는 방법들은 

 

1.  @SqlResultSetMapping를 이용하여 DTO로 받기

2.  QLRM 라이브러리 이용하기

 

이 정도입니다. 이 두 가지 방법의 공통점은 EntityManager를 이용한다는 점이며, 다만 Result를 개인이 만든 DTO로 받을 때 어떻게 받느냐의 차이입니다.

 

우선 @SqlResultSetMapping을 이용한 방법입니다.

 

1. 내가 이용하고 싶은 DTO를 만든다. ( 생성자도 만들어 줘야 함 )

@Data
public class RecommandPostList {
	
	private Long postId;
	private Long userId;
	private Integer phoneNumber;
	private Date registerTime;
	private Geometry location;
	
	public RecommandPostList(
			Long postId,
			Long userId,
			Integer phoneNumber,
			Date registerTime,
			Geometry location
			) {
		this.postId = postId;
		this.userId = userId;
		this.phoneNumber = phoneNumber;
		this.registerTime = registerTime;
		this.location = location;
	}

}

 

2. @SqlResultSetMapping을 이용하여 Mapping? ( Mabatis의 resultMap과 비슷)

! 다만 @Entity가 선언된 Class에서 선언을 해줘야 합니다.

@Data
@Entity(name="t_posts")

// 내용을 보시면 Mapping Name을 RecommandPostListMapping로 선언했으며, 해당 Query Result 들을 Matching 시켜주는 그런 역할입니다.
@SqlResultSetMapping(
        name="RecommandPostListMapping",
        classes = @ConstructorResult(
                targetClass = RecommandPostList.class,
                columns = {
                        @ColumnResult(name="postId", type = Long.class),
                        @ColumnResult(name="userId", type = Long.class),
                        @ColumnResult(name="phoneNumber", type = Integer.class),
                        @ColumnResult(name="registerTime", type = Date.class),
                        @ColumnResult(name="location", type = Geometry.class),
                })
)


public class Post {
   // 생략
}

3. DTO로 Mapping 하기

@Service
public class DtoSampleService{

	@PersistenceContext
	EntityManager em;
    
    public List<RecommandPostList> getList() {
    	
        String query = "생략";
        // 아까 선언해둔거 이용
        Query query = em.createNativeQuery(q, "RecommandPostListMapping");
        List<RecommandPostList> list = query.getResultList();   
        return list;    
    }
}

끝입니다. 간단해 보이나요? @SqlResultSetMapping을 이용한 방법의 단점은 DTO를 만들고 생성자 또한 만드는 작업이 매우 귀찮으며, 결국에는 영속성에 의존한다는 점입니다. (@Entity 클래스에 선언해야 함)

 

귀찮은 작업이 두 가지나 있는데, 불가피 하게 귀찮은 작업을 해야 한다면 두가지 보다 한 가지만 하는 게 낫겠죠?

그래서 나온 게 QLRM이라는 라이브러리입니다.

 

QLRM을 이용하면 DTO 생성 및 생성자만 만들어주면 됩니다.

1. Dependency 추가 

	compile 'org.qlrm:qlrm:2.0.2'

2. 내가 이용하고 싶은 DTO를 만든다. ( 생성자도 만들어 줘야 함 ) 

@Data
public class RecommandPostList {
	
	private BigInteger postId;
	private BigInteger userId;
	private Integer phoneNumber;
	private Date registerTime;
	
	public RecommandPostList(
			BigInteger postId,
			BigInteger userId,
			Integer phoneNumber,
			Date registerTime
			) {
		this.postId = postId;
		this.userId = userId;
		this.phoneNumber = phoneNumber;
		this.registerTime = registerTime;
	}

}

3. 사용

@Service
public class DtoSampleService{

	@PersistenceContext
	EntityManager em;
    
    public List<RecommandPostList> getList() {
    	
        String query = "생략";
        
        JpaResultMapper result = new JpaResultMapper();
        Query query = em.createNativeQuery(q);
        List<RecommandPostList> list = result.list(query, RecommandPostList.class);
        return list;    
    }
}

다만 주의해야 할 점이 있습니다.

QLRM을 사용하기 위한 DTO 부분 보시면 Long이 아닌 BigInteger로 선언한거 보이시나요?

QLRM 라이브러리의 ClassGenerator.class를 보시면 DB의 Data Type을 가져오는거 같습니다. 그리고 내부 클래스를 통해 Java Primitive Type으로 변환을 시켜주더라고요.

 

다만 Mysql Point 타입 같은거는 지원을 안해줘서 이러한 타입들을 이용하신다면 @SqlResultSetMapping를 이용해야 합니다.

 

그럼 이만~!

 

참고 및 출처

 

QLRM

https://github.com/72services/qlrm

 

EntityManager

https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#createNativeQuery-java.lang.String-

 

example 

https://www.programcreek.com/java-api-examples/?class=javax.persistence.EntityManager&method=createNativeQuery

반응형

'BackEnd > Java' 카테고리의 다른 글

pm2 java  (0) 2019.09.24
Log4j2 날짜별 폴더 생성 & Level별 로그 생성  (2) 2019.09.04
Spring boot AWS S3를 이용한 File Upload/Download  (1) 2019.08.26
Java send HTTP request  (0) 2019.04.02
Spring boot + Mybatis 연결하기  (0) 2019.03.26
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함