들어가기에 앞서

-예제에서 쉽게 설명하기 위해서 엔티티클래스에 setter getter를 모두 열어두어

 단순하게 설계를 할 것이다.

-실무에서는 getter는 열고, setter는 꼭 필요할 때에만 사용하는 것을 추천한다.

 

1. 회원엔티티개발

 

실습

회원엔티티클래스 생성 및 작성

설명

회원엔티티개발

a. jpabook.jpashopPackagedomain이라고 만든다.

-여기에 핵심 엔티티들을 설치 할 것이다.

 

b. 회원엔티티 작성

-List, ArrayList import class를 해줌

 

c. Address, Order 클래스 파일 생성

 

c. 회원테이블 이름 매핑

-@Id, @generatedValue, @Columns 어노테이션 세팅

 

2.주소값 타입 개발

실습

주소값타입개발

설명

a. address주소 클래스에서 코드작성

@Embeddable 어노테이션 사용

-address 주소가 어딘가에 내장될 수 있게 하기 위해 사용

@Getter 어노테이션을 열어두기

 

b.회원엔티티(RealMember)클래스파일에서 내장타입관련 어노테이션 세팅

-Address변수에 내장타입을 포함했다라는 @Embedded 어노테이션으로 매핑을 해주었다.

-Address변수에 @Embedded 하나만 있어도 되지만,  대개 두가지 어노테이션을 많이 사용한다.

 

3. 주문(order)엔티티클래스파일에서

실습

주문엔티티클래스 생성 및 작성(주문과 회원관계 연관관계매핑)

설명

a.주문엔티티클래스파일에서

-@Entity, @Table 이름 설정을 했다.

-@Table(name = "orders")라고 해주지 않으면

  public class Order에서 Order의 관례로 이름이 Order가 되어 버리기 때문에 이름 설정을 해주어야 한다.

 

b.order_id

-DB컬럼의 id이름을 테이블명으로 가져와 테이블명_id형태로 설정해준다.

 DBA포지션 엔지니어가 이러한 형태로 설정해주는 것을 원한다.

 

참고

엔티티의 식별자는 id를 사용하고 PK 컬럼명은 member_id를 사용했다. 엔티티는 타입(여기서는 Member)이 있으므로 id 필드만으로 쉽게 구분할 수 있다. 테이블은 타입이 없으므로 구분이 어렵다.

그리고 테이블은 관례상 테이블명 + id를 많이 사용한다.

참고로 객체에서 id 대신에 memberId를 사용해도 된다. 중요한 것은 일관성이다.

 

c.@ManyToOne

-주문과 회원의 관계, 다대 1관계를 설정해주는 어노테이션

 

d.@JoinColumn(name = "member_id")

-@JoinColumn 어노테이션은 외래 키를 매핑 할 때 사용

 

e.name 속성에는 매핑 할 외래키(연관관계주인) 이름지정

-member_id = foregien key(외래키)

-주문회원테이블에서 주문회원에 대한 정보를 매핑

 

 

4. 회원엔티티클래스(RealMember)에서

실습

회원엔티티 연관관계 매핑

 

a.어노테이션 설정

@OneToMany

-회원과 주문의 관계, 1대 다 관계를 설정해주는 어노테이션

 

@OneToMany (mapped by = "member")

-foreign key가 있는 order클래스에 있는 member가 연관관계의 주인이다.

-mapped by - order 테이블에 있는 member필드에 의해 맵핑된 거울일 뿐이야라는 뜻

-여기에 무엇을 넣는다고 해서 order에 있는 member필드의 foreign key 값이 변경되지

 않는다.

-order엔티티클래스에 있는 order테이블에 있는 member필드 값을 변경하면

 member_idforeign key 값이 변경된다.

 

어노테이션 설명 참고

https://docs.oracle.com/javaee/6/api/index.html

어노테이션이 궁금하다면 java.persistence -> annotation type을 클릭하면 어노테이션 설명을 볼 수 있다.

 

6. MemberRepositoryTest파일 테스트

MemberRepositoryTest 파일

설명

@SpringBootTest

-스프링부트로 테스트하기 때문에 SpringBootTest annotation 세팅

 

@RunWith(SpringRunner.class)

-JUnit에게 스프링과 관련된 테스트를 할 것이라고 알려주기 위해 하는 세팅

 

