221101 Spring Boot - JPA

wonny·2022년 11월 1일
0

수업 복습

목록 보기
9/14

JPA 설명
https://ultrakain.gitbooks.io/jpa/content/chapter1/chapter1.3.html
https://dbjh.tistory.com/77

SpringBootJpaEx3


프로젝트 생성할 때 MySQL Driver, Spring Data JPA 추가

pom.xml - jpa 관련 dependency

		<!-- jaxb-runtime -->
		<dependency>
		    <groupId>org.glassfish.jaxb</groupId>
		    <artifactId>jaxb-runtime</artifactId>
		    <version>2.3.1</version>
		</dependency>
		
		<!-- jaxb-api -->
		<dependency>
		    <groupId>javax.xml.bind</groupId>
		    <artifactId>jaxb-api</artifactId>
		    <version>2.3.1</version>
		</dependency>

jpa 관련 dependency들을 https://mvnrepository.com/ 에서 복사해준다.

application.properties

#server
server.port=9002
#mysql_setting
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/sist?serverTimezone=Asia/Seoul
spring.datasource.username=dragon
spring.datasource.password=1234
#JPA_setting
#스키마 생성 create: 기존 테이블 삭제 후 생성, update: 변경된 부분만 반영
spring.jpa.hibernate.ddl-auto=update
#ddl 생성시 고유기능 사용할 지
spring.jpa.generate-ddl=true
#api 호출시 실행되는 sql문을 콘솔에 보여줄 것인지
spring.jpa.show-sql=true
#사용할 데이터베이스 종류
spring.jpa.database=mysql
#mysql 상세지정
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
#JSP_setting
spring.mvc.view.prefix=/WEB-INF/
spring.mvc.view.suffix=.jsp
spring.devtools.livereload.enabled=true

그리고 properties에 setting을 해준다.(나중에 .yml 써보면 더 편하다)

SpringBootJpaEx3Application.java

@SpringBootApplication
@ComponentScan({"mycar.*"})
public class SpringBootJpaEx3Application {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootJpaEx3Application.class, args);
	}

}

src/main/java에 mycar.data라는 패키지를 만들어서 @ComponentScan으로 패키지 등록을 해주었다.
이 다음엔 dto를 만들어보자. jpa에선 dto가 매우 중요하다.

MyCarDto.java

Dto에서 테이블을 생성한다.

package mycar.data;

import java.sql.Timestamp;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.CreationTimestamp;

import lombok.Data;

@Entity
@Table(name = "mycar") //mycar이라는 테이블에 mysql에 만들어진다
@Data
public class MyCarDto {

	@Id //각 엔티티 구별하도록 하는 식별 아이디(시퀀스)
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long num; //int보다 long을 많이 사용하는 편
	
	@Column(name = "carname")
	private String carname;
	
	@Column(name = "carprice")
	private int carprice;
	
	@Column(name = "carcolor")
	private String carcolor;
	
	@Column(name = "carguip") //이름을 그대로 하는 경우 (name="")을 생략해도 되긴 하지만 @Column은 필수
	private String carguip;
	
	@CreationTimestamp //엔티티가 생성되는 시점의 시간을 자동 등록
	@Column(updatable = false) //수정했을 때 이 컬럼은 수정하지 않겠다는 뜻, 이게 없으면 null값이 들어감
	private Timestamp guipday;
	
	
}
  • @Entity: 자동완성에서 org.hibernate.annotations(X) 말고 javax.persistence(O)를 선택해줘야 한다. 테이블을 만드는 하나의 대응 클래스라고 생각하면 된다.

  • @Table(name="mycar"): 이것도 javax.persistence로 선택, mycar라는 테이블이 db에 생성된다. (변수를 변경하는 경우 자동 수정됨)

  • @Data: lombok, setter+getter+toString

  • @Id: javax.persistence, private long num;이 시퀀스 역할을 할 수 있게 @Id를 준다. Hibernate으로 만들어질 예정

  • @GenerateVlue(strategy = GenerationType.AUTO): long num이 있는지 없는지에 따라 save가 insert인지 update인지를 구분해준다.

  • @Column(name="carname"): carname이라는 컬럼을 만든다는 뜻, dto와 컬럼명이 일치하는 경우 name을 생략해도 되지만 @Column은 필수

  • @CreationTimestamp: 엔티티가 생성되는 시점의 시간을 자동 등록

  • @Column(updatable = false): 수정했을 때 이 컬럼은 수정하지 않겠다는 뜻, 이게 없으면 null값이 들어감

