[Java] 58. Eclipse에서 Spring boot의 JPA를 설정하는 방법


Study/Java  2022. 2. 23. 18:09

안녕하세요. 명월입니다.


이 글은 Eclipse에서 Spring boot의 JPA를 설정하는 방법에 대한 글입니다.


Spring Web Framework 환경에서 JPA를 설정하는 방법에 대해서 설명한 적이 있습니다.

링크 - [Java] 45. JPA 설정하는 방법


기본적인 설정은 Spring Web Framework 환경에서 설정하는 것과 같습니다. 다른 점이 있다면 Spring Web Framework는 persistence.xml에서 접속 환경을 설정하고 Spring boot는 application.properties에서 설정을 하게 됩니다.

Spring boot는 환경 설정 파일이 하나로 통합이 되니 관리하기 편하네요.


먼저 JPA를 연결하기 위해서 로컬 데이터베이스에 테스트 테이블을 작성합시다.

-- test 데이터 베이스에 접속
use test;
-- 이전 테이블이 있다면 일단 삭제
-- drop table info;
-- drop table user;
-- user 테이블 생성
create table user(
  id varchar(255) not null,
  name nvarchar(255) not null,
  
  primary key(id) -- 키 설정
);
-- info 테이블 생성
create table info(
  idx int not null auto_increment, -- 자동 증가
  id varchar(255) not null,
  age int not null,
  
  primary key(idx), -- 키 설정
  foreign key(id) references user(id) -- id는 user의 id로 연결
);

그리고 테이블에 테스트 데이터를 넣겠습니다.

-- user 테이블에 데이터를 삽입
insert into user (id, name) values('nowonbun', 'Hello');
-- info 테이블에 데이터를 삽입
insert into info(id, age) values('nowonbun', 20);

이제 위 데이터를 Spring boot를 이용해서 화면에 표시해 보겠습니다.


우선, 이전 글에서 작성한 프로젝트에서 JPA 라이브러리를 추가하겠습니다.

링크 - [Java] 57. Eclipse에서 Spring boot를 설정하는 방법


먼저 위자드를 실행해서 JPA를 추가합니다.

프로젝트에서 마우스 오른쪽을 눌러 Spring의 Add Starter를 실행합니다.

그리고 이게 이클립스 버그인지는 모르겠는데.. 기존에 선택한 것이 선택이 되지 않았습니다. 그래서 선택하지 않고 Finish를 누르고 설정하게 되면 기존에 설정한 라이브러리가 빠지는 현상이 발생하네요.

그래서 이전에 설정한 것도 체크해야 합니다. (버그인듯...)

JPA를 사용하기 위해서 JDBC API, Spring Data JDBC, Spring Data JPA, MariaDB Driver를 추가해야 합니다.

Next 버튼을 누르면 소스 비교 화면이 나오는데, 여기서 pom.xml만 변경하는 것으로 체크하고 Finish 버튼을 누르면 maven 업데이트가 됩니다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.3</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <groupId>com.example</groupId>
  <artifactId>SpringBootTest</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>SpringBootTest</name>
  <description>Demo project for Spring Boot</description>
  <properties>
    <java.version>11</java.version>
  </properties>
  <dependencies>
    <!-- thymeleaf 라이브러리 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <!-- Spring boot 라이브러리 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- JUnit 라이브러리 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- devtools 라이브러리 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <scope>runtime</scope>
      <optional>true</optional>
    </dependency>
    <!-- data-jdbc 라이브러리 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jdbc</artifactId>
    </dependency>
    <!-- data-jpa 라이브러리 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- jdbc 라이브러리 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <!-- mariadb-java-client 라이브러리 -->
    <dependency>
      <groupId>org.mariadb.jdbc</groupId>
      <artifactId>mariadb-java-client</artifactId>
      <scope>runtime</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

위자드를 사용하지 않고 pom.xml를 직접 수정하는 방법도 있습니다. 사실 위자드를 사용하는 것보다 직접 환경 설정을 하는 것이 정확하기 때문에.. 직접 pom.xml를 설정하는 것을 추천합니다.


그리고 이클립스에서 JPA를 사용해야 하기 때문에 JPA 모드로 변경해야 합니다.

이클립스는 Spring boot 기준이 아니고 Web framework 기준으로 설정되어 있습니다. 그래서 이클립스 환경 설정을 약간 수정해야 합니다.

먼저 소스 안에 META-INF/persistence.xml 파일을 지웁니다..

