Java ORM은 "Object-Relational Mapping"의 약자로, 객체 지향 프로그래밍 언어인 Java와 관계형 데이터베이스 사이의 데이터를 변환하고 연결하는 기술을 나타냅니다.
ORM은 데이터베이스의 테이블과 Java 프로그래밍 언어에서 사용하는 객체 간의 매핑을 자동화하고 단순화하는 방법을 제공합니다.
객체 지향 프로그래밍과 관계형 데이터베이스 간의 간극을 줄이기: 객체 지향 언어에서 작성된 코드를 사용하여 데이터베이스를 조작하고 관리할 수 있도록 합니다.
복잡한 SQL 쿼리 및 데이터베이스 접근 코드 작성 감소: ORM 프레임워크를 사용하면 SQL 쿼리를 직접 작성할 필요 없이 객체를 통해 데이터를 읽고 쓸 수 있으므로 코드 작성 및 유지 관리를 단순화합니다.
데이터베이스 독립성 제공: ORM은 특정 데이터베이스 시스템에 종속되지 않고 여러 데이터베이스 시스템과 호환될 수 있도록 해줍니다.
객체 간 관계 매핑: ORM은 객체 간의 관계를 효과적으로 매핑하여 객체 간의 연결을 관리하고 데이터베이스 테이블 간의 관계를 처리합니다.
이와 같은 특징을 고려하지 않고 작성한 코드입니다.
public List<ArticleDto> getAllArticle() {
List<ArticleDto> articleDtos = new ArrayList<>();
List<Object[]> articles = articleRepository.findByAllArticleAndLikes();
for (Object[] arr : articles) {
ArticleDto articleDto = new ArticleDto();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS");
Long id = arr[0] != null ? Long.valueOf(arr[0].toString()) : null;
String Type = arr[1] != null ? (String)arr[1] : null;
String contents = arr[2] != null ? (String)arr[2] : null;
String imgUrl = arr[3] != null ? (String)arr[3] : null;
Optional<String> regString = (arr[4] != null) ? Optional.of(arr[4].toString()) : Optional.empty();
Optional<LocalDateTime> regDate = regString.map(str -> str != null ? LocalDateTime.parse(str, formatter) : null);
boolean status = arr[5] != null ? (boolean)arr[5] : true;
String title = arr[6] != null ? (String)arr[6] : null;
Optional<String> updateString = (arr[7] != null) ? Optional.of(arr[7].toString()) : Optional.empty();
Optional<LocalDateTime> updateDate = updateString.map(str -> str != null ? LocalDateTime.parse(str, formatter) : null);
String vidUrl = arr[8] != null ? (String)arr[8] : null;
int viewCount = arr[9] != null ? (int)arr[9] : null;
BigInteger likeCount = arr[10] != null ? (BigInteger)arr[10] : null;
articleDto.setId(id);
articleDto.setArticleType(Type);
articleDto.setContents(contents);
articleDto.setImgUrl(imgUrl);
articleDto.setRegDate(regDate.orElse(null));
articleDto.setStatus(status);
articleDto.setTitle(title);
articleDto.setUpdateDate(updateDate.orElse(null));
articleDto.setVidUrl(vidUrl);
articleDto.setViewCount(viewCount);
articleDto.setLikeCounts(likeCount);
articleDtos.add(articleDto);
}
return articleDtos;
}
서비스 코드 입니다.
@Query(value = "SELECT a.article_id, " +
"a.article_type, " +
"a.contents, " +
"a.img_url, " +
"a.reg_date, " +
"a.status, " +
"a.title, " +
"a.update_date, " +
"a.vid_url, " +
"a.view_count, " +
"COUNT(CASE WHEN l.status = 1 THEN l.article ELSE NULL END) AS like_counts " +
"FROM Article a " +
"LEFT JOIN Likes l ON a.article_id = l.article " +
"GROUP BY a.article_id",nativeQuery = true)
List<Object[]> findByAllArticleAndLikes();
레포지토리 입니다.
이 코드는 게시판에 게시물들과 좋아요를 한꺼번에 불러오는 코드를 작성하기 위해서 쿼리문을 작성한 뒤 nativeQuery = true 속성을 주고 데이터를 전부 받아왔습니다.
이렇게 작성하게 되면 nullPointException을 일일히 잡아야되고 Date또한 파싱해줘야 하기 때문에 유지보수와 가독성이 저하되게 됩니다. 이와 같은 코드를 수정했습니다.
public List<ArticleDto> getAllArticle() {
List<ArticleDto> articleDtos = new ArrayList<>();
List<Article> articles = articleRepository.findAll();
for (Article article : articles) {
ArticleDto articleDto = new ArticleDto();
Long likeCount = likesRepository.countByArticle(article);
articleDto.setId(article.getId());
articleDto.setArticleType(article.getArticleType());
articleDto.setContents(article.getContents());
articleDto.setImgUrl(article.getImgUrl());
articleDto.setRegDate(article.getRegDate());
articleDto.setStatus(article.isStatus());
articleDto.setTitle(article.getTitle());
articleDto.setUpdateDate(article.getUpdateDate());
articleDto.setVidUrl(article.getVidUrl());
articleDto.setViewCount(article.getViewCount());
articleDto.setLikeCounts(likeCount);
articleDtos.add(articleDto);
}
return articleDtos;
}
서비스 코드 입니다.
Long countByArticle(Article article);
Likes 테이블에 레포지토리 입니다.
이처럼 기존 게시판 정보를 전부 조회하고 따로 Likes 레포지토리에 countByArticle만 추가하게 되면 보다 유지보수 및 가독성이 좋은 코드를 작성할 수 있습니다.