본문 바로가기

Spring

240314 스프링 부트

https://docs.jboss.org/hibernate/orm/5.6/javadocs/org/hibernate/dialect/package-summary.html

 

org.hibernate.dialect (Hibernate JavaDocs)

An SQL dialect for MariaDB 10.3 and later, provides sequence support, lock-timeouts, etc.

docs.jboss.org

 

다시 한번 JPA 설정을 해보자

스프링 프로젝트 새로 생성, Controller, Service, Repository, Entity 생성하기

@Controller
public class BoardController {
	// 서비스 -> Service
	// DAO -> Repository
	// DTO -> Entity
	
	@Autowired
	private BoardService boardService;
	
	@GetMapping("/")
	public String index() {
		return "redirect:/board";
	}
	
	@GetMapping("/board")
	public String board() {
		return "board";
	}
}

@Service
public class BoardService {
	@Autowired
	private BoardRepository boardRepository;
}

// Repository
public interface BoardRepository extends JpaRepository<JPABoard, Integer> {
}

@Entity
@Getter
@Setter
public class JPABoard {
	// JPA 에서 주의해야할 점
	// 언더바, 언더스코어 "_" 를 못 씀, 인식 오류
	
	@Id // PK 설정
	@GeneratedValue(strategy = GenerationType.IDENTITY) // Auto_increment 설정
	private int jbno;
	
	// Column 의 도메인을 지정할 수 있음 (도메인 : 해당 칼럼의 제약 조건)
	@Column(columnDefinition = "TEXT")
	private String jbtitle;
	
	@Column(columnDefinition = "LONGTEXT")
	private String jbcontent;
	
	// Column 의 기본 값 설정, 여기서는 행이 삽입될 때의 시간을 입력
	@ColumnDefault("CURRENT_TIMESTAMP")
	private LocalDateTime jbdate = LocalDateTime.now();
	
	@ColumnDefault("0")
	private int jblike;
	
	@ColumnDefault("1")
	private int jbread;
}

 

여기서 테이블이 없는 상태로 서버 실행 시 자동으로 테이블을 생성해 줌

지정한 조건들로 테이블이 생성된 모습

데이터 출력해보기

Controller, Service, Repository 연결하기

// Controller
List<JPABoard> list = boardService.boardList();

// Service
public List<JPABoard> boardList() {
  return boardRepository.findAll();
}

// Repository

 

Repository 는 할 것이 없음, Controller 에서 Model 로 넘기기

임시로 넣어 둔 데이터들이 잘 보이는 모습

 

title 클릭 시 detail 로 연결해보기

두가지 방법으로 링크할 수 있음
<td th:onclick="|location.href='@{detail(no=${j.jbno})}'|" th:text="${j.jbtitle}"></td>
<td><a th:text="${j.jbtitle}" th:href="@{detail(no=${j.jbno})}"></a></td>

 

Detail 창을 열어보자

DB 에서 모든 값을 받아오는 것이 아닌 하나만 가져오기

// Controller
@GetMapping("/detail")
  public String detail(@RequestParam("no") int no, Model model) {
    JPABoard detail = boardService.detail(no);
    model.addAttribute("detail", detail);
    return "detail";
  }

 

BoardService 에서 값 받기

원래 JpaRepository 에 있는 findById() 를 이용하면 Optional 로 객체를 받아야 하기 때문에

BoardRepository 에 findByJbno() 라는 메소드를 추가 생성

findBy + 찾고 싶은 칼럼명을 입력하면 해당 칼럼을 기준으로 해서 값을 찾음

// Service
public JPABoard detail(int no) {
  // Optional<JPABoard> detail = boardRepository.findById(no);
  JPABoard detail = boardRepository.findByJbno(no);
  return detail;
}

// Repository
JPABoard findByJbno(int no);

 

값이 정상 출력되는 모습을 확인할 수 있음, SQL 은 자동으로 실행됨

자동으로 jbno 를 기준으로 검색하는 모습

 

글 작성하기

write.html 생성

<form action="/write" method="post">
  <input type="text" name="jbtitle"/>
  <textarea name="jbcontent"></textarea>
  <button type="submit">작성</button>
</form>

 

Controller 에 Get, Post 다 생성하기

@GetMapping("/write")
public String write() {
  return "write";
}
	
@PostMapping("/write")
public String write(@RequestParam Map<String, Object> map) {
  JPABoard board = new JPABoard();
  board.setJbtitle((String)map.get("jbtitle"));
  board.setJbcontent((String)map.get("jbcontent"));
  boardService.write(board);
  return "redirect:/board";
}

 

BoardService 에 값 저장 넘기기

public void write(JPABoard board) {
  boardRepository.save(board);
}

 

==> 실제 저장된 값 확인해보기

jbread 값의 default 는 1 로 설정했는데, 0 으로 저장된 모습

 

JPABoard 객체를 새로 만들었기 때문에 초기 값으로 모든 값이 세팅됨

 

실제 적용되는 쿼리문

모든 칼럼에 값이 다 들어감

 

JPABoard, Entity 에 객체 생성 시 기본 값을 대입하면 해결할 수 있음

@ColumnDefault("0")
private int jblike = 1;
	
@ColumnDefault("1")
private int jbread = 1;

 

글 삭제하기

detail.html 에 삭제 버튼 추가하기

<h1>DETAIL</h1>
<h3 th:text="${detail.jbtitle}"></h3>
<button th:onclick="|location.href='@{postDel(no=${detail.jbno})}'|">삭제</button>

 

Controller 에서 값을 받아 넘기기