dto를 다 작성했으면 main으로 다시 ㄱㄱ

SpringBootJpaEx3Application.java

import javax.persistence.Entity;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@ComponentScan({"mycar.*"})
@EntityScan("mycar.data")  //dto를 인식
@EnableJpaRepositories("mycar.data")  //dao 인식
public class SpringBootJpaEx3Application {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootJpaEx3Application.class, args);
	}

}
  • @EntityScan("mycar.data"): dto 인식
  • @EnableJpaRepositories("mycar.data"): dao 인식

(사실 테이블을 만드는 시점에선 @ComponentScan({"mycar.*"}), @EnableJpaRepositories("mycar.data") 이 두가지는 없어도 테이블 생성이 제대로 된다.)

MyCarInter.java

package mycar.data;

import org.springframework.data.jpa.repository.JpaRepository;

public interface MyCarInter extends JpaRepository<MyCarDto, Long>{

}

JpaRepository<T,ID>: T는 table 의미, ID는 Id의 type 의미
이렇게만 해주면 Interface 끝.

추가

MyCarDao.java

@Repository
public class MyCarDao {
	
    @Autowired
	MyCarInter carInter;
    
    //insert
	public void insertCar(MyCarDto dto) {
		carInter.save(dto); 
	}
	
}

save는 id타입 유무에 따라 자동으로 insert/update 구분

MyCarController.java

@Controller
public class MyCarController {

	@Autowired
	MyCarDao dao;
	
	// http://localhost:9002/carform -> addform.jsp 뜨게 하기
	@GetMapping("/carform")
	public String form() {
		
		return "mycar/addform";
	}
	
	//insert
	@PostMapping("/insert")
	public String add(@ModelAttribute MyCarDto dto) {
		dao.insertCar(dto);
		return "redirect:list";
	}

	//처음 시작할 때(루트), /list일 때 list.jsp 뜨게
	@GetMapping({"/","/list"})
	public ModelAndView list() {
		ModelAndView mview = new ModelAndView();
			
		return mview;
	}

addform.jsp

<body>
<form action="insert" method="post">
	<table class="table table-bordered" style="width: 400px;">
		<caption>차 정보 입력</caption>
		<tr>
			<th bgcolor="pink">차 종류</th>
			<td>
				<input type="text" name="carname" class="form-control" style="width: 200px;" required="required">
			</td>
		</tr>
		
		<tr>
			<th bgcolor="pink">차 가격</th>
			<td>
				<input type="text" name="carprice" class="form-control" style="width: 200px;" required="required">
			</td>
		</tr>
		
		<tr>
			<th bgcolor="pink">차 색상</th>
			<td>
				<input type="color" name="carcolor" class="form-control" style="width: 200px;" required="required">
			</td>
		</tr>
		
		<tr>
			<th bgcolor="pink">차 구입일</th>
			<td>
				<input type="date" name="carguip" class="form-control" style="width: 200px;" required="required">
			</td>
		</tr>
		
		
		<tr>
			<td colspan="2" align="center">
				<button type="submit">정보 입력</button>
				<button type="button" onclick="location.href='list'">목록으로</button>
			</td>
		</tr>
	</table>
</form>

전체 출력

MyCarDao.java

//전체 출력
	public List<MyCarDto> getAllList(){
		
		return carInter.findAll();
	
	}

MyCarController.java

@GetMapping({"/","/list"})
	public ModelAndView list() {
		ModelAndView mview = new ModelAndView();
			
		List<MyCarDto> list = dao.getAllList();
		
		//저장
		mview.addObject("list", list);
		mview.addObject("totalCount", list.size());
		
		mview.setViewName("mycar/list");
			
		return mview;
	}

list.jsp

<body>
<img alt="" src="icon05.png" style="width: 60px;">
<button type="button" onclick="location.href='carform'">차 등록</button>
<h3>차 목록</h3>
<h4>총 ${totalCount}대의 차가 등록되어 있습니다.</h4>

<table class="table table-bordered" style="width: 1000px;">
	<caption>자동차 정보</caption>
		<tr>
			<th width="60">번호</th>
			<th width="130">차종</th>
			<th width="80">색상</th>
			<th width="150">가격</th>
			<th width="180">구입일</th>
			<th width="180">등록일</th>			
			<th width="120">편집</th>
		</tr>
	
