Java&Spring

ddl-auto - Spring jpa (활용 part1)

sung.hyun.1204 2022. 7. 5. 16:16

이글은 인프런 강의 jpa 활용1 을 보고 만든 글입니다.

 

---------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------

 

Test 를 했는데, ddl-auto option 이 안된다? -> 띄어쓰기를 확인해보자. 공백 주의 like python

ddl-auto: create

 

spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/jpashop
    username: sa
    password:
    driver-class-name: org.h2.Driver
  jpa:
    hibernate:
      ddl-auto: create
    
    properties:
      hibernate:
        format_sql: true
      #show_sql: true

logging.level:
  org.hibernate.SQL: debug

---------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------

 

 

Bakend :  쿼리 , DB 어떻게 할지

spring의 장점은 DB  transaction 의 효과 적인 처리와 객체를 이용한 작업으로 인하여  생산성을 높인점이다.

 

 

Lombok , getter setter 와 같은 귀찮은 코드를 어노테이션을 통해 쉽게 만들어준다.

 

Applicatation.java

package jpabook.jpashop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JpapracApplication {

    public static void main(String[] args) {


        Hello h = new Hello();
        h.setData("this is data");
        String data =h.getData();
        System.out.println("data = " + data);

        SpringApplication.run(JpapracApplication.class, args);
    }

}

Hello.java (class)

package jpabook.jpashop;


import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class Hello {
    private String data ;
}

tip, intellij 단축키 :

soutv : systemprinout , 조건 : 상단의 객체를 만든 코드가 있어야한다.

 

 

 

 

work flow !

1. member class 작성 : DB 의 column 을 만들어줌 : (C 에서 구조체를 만드는 과정이다 . )

2.MemberRepository class  작성 : JPA manager 을 붙어 spring 에서 enttity를 handle  해줄 준비

 

 

1. @Repository spring 의 component scan 의 대상! 자세한건 Command +B  로 anotaion class 파일을 읽어보자.,

 

Repository.java

/*
 * Copyright 2002-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.stereotype;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;

/**
 * Indicates that an annotated class is a "Repository", originally defined by
 * Domain-Driven Design (Evans, 2003) as "a mechanism for encapsulating storage,
 * retrieval, and search behavior which emulates a collection of objects".
 *
 * <p>Teams implementing traditional Java EE patterns such as "Data Access Object"
 * may also apply this stereotype to DAO classes, though care should be taken to
 * understand the distinction between Data Access Object and DDD-style repositories
 * before doing so. This annotation is a general-purpose stereotype and individual teams
 * may narrow their semantics and use as appropriate.
 *
 * <p>A class thus annotated is eligible for Spring
 * {@link org.springframework.dao.DataAccessException DataAccessException} translation
 * when used in conjunction with a {@link
 * org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
 * PersistenceExceptionTranslationPostProcessor}. The annotated class is also clarified as
 * to its role in the overall application architecture for the purpose of tooling,
 * aspects, etc.
 *
 * <p>As of Spring 2.5, this annotation also serves as a specialization of
 * {@link Component @Component}, allowing for implementation classes to be autodetected
 * through classpath scanning.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @since 2.0
 * @see Component
 * @see Service
 * @see org.springframework.dao.DataAccessException
 * @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {

   /**
    * The value may indicate a suggestion for a logical component name,
    * to be turned into a Spring bean in case of an autodetected component.
    * @return the suggested component name, if any (or empty String otherwise)
    */
   @AliasFor(annotation = Component.class)
   String value() default "";

}

 

 

Member.java

package jpabook.jpashop;


import lombok.Getter;
import lombok.Setter;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

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

MemberRepository.java

package jpabook.jpashop;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;


@Repository
public class MemberRepository {

    @PersistenceContext
    private EntityManager em;

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

    public Member find(Long id)
    {

        return em.find(Member.class, id);
    }

}

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

test code 작성:

MemberRepository.java 에 커서 두고 커맨드 + shift + t -> testcode

tdd 작성

Tip : intellij live+ templete 을 등록 하자. 

 

memberRepository.save(member);

save 에 커서 두고 커맨드 옵션 v 로 extract value 하자

 

 

MemberRepositorytest.java

package jpabook.jpashop;

import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.transaction.Transactional;

import static org.junit.Assert.*;

// junit 4
@RunWith(SpringRunner.class)
@SpringBootTest
public class MemberRepositoryTest {
    // get injection
    @Autowired MemberRepository memberRepository;

    @Test
    @Transactional //모든 entity 변화는 Transaction 안 , entity manager 가 필요하다
    public void testMember()throws Exception{
        //given
        Member member = new Member();
        member.setUsername("memberA");
        // when
        Long savedId = memberRepository.save(member);
        Member findMember = memberRepository.find(savedId);
        // then
        Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());
        Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername());

    }



}

 

: 일반적으로 스프링에서는 testcase 에 transaction 이 있으면 결과 DB 에 data 가 저장 되지 않고 Roll back 이된다 

-->  반복적인 test  를 위한 방식이다 .  

Roll back 없이 test 를 위하면.   > @Rollback(false)   어노테이션을 붙여준다.

 

----------------------------------------------------------------------------------------------------------------------

System.out.println("fm == m : "+ (findMember==member));

  resurlt : ture

같은 transaction 안, 같은 영속성 안에서 같은 id 는 같은것으로 본다. 

영속석 context 안 같은 식별자 => 1차 캐쉬 안 에서 가져온다.

즉 , insert 쿼리만 날라가고 select 쿼리는 없다.

>> insert 
    into
        member
        (username, id) 
    values
        (?, ?)

 

----------------------------------------------------------------------------------------------------------------------jar 빌드해서 동작 확인. >> 배포 할때 중요,  port 안겹치는지 미리 확인하자.

folder -> gradlew 확인

$./gradlew clean build

$ll 

$java -jar jpashop-0.0.1-SNAPSHOT.jar

----------------------------------------------------------------------------------------------------------------------

쿼리 파라미터 로그 남기기!!!!

 

1. yml  파일 , type option 추가

logging.level:
  org.hibernate.SQL: debug
  org.hibernate.type: trace

 

2.   다음 깃허브 링크에 들어가 gradle implementaion을 찾아 추가하고 , 버전확인 필수 , 바로 test 를 돌리면 된다.

자료 : 추가 적인 원하는 방식의 로그 형식을 찾아서 설정도 가능하다. 

https://github.com/gavlyukovskiy/spring-boot-data-source-decorator

implementation("com.github.gavlyukovskiy:p6spy-spring-boot-starter:${version}")

버전 1.8.0    date : 2022.7.05 

 

> 참고: 쿼리 파라미터를 로그로 남기는 외부 라이브러리는 시스템 자원을 사용하므로, 개발 단계에서는 편하 게 사용해도 된다

 하지만 운영시스템에 적용하려면 꼭 성능테스트를 하고 사용하는 것이 좋다.

 

 

 

찾아볼것들 : 다음 글에서 알아보자. 

------------------------------------------------------------------------------------------------------------------

DAO VS Repositiory ?

 

Class Vs Interface?

 

Directroy. vs Package?

------------------------------------------------------------------------------------------------------------------