ddl-auto - Spring jpa (활용 part1)
이글은 인프런 강의 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?
------------------------------------------------------------------------------------------------------------------