*annotation관련설명

(https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/html/spring-boot-features.html#boot-features 참고)

If you are using JUnit 4, don’t forget to also add @RunWith(SpringRunner.class) to your test,

otherwise the annotations will be ignored.

If you are using JUnit 5, there’s no need to add the equivalent @ExtendWith(SpringExtension.class)

as @SpringBootTest and the other @Test annotations are already annotated with it.

 

-JUnit4 사용할 경우, @RunWith를 넣지 않으면 annotations들이 적용되지 않을 것이라고 함.

 JUnit5 @SpringBootTest와 같은 annotation을 세팅할필요 없다고 한다.

 

@Autowired MemberRepository memberRepository;

-MemberRepository작동을 위해서 Autowired를 사용해서 MemberRepository 인젝션 받음

 

@Test

-member를 테스트하기 위함

-given when then 형태로 테스트

 

//given

-member 변수를 만들고, memberA로 설정한다.

 

//when

a.member가 잘 저장되는지 확인

: memberRepository.save(member)작성후 save에서 단축키 ctrl+ Alt + v를 누르면

다음과 같은 형태로 설정이 된다.

 

Long saveId = memberRepository.save(member);

-> saveId: 저장된 Id(변수)를 뽑아오는(extract) 역할을 한다.

->member를 가지고 save를 하면 잘 저장이 되는지 확인을 해야 한다.

 

b.Member findmember = memberRepository.find(saveId);

-memberRepository에서 find해서 saveId가지고 넘긴 것이 findmember가 맞는지 확인한다.

*findMember 변수를 만든다.

 

//then (검증)

-Assertions 라고 하면 assertj라는 라이브러리를 스프링테스트가 자동으로 가지고 있어

라이브러리 디펜던시에서 자동으로 올라온다. “ . ”을 찍어주기만 하면!

 

-findMembergetIdmembergetId와 같다.

 findMembergetUsernamemembergetUsername과 같다.

 

#마주한문제

a.applcation.yml_debug설정 위치변경

무엇이 문제인지 정확히 몰라 test하기 위해 연관 있는 파일들을 확인하기 시작했다.

-application.yml 로 들어감

-applcation.yml_debug설정 위치변경

 level : debug 라고 설정이 되어 있음을 확인

 org.hibernate.SQL : debug로 변경

 

b.application.yml_DB경로접속 휴먼에러_JPA에러

-다음과 같은 메시지 확인

a,b 문제해결

그래서 application.yml 들어가니 설정경로가 jap와 debug위치 변경

 

c.MVCC_unsupported 메세지

-MVCC=TRUE 삭제

 

d. URL 에러메세지

-application.yml에서 경로를 확인하니

“ : ” 가 하나 더 추가 되어 있어 삭제

 

 

e. No EntityManager with actual transaction available 에러메세지

엔티티매니저를 통한 모든 데이터 변경 트랜잭션 안에서 이루어져야 하는데

현재 @Transactional 어노테이션이 없다.

2가지 종류의 transaction이 있는데 현재 스프링프레임워크를 사용하므로

-javax.transaction

-org.springframework.transanction <-이것을 사용한다.

 

에러메시지

문제해결

#마주한문제 3_Member테이블 미생성

-H2 콘솔에 접속하여 데이터베이스에 member 테이블이 생겼나 확인하니 Member 생성이 안되어 있었다!

 

a.application.yml_hibernate 단어오타

-hibernate 단어correction

 

b.application.yml에서

-logging.level: 로 다시 변경

-그리고 전체적으로 띄어쓰기가 중요하다는 사실을 발견 전체적으로 2칸씩 이동해줌

-그리고 다시 h2 콘솔 접속하여 데이터베이스에 member테이블생성 확인!

 

문제해결

*localhost:8082로 접속이 안될 시

local에서 h2데이터베이스를 실행시켜주지 않고 실행시킬 시에는

h2.database 관련하여 에러가 나오니 주의 할 것!

cmd에서 h2<bin<h2.bat실행 해주어야 h2데이터베이스로 접속(localhost:8082)접속할 수 있다.

 

 

JPA가 ddl-auto: 에 CREATE 옵션이 있으니 멤버테이블을 만들어 주었다.

member 테이블생성과정

-dropcreate로 테이블 생성을 했다.

-Member Entity정보를 보고 테이블을 생성한다.

 

 

member 테이블에 데이터가 없다?

Transactional이 데이터를 Rollback한다.

-Transactional 어노테이션이 테스트케이스에 있으면 테스트가 끝난 후에 바로 롤백이 되어 버린다.

-테스트케이스가 아닌 곳에서는 제대로 작동된다.

 왜냐하면 데이터가 계속 들어가 있으면 반복적인 테스트를 하지 못하기 때문이다.

 

Rollback(false) annotation

-그럼에도 불구하고 내눈으로 직접 데이터를 보고 싶을 때 이용

JPA 세팅 및 동작 확인완료!

 

기타

-같은 트랜잭션 안에서 저장하고 조회하면 영속성 컨텍스트 같다.

 같은 영속성 context안에서는 id값이 같으면 같은 엔티티로 식별한다.

 같은 영속성 context 안에서 기존 엔티티에서 관리하던 1차 캐쉬에서 바로 정보를 가져온다.

 그래서 select 쿼리는 없고, insert 쿼리만 보인다

a.쿼리 파라미터 로그 남기기 2가지 방법

쿼리 파라미터를 남기는 방법 1

-application.yml ->logging.levvel

org.hibernate.type: trace 추가

쿼리 파라미터를 남기는 방법 2

외부라이브러리 사용

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

 

-데이터베이스 커넥션을 랩핑해서 왔다갔다하는 만들어진 sql 스테이트먼트를 로그로 출력해주는 라이브러리들을 이용

 

-P6Spy 라이브러리 추가

->build.gradle

-implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.6.1' 추가

->refresh

 

MemberRepositoryTest 실행후

-원본 출력정보 확인 및 파라미터 바인딩 출력정보 확인

-url에서 connection 얻어오는 로그

 

*로그를 어떻게 찍을 건지에 대한 옵션은 상기 사이트에서 확인할 수 있다.

*외부라이브러리 사용시 개발단계에서는 편한데,

 운영단계에서는 성능테스트를 해야 하고 성능저하가 있을 수 있기 때문에,

 성능이 좋지 못하면 개발단계에서만 사용할 것!

 

단어개념_binding Parameter를 보다가

파라미터 - 매개변수

매개변수란

-컴퓨터 프로그래밍에서 매개변수란 변수의 특별한 한 종류로서, 함수 등과 같은 서브루틴의 인풋으로 제공되는 여러

 데이터 중 하나를 가리키기 위해 사용된다. 여기서 서브루틴의 인풋으로 제공되는 여러 데이터들을 전달인자 라고 부른

 다.

 

위키백과 및 구글 참고

https://www.google.com/search?q=%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0&oq=%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0&aqs=chrome..69i57j0l7.1697j0j7&sourceid=chrome&ie=UTF-8

 

바인딩이란

바인딩(binding)이란 프로그램에 사용된 구성 요소의 실제 값 또는 프로퍼티를 결정짓는

행위를 의미합니다.

 

예를 들어 함수를 호출하는 부분에서 실제 함수가 위치한 메모리를 연결하는 것도

바로 바인딩입니다.

이러한 바인딩은 크게 다음과 같이 구분할 수 있습니다.

 

1. 정적 바인딩(static binding)

-실행 시간 전에 일어나고, 실행 시간에는 변하지 않은 상태로 유지되는 바인딩임.

 

2. 동적 바인딩(dynamic binding)

- 실행 시간에 이루어지거나 실행 시간에 변경되는 바인딩임.

이러한 동적 바인딩은 늦은 바인딩(late binding)이라고도 불립니다.

 

참고사이트

http://tcpschool.com/php/php_oop_binding

 

 

다른 라이브러리는 버전정보가 왜 없나요?

기본적으로 스프링부트가 2.1.7에서는 내한테 맞는 라이브러리를 전부 세팅 해놓았따.

미리 세팅 해놓지 않은 라이브러리들은 직접 버전정보를 적어주어야 한다.

 

#마주한문제 <미해결>

jar빌드 동작확인

-windowsmac 환경에 따라 명령어가 다르니 주의!

 

Build

<windows 환경>

jpashop> gradlew.bat

 

<mac 환경>

jpashop> ./gradlew clean build

 

 

Buildjar 라이브러리가 생긴다.

+ Recent posts