@GetMapping("/postDel")
public String postDel(@RequestParam("no") int no) {
  // 첫 번째 방법
  boardService.postDel(no);
  
  // 두 번째 방법
  JPABoard board = new JPABoard();
  board.setJbno(no);
  boardService.postDel2(board);
  return "redirect:/board";
}

 

Controller 에서 값을 넘기는 2가지 방법으로 삭제할 수 있음

하나는 PK 의 value 값만 받아서 삭제하는 방법과 객체를 넘겨 삭제하는 방법

여기서는 둘 다 jbno 값만 넘겨 쿼리문은 동일하게 작동

public void postDel(int no) {
  boardRepository.deleteById(no);
}

public void postDel2(JPABoard board) {
  boardRepository.delete(board);
}

 

조건에 jbno 만 들어간 모습

 

글 수정하기

detail.html 에 update 버튼 추가

<button th:onclick="|location.href='@{update(no=${detail.jbno})}'|">수수정</button>

 

GetMapping 으로 받기

@GetMapping("/update")
public String update(@RequestParam("no") int no, Model model) {
  JPABoard detail = boardService.detail(no);
  model.addAttribute("detail", detail);
  return "write";
}

 

update.html 을 만들어서 편하게 해도 되지만

하나의 write.html 을 가지고 사용해보았지만.. 그냥 따로 html 만드는게 편한 것 같음

<th:block th:if="${detail ne null}">
  <form action="/update" method="post">
</th:block>
<th:block th:unless="${detail ne null}">
  <form action="/write" method="post">
</th:block>
  <th:block th:if="${detail ne null}">
    <input type="text" name="jbtitle" th:value="${detail.jbtitle}"/>	
  </th:block>
  <th:block th:unless="${detail ne null}">
    <input type="text" name="jbtitle"/>
  </th:block>	
  <textarea name="jbcontent"><th:block th:if="${detail ne null}">[(${detail.jbcontent})]</th:block></textarea>
  <th:block th:if="${detail ne null}">
    <input type="hidden" name="jbno" th:value="${detail.jbno}"/>	
  </th:block>
  <button type="submit">작성</button>
</form>

 

Post 로 값 받기

@PostMapping("/update")
public String update(@RequestParam("jbtitle") String jbtitle,
                      @RequestParam("jbcontent") String jbcontent,
                      @RequestParam("jbno") int jbno) {
  JPABoard post = new JPABoard();
  post.setJbtitle(jbtitle);
  post.setJbcontent(jbcontent);
  post.setJbno(jbno);
  boardService.update(post);
		
  return "redirect:/detail?no=" + jbno;
}

 

Service 에서 update 하기, save 는 PK 가 없으면 insert, PK 가 있으면 update 로 진행됨

public void update(JPABoard post) {
  boardRepository.save(post);
}

 

Board 에서 역순으로 정렬해보기

BoardService 에서 메소드 하나 생성하기

// 기존 findAll() 을 findAllByOrderByJbnoDesc() 로 변경
public List<JPABoard> boardList() {
  // return boardRepository.findAll();
  return boardRepository.findAllByOrderByJbnoDesc();
}

==> BoardRepository 에서 메소드 생성, JPA 에서 메소드 이름을 인식하여 자동 생성함
List<JPABoard> findAllByOrderByJbnoDesc();

 

직접 Query 써보기

@Query(value = "SELECT * FROM jpaboard j where j.jbno=?1", nativeQuery = true)
JPABoard findByJbno(int no);

==> ?1 의 뜻은 해당 물음표에 첫 번째 파라미터 값을 넣는다는 뜻

 

Join 걸어보기

 

JPA @OneToMany, @ManyToOne으로 연관관계 관리하기

안녕하세요, 오늘은 스프링을 이용하면서 자주 쓰는 JPA에 대해서 이야기해보려고 합니다. JPA는 스프링 개발을 하면서 이제 거의 필수가 된 ORM 기술입니다. @OneToMany, @ManyToOne 어노테이션은 1:N, N:1

velog.io

 

JPABoard 에 아래 어노테이션 추가

@ManyToOne
@JoinColumn
private JPAMember jpaMember;

 

하면 JPABoard 에서 JPAMember 의 PK 값을 참조

 

/write 의 Post 수정해보기

@PostMapping("/write")
public String write(@RequestParam Map<String, Object> map) {
  JPABoard board = new JPABoard();
  board.setJbtitle((String)map.get("jbtitle"));
  board.setJbcontent((String)map.get("jbcontent"));
		
  JPAMember member = new JPAMember();
  // 우리가 알고 있는 것은 세션에 등록된 mid 이므로, member 객체에 세팅 후 추가
  member = boardService.findByJmid("1234");
  board.setJpaMember(member);
		
  boardService.write(board);
  return "redirect:/board";
}

 

jmno 가 1번인 객체가 들어가는 모습을 볼 수 있다

 

board 테이블의 값 확인해보기

마지막으로 쓴 글의 jmno 값이 1 인 모습

 

게시글 목록에서 작성자 출력하기

==> JPABoard 객체에 JPAMember 객체가 담겨져 List 로 들어감
List<JPABoard> list = boardService.boardList();
model.addAttribute("list", list);
==> 객체의 jpaMember 객체의 jmname 을 열어서 조회 가능
<td th:text="${j.jpaMember.jmname}"></td>

다른 테이블의 속성값도 볼 수 있다

 

'Spring' 카테고리의 다른 글

Log 찍기  (0) 2024.07.17
240315 도커  (0) 2024.03.15
240313 스프링 부트  (1) 2024.03.13
240312 스프링 부트  (0) 2024.03.12
240311 스프링 부트  (0) 2024.03.11