그러면 이클립스에서 META-INF/persistence.xml 파일이 없다고 에러를 표시합니다.

Window -> Preferences 탭으로 가서 Java Persistence -> JPA -> Errors/Warnings의 Project -> No persistence.xml file found in project를 ignore로 바꿉니다.

에러 메시지가 없어졌습니다.


그리고 이제 데이터베이스에서 Entity를 만들어 봅시다. 프로젝트에서 마우스 오른쪽 클릭을 합니다.

클래스를 생성을 하면 model.entity 클래스가 만들어 지는 것을 확인할 수 있습니다.

이것을 SpringBootTestApplication 클래스의 하위 패키지로 이동합니다. 이전에 Controller처럼 scanBasePackages를 맞추지 않으면 에러가 발생합니다. 역시 scanBasePackages를 설정하면 다른 패키지로 설정할 수 있습니다.


이제 application.properties로 가서 접속 정보를 설정합니다.

# 서버 포트 설정
server.port=8081
# thymeleaf 파일 설정
spring.thymeleaf.prefix=classpath:templates/
spring.thymeleaf.check-template-location=true
# thymeleaf 파일 확장자
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
# thymeleaf 캐쉬 모드
spring.thymeleaf.cache=false
# 데이터베이스 접속 정보
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
# 아이디
spring.datasource.username=root
# 패스워드
spring.datasource.password=****
# 드라이브 클래스
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
# 쿼리 로그 표시하기
spring.jpa.show-sql=true
# 콘솔 표시
spring.h2.console.enabled=true

데이터베이스 접속 설정이 되었으면 이제 레포지토리 인터페이스를 생성해서 화면에 출력해 보겠습니다.

package com.example.demo.repository;

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

import com.example.demo.model.User;
// 레포지토리 인터페이스
public interface UserRepository extends JpaRepository<User, String> {}

Spring boot에서는 transaction을 설정하지 않아도 Repository를 통해서 데이터를 취득할 수 있습니다.

레포지토리 인터페이스를 생성했으면, 기존 Controller의 HomeController에 의존성 추가(@Autowired)를 합니다.

package com.example.demo.Controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.demo.repository.UserRepository;

// 컨트럴러 어노테이션
@Controller
public class HomeController {
  // 레포지토리 의존성 주입
  @Autowired
  private UserRepository userRepository;
  // 매핑 주소
  @RequestMapping(value = { "/", "/index.html" })
  public String index(Model model) {
    // 레포지토리에서 id를 통해 User 데이터를 취득한다.
    var user = userRepository.findById("nowonbun").get();
    // 템플릿에 전달할 데이터
    model.addAttribute("data", user.getName());
    // 템플릿 파일명
    return "Home/index";
  }
}

root 페이지가 호출되면 userRepository에서 nowonbun의 키로 데이터를 취득해 옵니다. 그리고 Thymeleaf 템플릿에 name 데이터를 표시합니다.

대략 아래와 같은 구조의 프로젝트가 생성됩니다.

그럼 프로젝트를 실행하니 아래와 같은 결과가 나왔습니다.

user테이블의 nowonbun의 레코드의 name 값이 Hello이니 정상적으로 데이터베이스에서 데이터를 취득해서 출력한 결과입니다.


설정 방법이 다를 뿐 Entity를 다루는 것은 이전 Web framework때와 같습니다.

링크 - [Java] 46. JPA의 Entity 클래스의 기본 설정(@GeneratedValue, @ManyToMany)

링크 - [Java] 47. JPA의 Entity 클래스의 레퍼런스 설정(cascade, fetch)


기존 Web Framework에서는 제가 Dao를 생성하고 FactoryDao를 이용하여 트랜젝션을 관리했습니다.

그런데 Spring boot에서는 Repository 인터페이스를 만들고 의존성 주입된 인스턴스에서 자동으로 트랜잭션을 관리하네요... 사실 자동이라고 표현이지만 이게 commit rollback을 어떻게 관리를 해야 하며 에러가 발생할 경우 어떻게 rollback을 해야할 지에 대해 불명확합니다.

그래서 Spring boot에서도 EntityManager를 취득해서 트랜젝션을 직접 관리하는 방법이 있습니다. 다음 글에서는 Spring boot에서 Dao와 Factory, 실질적인 트랜젝션 관리하는 방법에 대해서 설명하겠습니다.


여기까지 Eclipse에서 Spring boot의 JPA를 설정하는 방법에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.