일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- openapi3
- SWAGGER
- tasklet
- stopPropogation
- T-OTP
- Filter
- gradle
- preventdefault
- Spring REST Docs
- Flyway
- SpringRESTDocs
- REACT
- cloud native
- MSA
- Reduxpender
- vue
- MFA
- AuthenticatoinProvide
- Spring Batch
- cheerio
- UsernamePasswordAuthenticationFilter
- Crawling
- Spring Security
- JavaScript
- 리액트
- OpenStack
- axios
- vuejs
- Pender
- SpringBoot
- Today
- Total
Miracle Morning, LHWN
8-2. 프로젝트에서 JPA 직접 사용해보기 본문
DB 에 테이블 생성이 확인되면 Car 에 대한 클래스를 정의해준다.
이때
(1) @Table annotation 을 통해 어느 테이블과 매핑할지 설정한다.
(2) 식별자는 DB 에게 위임하기 위해 @GeneratedValue(strategy = GenerationType.IDENTITY) 로 설정한다.
(3) 제조사 하나에 여러 자동차가 있을 수 있기 때문에 Company 요소에 @ManyToOne annotation 을 설정한다.
(4) 승객수는 0명 일수도 있으니까 int 가 아닌 Wrapper class 인 Integer 로 설정한다.
(5) 모든 getter/setter 를 직접 설정해주기 번거로우니 lombok 을 사용하여 @Data annotation 을 설정한다.
Car.java
package com.springPractice.carInfo.domain;
import lombok.Data;
import javax.persistence.*;
@Entity
@Table(name="car")
@Data
public class Car {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 모델명
@Column(name="model_name")
private String modelName;
@ManyToOne
@JoinColumn(name="company_id")
private Company company;
@Column(name="passenger_capacity")
private Integer passengerCapacity;
@Column(name="created_at")
@Temporal(value=TemporalType.TIMESTAMP)
private Date createdAt;
@Column(name="updated_at")
@Temporal(value=TemporalType.TIMESTAMP)
private Date updatedAt;
}
이때 created_at 과 updated_at 은 다른 테이블과 중복될 여지가 많아 @MappedSuperClass 를 사용하여 코드 중복을 줄인다.
BaseEntity.java
package com.springPractice.carInfo.domain;
import lombok.Data;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.util.Date;
@MappedSuperclass
@Data
public abstract class BaseEntity {
@Temporal(value = TemporalType.TIMESTAMP)
private Date createdAt;
@Temporal(value = TemporalType.TIMESTAMP)
private Date updatedAt;
}
BaseEntity 를 만들어주었으니 Car 에서 BaseEntity 를 확장해준다.
Car.java
package com.springPractice.carInfo.domain;
import lombok.Data;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name="car")
@Data
public class Car extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 모델명
@Column(name="model_name")
private String modelName;
@ManyToOne
@JoinColumn(name="company_id")
private Company company;
@Column(name="passenger_capacity")
private Integer passengerCapacity;
}
이제 기본 화면 index.html 을 작성하는데, thymeleaf 를 사용한다.
Thymeleaf ?
Java 라이브러리로, Spring Boot 가 자동 설정을 지원하는 웹 텝플릿 엔진이다. HTML 문서에 HTML5 문법으로 서버 쪽 로직을 수행하고 적용시킬 수 있다. HTML 디자인에 전혀 영향을 미치지 않고 웹 템플릿 엔진을 통해 HTML 을 생성할 수 있다.
BasicController 에서는 "/" 경로에 들어왔을 때에는 index.html 페이지를 보여주도록 하고,
"/companyForm" 경로에 들어왔을 때에는 companyForm.html 페이지를,
"/saveCompany" 경로에 들어왔을 때에는 Service 의 saveCompanyInputDto 를 실행 후 index.html 로 돌아가게 한다.
BasicController.java
package com.springPractice.carInfo.controller;
import com.springPractice.carInfo.service.CompanyInputDTO;
import com.springPractice.carInfo.service.CompanyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/")
public class BasicController {
@Autowired
CompanyService companyService;
@RequestMapping("/")
public String index(Model model) {
return "index";
}
@RequestMapping("/companyForm")
public String companyForm(Model model) {
return "companyForm";
}
@RequestMapping("/saveCompany")
public String saveCompany(@ModelAttribute(name="companyInputDto") CompanyInputDTO companyInputDTO, Model model) {
companyService.saveCompanyImputDto(companyInputDTO);
return "index";
}
}
Service 에서는 Company 객체에 "companyInputDto 의 프로퍼티 + CreatedAt + UpdatedAt" 을 만들어 save 해준다.
CompanyService.java
package com.springPractice.carInfo.service;
import com.springPractice.carInfo.domain.Company;
import com.springPractice.carInfo.repository.CompanyRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.Date;
@Service
@Transactional
public class CompanyService {
@Autowired
CompanyRepository companyRepository;
@Transactional
public Company saveCompanyInputDto(CompanyInputDTO companyInputDto) {
Company company = new Company();
company.setCompanyName(companyInputDto.getCompanyName());
company.setCompanyNation(companyInputDto.getCompanyNation());
company.setCreatedAt(new Date());
company.setUpdatedAt(new Date());
return companyRepository.save(company);
}
public Company save(Company company) {
return companyRepository.save(company);
}
}
CompanyRepository 는 JpaRepository 를 상속받아 확장하는데, 이때 Generic 에는 Entity 와 Primary Key 의 타입을 넣어준다.
이로써 별도의 코드 작성 없이 Jpa 를 통해서 save 가 가능하게 된다.
CompanyRepository.java
package com.springPractice.carInfo.repository;
import com.springPractice.carInfo.domain.Company;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CompanyRepository extends JpaRepository<Company, Long> {
}
index.html 페이지에는 간단한 문구와 /companyForm 에 작성해놓은 등록 Form 으로 이동하는 Button 을 달아준다.
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>HELLO CAR!</h1>
<a href="./companyForm">Company Register</a>
</body>
</html>
companyForm 에는 Name, Nation 을 입력받는 항목과 submit 을 누르면 /saveCompany 로 이동될 수 있도록 한다.
companyForm.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>COMPANY FORM</h1>
<form method="POST" th:action="@{/saveCompany}"
th:object="${companyInputDto}">
<div class="form-group">
<label for="companyName">Company Name</label>
<input th:name="companyName"
id="companyName"
type="text"
class="form-control"
name="companyName" />
<label for="companyName">Company Nation</label>
<input th:name="companyNation"
id="companyNation"
type="text"
class="form-control"
name="companyNation" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">
REGISTER
</button>
</div>
</form>
</body>
</html>
그리고 서버가 구동될 때마다 테이블 내용 또한 초기화되어 없어지기 때문에 Construct 가 완료된 이후에 자동으로 메서드가 실행되도록
@PostConstruct annotation 을 통해 설정해준다.
AppInitializer.java
package com.springPractice.carInfo;
import com.springPractice.carInfo.domain.Company;
import com.springPractice.carInfo.service.CompanyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Date;
@Component
public class AppInitializer {
@Autowired
CompanyService companyService;
@PostConstruct
private void init() {
System.out.println("AppInitializer Start...");
Company company = new Company();
company.setUpdatedAt(new Date());
company.setCreatedAt(new Date());
company.setCompanyName("Ferrari");
company.setCompanyNation("Italy");
Company company2 = new Company();
company2.setUpdatedAt(new Date());
company2.setCreatedAt(new Date());
company2.setCompanyName("lamborghini");
company2.setCompanyNation("Italy");
Company company3 = new Company();
company3.setUpdatedAt(new Date());
company3.setCreatedAt(new Date());
company3.setCompanyName("BMW");
company3.setCompanyNation("Germany");
Company company4 = new Company();
company4.setUpdatedAt(new Date());
company4.setCreatedAt(new Date());
company4.setCompanyName("Hyundai");
company4.setCompanyNation("Korea");
companyService.save(company);
companyService.save(company2);
companyService.save(company3);
companyService.save(company4);
}
}
'IT 기술 > [JAVA] Spring Boot' 카테고리의 다른 글
10. JPA 를 사용한 페이징(Paging) 처리 (0) | 2021.05.11 |
---|---|
8-3. 프로젝트에서 JPA 직접 사용해보기 (0) | 2021.05.11 |
9. int 와 Integer 의 차이 (0) | 2021.05.10 |
8-1. 프로젝트에서 JPA 직접 사용해보기 (0) | 2021.05.08 |
7. 트랜잭션 (0) | 2021.05.07 |