본문 바로가기
개발/Kotlin

[Kotlin] 코틀린 + 스프링부트 + JPA 사용해보기

by devhooney 2022. 12. 2.
728x90

코틀린 + 스프링부트 + JPA 사용해보기

 

코틀린과 스프링부트 JPA를 사용해서

기본적인 Create, Read를 만들어보았다.

 

 

728x90

 

 

1. 프로젝트 생성

 

코틀린, gradle-kotlin 선택하고 java도 11로 선택 후 다음 선택

 

 

 

라이브러리 선택

Thymeleaf는 넣어도되고 빼도 된다.

 

 

2. 컨트롤러

@Controller
class TodoController {

    @GetMapping("/")
    fun home(model: Model): String {
        model["title"] = "Todo List"
        return "todo"
    }
}

화면은 Controller에서 만들어준다.

 

 

- RestController

@RestController
@RequestMapping("/api/v1")
class TodoRestController (private val todoService: TodoService) {

    @GetMapping("/todo")
    fun selectTodo(): List<Todo> {
        return todoService.selectTodo()
    }

    @PostMapping("/todo")
    fun insertTodo(@RequestBody todoDto: TodoDto): Int {
        return todoService.insertTodo(todoDto)
    }
}

데이터는 restController에서 조회하고 넣어준다.

 

 

 

 

3. 서비스

@Service
class TodoService @Autowired constructor (
    val todoRepository: TodoRepository,
    val modelMapper: ModelMapper) {

    fun selectTodo(): List<Todo> {
        return todoRepository.findAll()
    }

    @Transactional
    fun insertTodo(todoDto: TodoDto): Int {
        val save = todoRepository.save(modelMapper.map(todoDto, Todo::class.java))
        return save.id
    }

}

modelMapper를 통해서 타입을 Dto에서 Entity로 바꿔준다.

 

 

4. 엔티티, 리포지토리

@Entity
data class Todo (
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Int,
    var title: String,
    var content: String,
    var writer: String
)

 

- Repository

@Repository
interface TodoRepository: JpaRepository<Todo, Int> {

}

 

 

5. DTO 

data class TodoDto (
    var title: String,
    var content: String,
    var writer: String
)

 

 

6. 화면 생성

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="https://unpkg.com/mvp.css@1.12/mvp.css">
    <script th:src="@{/js/todo.js}"></script>
    <title th:text="${title}">title</title>
</head>
<body>
<button id="insert">Todo 추가</button>
<label for="title">제목</label><input type="text" id="title">
<label for="content">내용</label><input type="text" id="content">
<label for="writer">작성자</label><input type="text" id="writer">

<table>
    <thead>
        <tr>
            <th>제목</th>
            <th>내용</th>
            <th>작성자</th>
            <th>삭제</th>
        </tr>
    </thead>
    <tbody id="tbody"></tbody>
</table>
</body>
</html>

 

- JS

function findAll() {
    fetch("/api/v1/todo", {
        method: "GET",
        headers: {
            "Content-Type": "application/json",
        },
    })
    .then(async function (response) {
        const data = await response.json();
        const tbody = document.getElementById("tbody");
        console.log(tbody);
        data.forEach(i => {
            const tr = document.createElement("tr");
            const title = document.createElement("td");
            const content = document.createElement("td");
            const writer = document.createElement("td");

            title.innerText = i.title;
            content.innerText = i.content;
            writer.innerText = i.writer;

            tr.appendChild(title);
            tr.appendChild(content);
            tr.appendChild(writer);
            tbody.appendChild(tr);
        })
    })
    .catch(function (error) {
        console.error(error);
    })
}

function insertTodo() {
    const title = document.getElementById("title").value;
    const content = document.getElementById("content").value;
    const writer = document.getElementById("writer").value;

    fetch("/api/v1/todo", {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            title: title,
            content: content,
            writer: writer
        }),
    })
    .then(async function (response) {
        if (response.status === 200) {
            alert("등록 완료");
            location.reload();
        }
    })
    .catch(async function (error) {
        console.error(error);
    })
}

document.addEventListener( "DOMContentLoaded", function () {

    const insert = document.getElementById("insert");
    insert.addEventListener("click", insertTodo, false);
    findAll();

}, false);


 

<link rel="stylesheet" href="https://unpkg.com/mvp.css@1.12/mvp.css">

bootstrap보다 가볍고 쓰기 편한 라이브러리

restController에서 데이터를 조회하기 때문에, 동적으로 테이블을 그려줬다.

 

 

7. DB, JPA 설정

server:
  port: 8081
spring:
  datasource:
    hikari:
      username: sa
      driver-class-name: org.h2.Driver
      jdbc-url: jdbc:h2:tcp://localhost/~/test
      password: ''

  jpa:
    database-platform: org.hibernate.dialect.H2Dialect
    open-in-view: false
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        show_sql: true
        format_sql: true

 

 

문법이 조금 달라서 헤맸지만 일단 CR기능을 만들었다.

DTO에서 Entity로 변경을 직접 해주려했지만 여기서 많이 헤매서 라이브러리를 사용해서 편하게 작업했다.

 

 

완성!

 

 

데이터 추가

 

 

728x90

'개발 > Kotlin' 카테고리의 다른 글

[Kotlin] 코틀린 기초 살펴보기  (0) 2022.11.25