DB์ฐ๋
build.gradle
mariadb ์ jpa ๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ฏ๋ก ์ฃผ์์ฒ๋ฆฌ ํด๋์๋ jpa ๋ฅผ ์ฃผ์ ํด์ ํ๊ณ ์๋์ฒ๋ผ ์ ๋ ฅํ๋ค.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//jpa
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
//mariadb
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
}
์์ ํ gradle ์ refresh ํด์ค๋ค.
src/main/resources/application.properties
ํด๋น ๊ฒฝ๋ก์ properties ํ์ผ์ db ์ ์ ์ ๋ณด๋ฅผ ์ถ๊ฐํด์ค๋ค. ๊ฐ ์ค์ ์ ๋ณด๋ ์ฝ๋ ๋ฐ์ ์ ์ด๋์๋ค.
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3306/todolist
spring.datasource.username=root
spring.datasource.password=1234
#JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
- spring.jpa.hibernate.ddl-auto=update
- db์ ์์ฑ๋์ง ์์ ํ ์ด๋ธ, ์ปฌ๋ผ์ ์ถ๊ฐํ๋ค.
- spring.jpa.show-sql=true
- jpa ๊ฐ ๋ ๋ฆฌ๋ sql๋ฌธ์ ๋ณด์ฌ์ค๋ค
- spring.jpa.properties.hibernate.format_sql=true
- ๋ณด์ฌ์ฃผ๋ sql ๋ฌธ์ ๊น๋ํ๊ฒ ํฌ๋งคํ ํด์ค๋ค.
Entity ์์ฑ
/todo/model/TodoITem.java
๋ด์ฉ์ ์๋์ฒ๋ผ ์์ ํด์ค๋ค. @Entity ๋ ์๋ฐ ๊ฐ์ฒด๋ฅผ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ table ๊ณผ ๋งคํ์ํฌ ์ ์๋๋ก jpa์ entity ๋ก ์ ์ธํ๋ ์ด๋ ธํ ์ด์ ์ด๋ค. DB์ ํ ์ด๋ธ์ ์์ฑํ์ง ์์๋ JPA Hibernate ๊ฐ ์๋ ๋ด์ฉ์ ์ฐธ๊ณ ํด create ๋ฌธ์ ์คํํด์ค๋ค.
id ์ ํ์ ์ ๊ธฐ๋ณธ ๋ฐ์ดํฐ ํ์ long ์ด ์๋ ๋ํผ ํ์ ์ธ Long ์ผ๋ก ์ ์ธํ๋ ์ด์ ๋ null ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ค. auto_increment ๋ id ๊ฐ์ด ์์ ๋ ์๋์ผ๋ก ๋ฃ์ด์ฃผ๋ ์ต์ ์ธ๋ฐ, long ์ default ๊ฐ์ 0์ด๊ธฐ ๋๋ฌธ์ ๊ฐ์ด ์๋ค๊ณ ๋ณด๊ฒ ๋๋ค. Long ์ default ๊ฐ์ Null ๋ก ์ ํํ๊ฒ ๊ฐ์ด ์๋ค๊ณ ํ๋จํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋๋ก jpa ์์ pk ๋ Nullable ํ ๋ฐ์ดํฐ ํ์ ์ ์ฐ๋ ๊ฒ์ด ๊ถ์ฅ๋๋ค.
package com.todolist.tutorial.todo.model;
import lombok.*;
import javax.persistence.*;
@Entity //jpa entity ๋ก ์ ์ธ
@Table(name="todos") //table ์ ๋ณด
@Getter @Setter //getter, setter ๋ฉ์๋
@NoArgsConstructor //์ธ์ ์๋ ๊ธฐ๋ณธ ์์ฑ์
@AllArgsConstructor //๋ชจ๋ ์ธ์ ๊ฐ์ง๋ ์์ฑ์
@Builder //๋น๋ ํจํด์ผ๋ก ์์ฑํ๊ฒ ํด์ค.
public class TodoItem {
@Id //pk ํ๋. ๋ฐ๋์ ํ์,
@Column(name="id", nullable = false) //ํ
์ด๋ธ ์ปฌ๋ผ๊ณผ ๋งคํ
@GeneratedValue(strategy = GenerationType.IDENTITY) //auto increment
private Long id;
@Column(name="title", nullable = false, length = 100)
private String title;
@Column(name="done", nullable = false)
private boolean done;
}
Repository ์์ฑ
/todo/model/TodoItemRepository.interface
JpaRepository ์ ๋ฉ์๋๋ฅผ ์์๋ฐ๋ ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ ๋ค. ๋ชธ์ฒด๋ฅผ ์ง์ ๊ตฌํํ์ง ์์๋, Hibernate ๊ฐ ์๋์ผ๋ก ๋ง๋ค์ด์ฃผ๋ฏ๋ก ์ด ํ ์ค์ด๋ฉด ๋๋ค.
package com.todolist.tutorial.todo.model;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TodoItemRepository extends JpaRepository<TodoItem, Long> {
}
๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณต๋๋ Jpa ๋ฉ์๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
method | return | description |
findAll() | List<T> | search |
findById | Optinal<T> | search |
deleteById(T id) | void | delete |
save(T entity) | T | insert, update |
Service ์ Repository ์ถ๊ฐ
/todo/TodoItemService.java
์๋น์ค์ ์์์ ๋ง๋ Repository ๋ฅผ ์ถ๊ฐํ์ฌ ์๋์ ๊ฐ์ด ๋ด์ฉ์ ๋ณ๊ฒฝํ์. ์ฐธ๊ณ ๋ก, getById() ๋ Optional ์ ๋ฐํํ๋ฏ๋ก orElseThrow() ๋ฅผ ๋ถ์ฌ์ฃผ์๋ค. ์ด์ ์ ์๋น์ค ์ธ์คํด์ค๋ฅผ ์ปจํธ๋กค๋ฌ์ ์ถ๊ฐํ ๋์ ๋ง์ฐฌ๊ฐ์ง๋ก, Repository ์ ์์กด์ฑ์ ์๋์ผ๋ก ์ฃผ์ ๋ฐ๊ธฐ ์ํด @Autowired ์ด๋ ธํ ์ด์ ์ ๋ถ์ฌ์ฃผ์๋ค.
Optional ๊ฐ์ฒด๋ NullPointerException ๋ฅผ ์์ฝ๊ฒ ์ฒ๋ฆฌํ๊ธฐ ์ํด T ํ์ ์ ๊ฐ์ฒด๋ค์ ๊ฐ์ธ์ฃผ๋ Wrapper ํด๋์ค๋ค. ๋ณต์กํ ์กฐ๊ฑด๋ฌธ ์์ด orElsethrow ๋ฉ์๋ ๋ฑ์ผ๋ก null exception ์ ์ฒ๋ฆฌํ ์ ์๋ค.
package com.todolist.tutorial.todo;
import com.todolist.tutorial.todo.model.TodoItem;
import com.todolist.tutorial.todo.model.TodoItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TodoItemService {
@Autowired
private TodoItemRepository todoRepo;
public List<TodoItem> getTodos() {
List<TodoItem> todos = todoRepo.findAll();
if(!todos.isEmpty()) return todoRepo.findAll();
else throw new IllegalArgumentException("no such data");
}
public TodoItem getTodoById(final Long id) {
return todoRepo.findById(id).orElseThrow(()-> new IllegalArgumentException("no such data"));
}
public TodoItem createTodo(final TodoItem createTodoItem) {
if(createTodoItem == null) throw new IllegalArgumentException("todo item cannot be null");
return todoRepo.save(createTodoItem);
}
public TodoItem updateTodo(final long id, final TodoItem updateTodoItem) {
TodoItem todoItem = getTodoById(id);
todoItem.setTitle(updateTodoItem.getTitle());
todoItem.setDone(updateTodoItem.isDone());
return todoRepo.save(todoItem);
}
public void deleteTodoById(final Long id) {
todoRepo.deleteById(id);
}
}