SpringBoot 와 JPA

Panda·2022년 2월 19일
0

Spring

목록 보기
6/45

현재 진행하고 있는 프로젝트에서
Database 접근을 JPA 사용하여 관리하려고 하였다.
nestJS 하면서 typeORM 처럼 쓰면 될줄알았는데
생각외로 지식이 요구되고 설정도 복잡하였다.

JPA란?

쉽게 말해서 자바에서 사용하는 ORM 인터페이스 입니다.
인터페이스이기때문에 JPA를 구현한 Hibernate, OpenJPA을 사용을 하는데
프로젝트에서는 Hibernate 사용을 했습니다.

구조

의존성

implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.projectlombok:lombok")
implementation("org.postgresql:postgresql")

Database는 postgreSQL을 사용하고
JPA 의존성 추가와
Model 코드의 생산성을 높이기위해 lombok을 추가해줬습니다. (java로 구현할 예정)

설정

// application.properties
// JPA 설정

// spring.jpa.hibernate.ddl-auto 속성을 사용할지 말지를 결정.
spring.jpa.generate-ddl=true
// Database 초기화 방법 (update : 변경된 스키마만 Database에 반영.)
spring.jpa.hibernate.ddl-auto=update
// 콘솔에 출력되는 JPA 실행 쿼리를 가독성있게 표현합니다.
spring.jpa.properties.hibernate.format_sql = true
// 콘솔에 실행 sql를 보여줌.
spring.jpa.show-sql = true
// Database 유형 설정 (sql 자동 생성 때문에 Database 유형 명시 해줘야함.)
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
// config.properties
// db에 접근할 driver 설정? (추후 자세히 알아봐야 할듯)
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/test
spring.datasource.username=postgres
spring.datasource.password=1234

데이터베이스 정보는 노출되서는 안되기때문에
.gitignore 처리를 해주기 위해서 properties를 분리해 작성을 하였다.

application.properties는 스프링부트가 자동으로 인식을 해서 설정값들이 잘 불러오지만
config.properties는 따로 코드상으로 처리해줘야한다.

@Configuration
@PropertySource("classpath:config.properties")
class GlobalPropertySource {
    @Value("\${spring.datasource.driverClassName}")
    private lateinit var driverClassName: String

    @Value("\${spring.datasource.url}")
    private lateinit var url : String

    @Value("\${spring.datasource.username}")
    private lateinit var username : String

    @Value("\${spring.datasource.password}")
    private lateinit var password : String

    fun getDriverClassName() : String = driverClassName

    fun getUrl() : String = url

    fun getUsername() : String = username

    fun getPassword() : String = password

    override fun toString(): String {
        return "driverClassName = ${driverClassName}, url = ${url}, username = ${username}, password = ${password}"
    }
}

@PropertySource : 경로에 있는 properties를 불러옴
@Configuration : 1개 이상의 Bean을 등록할거라고 알림. And properties를 스프링에 등록하기 위해 같이 쓰인다.

이러면 스프링부트가 Database에 접근 할수있는 환경설정은 완료하였다.

Repository, Model

// model은 java로 작성함.
@Entity
@Data
public class TestModel {
    @Id
    @GeneratedValue
    Long id;

    private String username;

    public void setUsername(String username) {
        this.username = username;
    }

    public Long getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }
}

id, username 을 가지고 있는 간단한 model이다.
@Entity
1. Entity 등록을 하여 스프링 실행시 Entity를 조회해 테이블을 자동으로 생성해줌
2. 테이블과의 매핑

테스트 용도로 대충 작성해서 getter, setter 를 직접 작성해줬다.
(@Data 가 적용되있으므로 굳이 작성할 필요없음.)

// repository는 Java로 작성함.
@Repository
public interface TestRepository extends JpaRepository<TestModel, Long> {
    @Query(nativeQuery = true, value = "SELECT * FROM test_model WHERE username = ?1")
    List<TestModel> findByUsername(String username);
}

JpaRepository를 상속을 받음으로써 CRUD가 자동으로 구현이 되있다.
@Query로 원하는 sql를 직접 작성할 수 있다.

테스트 용도로 대충 작성한거라서 interface 에다가 그냥 @Repository 등록을 해줬다.

Test

@SpringBootTest
// @DataJpaTest
internal class GlobalPropertySourceTest {
    @Autowired
    lateinit var testRepository: TestRepository

    @Test
    fun `Insert Database Check`() {
        // given
        val testEntity = TestModel()
        testEntity.username = "test1"

        // when
        val newEntity =  testRepository.save(testEntity)

        // then
        println(newEntity.id)
        assertThat(newEntity).isNotNull

        val existingEntities = testRepository.findByUsername(newEntity.username)
        println(existingEntities)
        existingEntities.forEach {
            println(it.id)
        }
        assertThat(existingEntities).isNotEmpty
    }
}

Test 환경은 2가지가 있는데
하나는 실제 DB로 테스트하는 것이고 (실제로 DB에 반영됨.)
나머지 하나는 인메모리DB로 테스트를 하는 것이다.

저는 실제 DB에 반영이 되는지를 테스트 하기 위해서
@SpringBootTest를 해줬습니다.

@DataJpaTest : JPA 관련 테스트 설정만 로드, 내장형 데이터베이스를 사용하여 실제 데이터베이스를 사용하지 않고 테스트 데이터베이스로 테스트 가능

테스트 결과 실제 DB에도 잘 반영이 되었고
테스트도 통과 한것을 확인할 수가 있었습니다.

느낀 점

JPA 환경설정 부터 테스트 환경설정 하는데만
2~3일 동안 하루종일 한거같은데....
관련 지식 공부,테스트, 오류 고치기 등

오류때문에 시간을 엄청 쓴거같았다.
별에별 사소한 이유로 오류가 발생하였다..

막상 다 구현하고 보니까 별거 없는거같다.......

profile
실력있는 개발자가 되보자!

0개의 댓글