Jpa Web Application

Spring Boot와 JPA를 활용해서 Web Application을 개발하는 과정이다.

Project Gradle Setting

spring boot starter을 활용해서 project을 생성한다.

  • gradle-groovy project
  • spring boot: 3.0.1
  • java: 17
  • dependency
    • web
    • lombok
    • validation
    • spring data jpa
    • h2
    • devtools

View Page Test

Thymeleaf 기반의 template engine을 활용해서 SSR을 구현한다.

HelloController

@Controller
public class HelloController {
    @GetMapping("hello")
    public String hello(Model model) {
        model.addAttribute("data", "hello");
        return "hello";
    }
}

hello.html

<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Hello</title>
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

</head>
<body>
    <p th:text="'안녕하세요 ' + ${data}"> 안녕하세요 손님.</p>

</body>
</html>

Jpa Settings

spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/jpashop
    username: sa
    password:
    driver-class-name: org.h2.Driver
  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        # show_sql: true --> system.out을 log 출력으로 아래의 logging 방식을 활용한 log 출력을 진행한다.
        format_sql: true
logging.level:
  org.hibernate.SQL: debug
# org.hibernate.type: trace #스프링 부트 2.x, hibernate5
# org.hibernate.orm.jdbc.bind: trace #스프링 부트 3.x, hibernate6

간단한 애플리케이션 개발을 위해 가벼운 DB인 H2를 활용하여 JPA 웹애플리케이션 개발 실습을 진행한다.

Jpa Sample Test

Member.class

@Entity
@Getter
@Setter
public class Member {
    @Id
    @GeneratedValue
    private Long id;
    private String username;
}

Member Repository

@Repository
public class MemberRepository {
    @PersistenceContext
    EntityManager entityManager;

    public Long save(Member member) {
        entityManager.persist(member);
        return member.getId();
    }

    public Member find(Long id) {
        return entityManager.find(Member.class, id);
    }
}

Repository Test

@SpringBootTest
public class MemberRepositoryTest {

    @Autowired
    MemberRepository memberRepository;

    @Test
    @DisplayName("멤버 객체를 저장하고 검색하는 기능 테스트")
    @Transactional
    @Rollback(false)
    void testMember() {
        //given
        Member member = new Member();
        member.setUsername("memberA");

        //when
        Long savedId = memberRepository.save(member);
        Member savedMember = memberRepository.find(savedId);

        //then
        assertThat(savedId).isEqualTo(member.getId());
        assertThat(savedMember.getUsername()).isEqualTo(member.getUsername());
        assertThat(savedMember).isEqualTo(member);
    }
}

Query Parameter Loggind

JPA을 활용한 Spring Web Application을 개발을 수행하게 되면, logging을 통해 실행되는 sql을 확인할 수 있다.

하지만, 아래와 같이 parameter에 대해서는 ?로 표현되어 어떠한 값이 입력되었는지 확인하기 어려운 경우가 있다.

2023-01-04T00:54:11.280+09:00 DEBUG 50616 --- [           main] org.hibernate.SQL                        : 
    insert 
    into
        member
        (username, id) 
    values
        (?, ?)

이럴 때는 application.yml에 log 옵션을 설정해서 parameter 값을 확인할 수 있다.

parameter binding option 추가

org.hibernate.orm.jdbc.bind: trace #Spring Boot 3.x, hibernate6

출력된 parameter 정보

2023-01-04T00:54:11.281+09:00 TRACE 50616 --- [           main] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [VARCHAR] - [memberA]
2023-01-04T00:54:11.281+09:00 TRACE 50616 --- [           main] org.hibernate.orm.jdbc.bind              : binding parameter [2] as [BIGINT] - [1]

값이 포함된 sql을 보고자 할때는, 외부 라이브러리 추가를 통해 parameter에 바인딩된 값을 같이 확인할 수 있다.

해당 실습에서는 p6spy 라이브러리를 활용한다.

build.gradle

implementation "com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.1"

spring boot 3.0.1 버전에서는 p6spy 사용을 위해 추가 작업이 필요하다

resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration

com.github.gavlyukovskiy.boot.jdbc.decorator.DataSourceDecoratorAutoConfiguration

resources/spy.properties

appender=com.p6spy.engine.spy.appender.Slf4JLogger

값이 포함된 sql 출력

2023-01-04T00:54:11.282+09:00  INFO 50616 --- [           main] p6spy                                    : 1672761251282|0|statement|connection 4|url jdbc:h2:tcp://localhost/~/jpashop|insert into member (username, id) values (?, ?)|insert into member (username, id) values ('memberA', 1)
2023-01-04T00:54:11.284+09:00  INFO 50616 --- [           main] p6spy  

References

link: inflearn

link:jpa

link:thymeleaf

link: springboot3

댓글남기기