		<c:forEach var="dto" items="${list}" varStatus="i">
			<tr>
				<td>${i.count}</td>
				<td><a href='detail?num=${dto.num}'>${dto.carname }</a></td>
				<td><div class="box" style="background-color: ${dto.carcolor}"></div></td>
				<td><fmt:formatNumber value="${dto.carprice}"  type="currency"/></td>
				<td>${dto.carguip}</td>
				<td><fmt:formatDate value="${dto.guipday}" pattern="yyyy-MM-dd HH:mm"/></td>
				<td>
				<button type="button" onclick="location.href='updateform?num=${dto.num}'">수정</button>
				<button type="button" onclick="location.href='delete?num=${dto.num}'">삭제</button>
				</td>
			</tr>
			
			
		</c:forEach>
		
	
</table>
</body>

수정

수정하려면 수정 버튼을 눌렀을 때 updateform이 나와야 하고, 그 updateform에 내가 수정하고자 하는 데이터의 기존 값이 나와있어야 한다. 그리고 submit 했을 때 수정한 데이터로 db에 저장되어야 한다.

MyCarDao.java

	//num에 맞는 dto 출력
	public MyCarDto getData(Long num) {

		return carInter.getById(num);
	}
    
	//수정
	public void updateCar(MyCarDto dto) {
		carInter.save(dto); //insert와 같은 save지만 num이 포함되어 있으므로 수정으로 인식함
	}

insert와 같은 save지만 updateform에는 num이 있으므로 알아서 update임을 인식함

MyCarController.java

수정 버튼 눌렀을 때 수정폼으로 가고 수정폼에 기존 데이터 뜨게 하기

	//수정 버튼 누르면 updateform.jsp 뜨게+기존 데이터 나오게
	@GetMapping("/updateform")
	public String updateform(@RequestParam Long num, Model model) {
		
		MyCarDto dto = dao.getData(num);
		
		model.addAttribute("dto", dto);
		
		return "mycar/updateform";
	}
	
	//수정하기
	@PostMapping("/update")
	public String update(@ModelAttribute MyCarDto dto) {
		dao.updateCar(dto);
		
		return "redirect:list";
	}

updateform.jsp

addform.jsp를 복사하고
1. form의 action 수정
2. hidden으로 num값 넘기기
3. 각 input에 기존 데이터 value값으로 넣기
세가지를 해줘야 한다.

<body>
<form action="update" method="post">
	<input type="hidden" name="num" value="${dto.num}">
	<table class="table table-bordered" style="width: 500px;">
		<caption>차 정보 수정</caption>
		<tr>
			<th bgcolor="pink">차 종류</th>
			<td>
				<input type="text" name="carname" class="form-control" style="width: 200px;" value="${dto.carname }">
			</td>
		</tr>
		
		<tr>
			<th bgcolor="pink">차 가격</th>
			<td>
				<input type="text" name="carprice" class="form-control" style="width: 200px;" value="${dto.carprice }">
			</td>
		</tr>
		
		<tr>
			<th bgcolor="pink">차 색상</th>
			<td>
				<input type="color" name="carcolor" class="form-control" style="width: 200px;" value="${dto.carcolor}">
			</td>
		</tr>
		
		<tr>
			<th bgcolor="pink">차 구입일</th>
			<td>
				<input type="date" name="carguip" class="form-control" style="width: 200px;" value="${dto.carguip}">
			</td>
		</tr>
		
		
		<tr>
			<td colspan="2" align="center">
				<button type="submit">정보 수정</button>
				<button type="button" onclick="location.href='list'">목록으로</button>
			</td>
		</tr>
	</table>
</form>
</body>

삭제

MyCarDao.java

	//삭제
	public void deleteCar(Long num) {
		carInter.deleteById(num);
	}

MyCarController.java

	//삭제
	@GetMapping("/delete")
	public String delete(@RequestParam Long num) {
		dao.deleteCar(num);
		
		return "redirect:list";
	}

디테일 페이지

list.jsp

<td><a href='detail?num=${dto.num}'>${dto.carname }</a></td>

MyCarController.java

//디테일 페이지
	@GetMapping("/detail")
	public String detail(@RequestParam Long num, Model model) {
		
		MyCarDto dto = dao.getData(num);
		
		model.addAttribute("dto", dto);
		
		return "mycar/detailpage";
	}
profile
하다 보면 되겠지요..!

0개의 댓글