오늘은 Spring Data Jpa
를 사용해서 간단한 유정정보에 대한 CRUD
를 처리하는 RestApi
를 만들어 보도록 하겠습니다.
Rest Api를 만들면서 배운 내용들을 복습하는 느낌으로 정리 하였기 때문에
내용이 번잡하거나 길수 있습니다.
Database 는 H2 Database
를 사용 하도록 하겠습니다 !
h2 설정
URL 과 name 을 이렇게 사용하도록 하겠습니다, password 는 따로 사용하지 않겠습니다.
Spring 에서 h2 Database에 접근할수 있도록 properties 를 설정 해주겠습니다.
application.properties
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
간단하게 이름(name), 나이(age) 정보를 가지는 Table를 생성 합니다.
Create Table User ( id int(5) PRIMARY KEY AUTO_INCREMENT, name varchar(10), age int(2))
@Entity
@Table
@Column
같은 Annotation 을 사용합니다.h2 에서 생성한 Table 을 바탕으로 Entity Class를 생성 하도록 하겠습니다.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "name")
private String name;
private int age;
/*
Getter, Setter
*/
}
Entity 클래스 에서 사용되는 Annotation 에 대해서 알아 보겠습니다.
@Entity
클래스를 Entity 클래스 역할을 하기 위해서 @Entity 를 붙여줘야 합니다.
해당 클래스 이름으로 DB 의 테이블명에 자동으로 매핑 됩니다.
만약, 다른 테이블에 매핑하고 싶으면 @Entity(name="테이블명") 을 지정해주면 원하는 테이블에 매핑 가능합니다.
@Id
DB 테이블에 식별자 역할(Key)을 하는 컬럼에 매핑 됩니다.
Java 의 Primitive 타입과 wrapper 타입 모두 사용 할 수 있습니다.
@GenerateValue
Id (Key)
의 자동 생성전략 을 설정해주는 Annotation 입니다.
속성으로 strategy(생성 전략) 과 generator(생성기) 가 존재합니다.
strategy 는 Default 값은 AUTO 이며 JPA 제공하는 4가지 방법이 존재합니다.
1. AUTO : DB에 맞게 자동 선택
2. IDENTITY : DB의 identity 컬럼을 이용
3. SEQUENCE : DB의 시퀀스 컬럼을 이용
4. TABLE : 유일성이 보장된 데이터베이스 테이블을 이용
@Column
해당 멤버가 DB 의 테이블명에 매핑됩니다. 기본적으로 Entity 클래스의 변수는 @Column
어노테이션이 부착되어 있습니다.
(name ="column명")
을 사용하여 원하는 컬럼과 매핑 가능합니다.
unique, nullable , length 등 다양한 속성을 통해서 제약조건을 설정 할 수 있습니다.
@Temporal
시간, 날짜 타입으로 매핑하기 위해 사용합니다.
@Transient
해당 변수를 DB의 컬럼에 매핑하지 않는 변수로 사용합니다.
이제 Entity 클래스를 생성하였으니, Repository 를 생성 해보도록 하겠습니다.
실제로 DB 와 소통하고 접근하는 객채를 말합니다. Service 와 DB 사이의 연결고리를 하는 역할입니다 !
DAO ( Data Access Object) 같은 역할을 하게 됩니다.
Spring Data Jpa
를 사용하기 위해서 JpaRepository
를 만들어서 사용 하겠습니다.
JpaRepository 는 interface 형식으로 제공됩니다.
JpaRepository 를 사용하게되면 간단한 CRUD 작업은 쿼리문 생성없이 간편하게 사용 할 수 있습니다. 메소드 이름 형식으로 쿼리를 생성해 사용하게 됩니다.
JpaRepository 를 사용하기 위해
public interface 'Repository명' extends JpaRepository <엔티티, ID 타입>
interface 를 생성합니다.
public interface JpaUserRepository extends JpaRepository<User, Long> {
@Override // Create, Update
User save(User user);
@Override // Read
Optional<User> findById(Long id);
@Override // Delete
void deleteById(Long id);
}
메소드 이름 형식으로 메소드 이름 만으로도 손쉽게 CRUD 기능을 만들 수 있습니다.
findByIdAndName
형식 처럼 And
와 Or
연산자도 사용 가능합니다.
반환값으로 save() 메소드는 Entity를 findBy() 메소드는 List< Entity>, Optional<> 형식으로 반환해주고 있습니다.
Service
는 Business Logic 이 담긴, Repository
가 DB 에서 받아온 데이터들을 실질적 으로 가공하는 곳 입니다.
@Service
어노테이션을 통해 클래스를 Service 로 등록하여 사용합니다.
@Service
public class UserService {
private JpaUserRepository jpaUserRepository;
@Autowired // Constructor 를 사용한 Autowired
public UserService(JpaUserRepository jpaUserRepository) {
this.jpaUserRepository = jpaUserRepository;
}
public User create(User user) {
return jpaUserRepository.save(user);
}
public Optional<User> read(Long id) {
return jpaUserRepository.findById(id);
}
public User update(Long id,int age) {
User user = read(id).get();
user.setAge(age);
return jpaUserRepository.save(user);
}
public void delete(Long id) {
jpaUserRepository.deleteById(id);
}
}
@Autowired
를 통해서 Repository
를 의존성 주입(Di) 해주었습니다.
Spring 4.3 부터는 생성자가 1개일 경우 생략 가능합니다.
요청되는 Url 에 따라서 View 을 반환하거나 Data 를 반환해주는 응답을 해주는 역할을 하게됩니다.
전통적인 Spring MVC 패턴에서는 @Controller
를 통해서 view 를 응답하고, Restful Api로 사용될때는 @RestController
를 통해서 Response Body를 생성해 응답해 줍니다.
Rest Api로 사용 하기 때문에 @RestController 를 이용하도록 하겠습니다.
@CrossOrigin (origins = "http://localhost:3000")
@RestController
@RequestMapping("/user")
public class UserController {
private final UserService userService;
@Autowired // Constructor 를 통한 Di
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("/create")
public ResponseEntity<User> create(@RequestBody User user) {
return ResponseEntity.ok()
.body(userService.create(user));
}
@GetMapping("/read/{id}")
public ResponseEntity<User> read(@PathVariable Long id) {
return ResponseEntity.ok()
.body(userService.read(id).get());
}
@PutMapping("/update")
public ResponseEntity<User> read(@RequestParam Long id, @RequestParam int age) {
return ResponseEntity.ok()
.body(userService.update(id,age));
}
@DeleteMapping("/delete/{id}")
public void delete(@PathVariable Long id) {
userService.delete(id);
}
}
@CrossOrigin (origins ="http://localhost:3000")
프론트엔드 , 백엔드 서버가 분리 되어있기 때문에 CORS 문제가 발 생하게 됩니다. 정상으로 통신하기 위해서 @CrossOrigin
어노테이션을 통해 해당 도메인에서 접근을 허용해줍니다.
@RestController
Spring 에서 Controller 를 지정해줄때 @Controller
, @RestController
를 사용하게 됩니다.
Spring MVC 패턴에 서는 @Controller
를 사용한 View 응답이 주로 사용됩니다.
Restful api 에서는 @RequestMapping
이 @ResponseBody
를 포함한 @RestController
를 사용하게 됩 니다.
@RequestMapping
HTTP Request 로 들어오는 Url 요청을 특정 Method 와 Class 에 매핑 시켜주는 역할을 합니다. Class Level 로@RequestMapping("/user")
을 해주면 /user
경로로 요청이 들어오면 해당 클래스를 매핑시켜 줍니다.
@GetMapping
@PostMapping
@RequestMapping
은 기본적으로 모든 Method 방식을 지원합니다.
Method 방식을 Get, Post 로 사용하는것이 @GetMapping
@PostMapping
입니다.
@PathVariable
Url 요청 경로에 변수를 담아서 요청 받을때 사용하게 됩니다.
@PathVariable
으로 선언된 변수명을 통해서 해당 값을 읽어오게 됩니다.
@RequestParam
Http 에서 Parameter 로 넘어오는 값을 받아 올 수 있습니다.
@RequestParam
으로 선언된 변수명을 통해서 해당 값을 읽어오게 됩니다.
생성한 Service 를 @Bean 등록을 하겠습니다.
public class SpringConfig {
private final JpaUserRepository jpaUserRepository;
//DI 해주기 외부에서 jpaUserRepository 넣어주기
@Autowired
public SpringConfig(JpaUserRepository jpaUserRepository) {
this.jpaUserRepository = jpaUserRepository;
}
@Bean
public UserService userService() {
return new UserService(jpaUserRepository);
}
}
React 에서 Controller 에 등록한 해당 Url로 요청을 하게 되면 동작하는 것을 확인 할 수 있습니다.
정상적으로 Data가 DB 에 등록하는 것을 알 수 있습니다.
정상적으로 DB 에 등록된 Data를 읽어 오는걸 알 수 있습니다.
정상적으로 DB 에 등록된 Data를 수정 하는걸 알 수 있습니다.
정상적으로 DB 에 등록된 Data를 삭제 하는걸 알 수 있습니다.