8. 게시판 글목록보기v2

송민경's avatar
Mar 13, 2024
8. 게시판 글목록보기v2

1. JPQL(Java Persistence Query Language)

Java Persistence API(JPA)에서 사용되는 쿼리 언어입니다. JPQL은 엔티티 객체를 대상으로 쿼리를 작성하고 실행하는데 사용됩니다. JPQL은 SQL과 비슷하지만 테이블이 아닌 엔티티 객체에 대해 작동합니다.
JPQL의 기본 구문은 다음과 같습니다:
SELECT [DISTINCT] select_expression FROM entity_name [AS] identification_variable [WHERE where_condition] [GROUP BY {grouping_expression [[,] grouping_expression]*}] [HAVING having_condition] [ORDER BY {order_by_expression | entity_name.attribute_name} [ASC | DESC] [, ...]]
  1. SELECT: 쿼리 결과에 반환할 열을 지정합니다. 한 번에 하나 이상의 열을 지정할 수 있습니다. 예를 들어, SELECT name, age는 "name"과 "age" 열을 선택합니다.
  1. DISTINCT: SELECT 문에 사용되며, 중복된 행을 제거합니다. 쿼리 결과에서 고유한 값만 반환됩니다.
  1. FROM: 쿼리의 대상이 되는 엔티티나 테이블을 지정합니다. 즉, 데이터를 검색할 데이터 소스를 지정합니다.
  1. AS: 엔티티나 테이블에 대한 별칭을 지정합니다. 별칭은 테이블이나 엔티티의 짧은 이름으로 사용되며, 쿼리 내에서 더 간결하게 참조할 수 있습니다.
  1. WHERE: 쿼리 결과에 대한 필터링 조건을 지정합니다. WHERE 절은 선택 사항이며, 지정된 조건에 해당하는 행만 결과에 포함됩니다.
  1. GROUP BY: 그룹화할 기준을 지정합니다. 그룹화된 결과를 생성하고, 집계 함수를 사용하여 각 그룹에 대한 계산을 수행할 수 있습니다.
  1. HAVING: GROUP BY 절과 함께 사용되며, 그룹화된 결과에 대한 필터링 조건을 지정합니다. WHERE 절은 개별 행에 대한 조건을 지정하는 반면, HAVING 절은 그룹 전체에 대한 조건을 지정합니다.
  1. ORDER BY: 쿼리 결과의 정렬 순서를 지정합니다. ASC(오름차순) 또는 DESC(내림차순)으로 지정할 수 있으며, 기본적으로 오름차순으로 정렬됩니다.
예를 들어, 다음은 JPQL의 간단한 쿼리입니다:
sqlCopy code SELECT e FROM Employee e WHERE e.department = :dept // 클래스 : Employee // 레퍼런스 변수 : e
이 쿼리는 "Employee" 엔티티에서 "department" 속성이 특정 부서와 일치하는 모든 직원을 검색합니다.
JPQL은 매개변수 바인딩, 조인, 하위 쿼리 등 다양한 기능을 지원합니다. 또한 엔티티와 관련된 상속, 다형성 등을 고려하여 객체 지향적인 쿼리를 작성할 수 있도록 지원합니다.
JPQL에 대한 자세한 내용은 Java Persistence API (JPA) 및 JPQL 문서를 참조하시기 바랍니다.
 
SELECT u, g FROM User u JOIN u.group g
User 엔티티의 객체를 u로 참조, group 변수를 통해 연결된 정보를 가져옴
User 엔티티의 group 변수는 객체(오브젝트)를 참조하고 있음

1. BoardPersistRepository 에 findAll() 만들

  • 조회시 JPQL을 사용
package shop.mtcoding.blog.board; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import java.util.List; @RequiredArgsConstructor @Repository public class BoardPersistRepository { private final EntityManager em; public List<Board> findAll() { Query query = em.createQuery("select b from Board b order by b.id desc", Board.class); return query.getResultList(); } @Transactional public Board save(Board board) { // PC에 Data 주소 넣기(Entity만 가능함) em.persist(board); // 실행후 영속 객체가 됨 return board; } }
notion image
  • 단위 테시트하기
package shop.mtcoding.blog.Board; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; import shop.mtcoding.blog.board.Board; import shop.mtcoding.blog.board.BoardPersistRepository; import java.util.List; @Import(BoardPersistRepository.class) @DataJpaTest public class BoardPersistRepositoryTest { @Autowired //DI private BoardPersistRepository boardPersistRepository; @Test public void findAll_test() { //given - 지금은 넣을게 없음 //when List<Board> boardList = boardPersistRepository.findAll(); //then System.out.println("findAll_test/size : " + boardList.size()); System.out.println("findAll_test/username : " + boardList.get(2).getUsername()); //org.assertj.core.api Assertions.assertThat(boardList.size()).isEqualTo(4); Assertions.assertThat(boardList.get(2).getUsername()).isEqualTo("ssar"); } @Test public void save_test() { //given Board board = new Board("제목5","내용5","ssar"); //when boardPersistRepository.save(board); //then System.out.println(board); } }
notion image
 

2. BoardController 에 index() 수정하기

package shop.mtcoding.blog.board; import ch.qos.logback.core.model.Model; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import java.lang.annotation.Native; import java.util.List; @RequiredArgsConstructor @Controller public class BoardController { private final BoardNativeRepository boardNativeRepository; private final BoardPersistRepository boardPersistRepository; @PostMapping("/board/{id}/update") public String update(@PathVariable Integer id, String title, String content, String username){ boardNativeRepository.updateById(id, title, content, username); return "redirect:/board/"+id; } @GetMapping("/board/{id}/update-form") public String updateForm(@PathVariable (name="id") Integer id, HttpServletRequest request) { Board board = boardNativeRepository.findById(id); request.setAttribute("board", board); return "/board/update-form"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨 } @PostMapping("/board/{id}/delete") public String delete(@PathVariable Integer id) { // DTO 없이 구현 boardNativeRepository.deleteById(id); return "redirect:/"; } @GetMapping("/") public String index(HttpServletRequest request) { // 조회하기 List<Board> boardList = boardPersistRepository.findAll(); // 가방에 담기 request.setAttribute("boardList", boardList); return "index"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨 } @PostMapping("/board/save") public String save(BoardRequest.SaveDTO reqDTO) { // DTO 없이 구현 boardPersistRepository.save(reqDTO.toEntity()); return "redirect:/"; } @GetMapping("/board/save-form") public String saveForm() { return "board/save-form"; } @GetMapping("/board/{id}") public String detail(@PathVariable Integer id, HttpServletRequest request) { // Integer : 없으면 null, int : 0 Board board = boardNativeRepository.findById(id); request.setAttribute("board", board); return "board/detail"; } }
notion image
Share article

vosw1