문제상황

 

1.RealMember 클래스이름을 다시 기억하기 쉽게 Member이름으로 변경(테스트용 Member클래스파일은 바로삭제)

연동되는 클래스파일이름을 RealMember로 안해주고 그냥 Member를 사용한상태로 테이블을 생성했었었다.

그리고, 다시 기존 Member 클래스파일을 지우고 RealMember 클래스파일 이름을 MemberRENAME으로 바꿔주었다.

 

2. 의문점

이미 한번 과거 Member 안에 작성된 코드를 이용해서 생성된 테이블 을 한번 만들어줬다가

이름만 바꿔서 코드내용 바꿔주어서 다시 생성하면 변경된대로 적용되는지 궁금하다.

 

3. 디비 h2 맞고, 연동도 되어 있다.

H2 데이터베이스 콘솔접속해서 테이블들을 확인해보니 RealMember는 그대로 있고 Member도 그대로 있다.

테이블에서는 영향을 미치지않아 내가 직접 drop해주어야 하는 건지 모르겠다.

 

문제해결시도과정

1. 이름이 변경된 Member클래스에서 Member를 import 설정

Build completed with 2 errors and 0 warnings in 11 s 105 ms

빌드하는 과정에서 에러가 두가지 있었는데 Memberimport를 해주었다.

바로 밑에 코드 에도 (Member)로 설정

 

 

2.초기화옵션 ddl-auto:create, 데이터베이스에서 기존 Member 테이블 삭제시도

 

사진

 

ddl-auto:create옵션인 상태에서 h2 데이터베이스 접속해서 기존 MEMBER 테이블 삭제하려고 하니

다음과 같은 에러가 나온다.

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

Cannot drop "MEMBER" because "FKPKTXWHJ3X9M4GTH5FF6BKQGEB" depends on it; SQL statement:

DROP TABLE member [90107-200] 90107/90107 (도움말)

org.h2.jdbc.JdbcSQLSyntaxErrorException: Cannot drop "MEMBER" because "FKPKTXWHJ3X9M4GTH5FF6BKQGEB" depends on it; SQL statement:

DROP TABLE member [90107-200]

at org.h2.message.DbException.getJdbcSQLException(DbException.java:576)

at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)

at org.h2.message.DbException.get(DbException.java:205)

at org.h2.command.ddl.DropTable.prepareDrop(DropTable.java:98)

at org.h2.command.ddl.DropTable.update(DropTable.java:124)

at org.h2.command.CommandContainer.update(CommandContainer.java:198)

at org.h2.command.Command.executeUpdate(Command.java:251)

at org.h2.server.TcpServerThread.process(TcpServerThread.java:406)

at org.h2.server.TcpServerThread.run(TcpServerThread.java:183)

at java.lang.Thread.run(Unknown Source)

 

at org.h2.message.DbException.getJdbcSQLException(DbException.java:576)

at org.h2.engine.SessionRemote.done(SessionRemote.java:611)

at org.h2.command.CommandRemote.executeUpdate(CommandRemote.java:237)

at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:228)

at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:201)

at org.h2.server.web.WebApp.getResult(WebApp.java:1459)

at org.h2.server.web.WebApp.query(WebApp.java:1116)

at org.h2.server.web.WebApp$1.next(WebApp.java:1078)

at org.h2.server.web.WebApp$1.next(WebApp.java:1065)

at org.h2.server.web.WebThread.process(WebThread.java:178)

at org.h2.server.web.WebThread.run(WebThread.java:94)

at java.lang.Thread.run(Unknown Source)

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

 

-여기에서 내가 확인하고 이해한 에러 핵심은 다음과 같다.

-일단 MEMBER 테이블을 삭제할 수 없다. 그리고 Unknown Source 알려지지 않은 소스 Cannot drop "MEMBER"....

.

.

at java.lang.Thread.run(Unknown Source)

 

-기존에 MEMBER클래스파일을 삭제해서 테이블에서도 찾아내지 못해 삭제하지 못하는 것이라는 가설을 세웠다.

 

2. Real_Member 테이블 삭제 시도

-DROP TABLE Real_Member;

-지워진다..

-이것은 Real_Member 이름을 가진 클래스파일을 인식해서인지 삭제가 되었다.

-다시 h2 데이터베이스 재접속 상황은 같다.

 

3. 기존 MEMBER 클래스 파일을 다시 만들어서 삭제한다?

-이미 RealMember클래스파일 이름을 MEMBER파일로 바꾸었는데 다시 만들어서 테이블삭제는 말이 안되었다.

이미 변경한 MEMBER클래스파일은 어떻게 한단 말이지..

 

4. 테이블삭제시도전에 코드를 run하는 과정에서 drop if exists 문구와 error executing ddl를 확인한 것이 기억났다.

 

출처 https://galid1.tistory.com/610

구글링 해보니, 초기화 옵션을 (ddl-auto: update)update로 해주면 에러가 해결된다는 내용이 있었다.

물론 나와는 상황이 조금 달랐지만, 혹시 테이블도 update 되지 않을까 하는 생각으로 변경해주고 다시 테이블 설정을 했다.

 

 

결과는 클래스파일 RealMember에서 RENAME으로 변경한 Member클래스파일에 작성된 컬럼들이 생성됨을 확인했다. 즉 새롭게 변경해준 Member클래스파일 내용으로 update가 되었다.

 

5.기존에 있던 ID, USERNAME은 그대로 존재한다. 기존에 있는 컬럼에 합쳐진 것 같다.

 

맴버테이블을 연관관계없이 생성한 상태일 때에 삭제가 안될 수도 있다고 하여,

기존 멤버테이블 컬럼삭제된 상태에서, 테이블을 삭제 시도 해보았다.

 

하기와 같은 명령어를 이용해 ID, USERNAME을 삭제했다.

ALTER TABLE MEMBER

DROP COLUMN USERNAME;

 

삭제가 되어 현재 변경된 Member클래스 내용과 동일한 내용으로 업데이트하여 해결완료!

 

7.이왕 삭제하는 김에 테이블전부 삭제하고 다시 생성하기로 했다. (ddl-auto : create)

 

*맴버테이블을 연관관계없이 생성한 상태일 때에 삭제가 안될 수도 있다고 하여,

만약 연관관계가 있는 상태에서 삭제가 되지 않는다면 하기 명령어로 해볼 것

 

DROP TABLE : 테이블의 모든 데이터 및 구조를 삭제

-DROP TABLE 테이블명 [CASACADE CONSTRAINT];

 

기타공부내용

기타해결방법(기존 member 클래스파일을 realmember로 변경할 경우에 사용할 것)

-삭제된 member는 이제 더 이상 jpa가 관리하는 persist에 의해 영속성을 가지지 못하고

그냥 orm과는 관계 없고, 자바와는 관계없는 분리된 db테이블이 됨

더 이상 사용되지 않는 테이블이 되었다.

 

ddl-auto : create (ddl-auto옵션은 create)

멤버랑 리얼멤버 테이블을 drop시키고 다시 테이블을 새로 생성해도 무방하다.

의존성을 가진다면 테이블 스페이스를 전체를 다 날려버리면,

스프링이 재시작 될 때에 처음부터 다시 전체 테이블을 만들어줄 것이다.

바뀐 멤버엔티티에 영속성이 걸리게 되고, 연관관계매핑도 작성된대로 설정이 된다.

 

이해를 위한 ddl-auto : create옵션 추가설명

-예를들어, jpashop이라는 폴더를 만들고 그안에 member라는 폴더를 만들고 파일도 있다.

근데 이름을 realmember로 바꾸려하면 create 옵션은

기존 member는 그대로 냅두고 realmember폴더를 새로 만드는 것과도 같다.

1.Category 엔티티분석 및 카테고리 테이블분석

 

Category 엔티티

-id

-name

-items: List (다대 다 관계)

-parent: Category

-child: List

-상품과 다대다 관계를 맺는다. parent, child로 부모, 자식 카테고리를 연결한 다.

*계층 구조를 이렇게 매핑할 수 있다를 보여주기 위해 이렇게 설정 했다.

*자기자신을 셀프로 계층구조형태로 매핑을 하진 않았을 것 같아 이렇게 설정했다.

 

카테고리 테이블 분석

CATEGORY_ID

-PARENT_ID (FK)

-NAME

 

설명

카테고리와 상품 테이블 분석

-@ManyToMany를 사용해서 매핑한다.

(실무에서 @ManyToMany는 사용하지 말자. 여기서는 다대다 관계를 예제로 보여주기 위해 추가했을 뿐이다)

 

 

2.(Category_Item)중간테이블 및 카테고리와 상품 연관관계 맵핑

 

CATEGORY_ITEM

-CATEGORY_ID (FK)

-ITEM_ID (FK)

 

카테고리 엔티티

-id

-name

-items: List

-parent: Category

-child: List

 

아이템 엔티티

-id

-name

-price : int

-stockQuantity

-categories: List

 

a.카테고리클래스에서 상품과 맵핑

설명

@JoinTable(name = "category_item",
joinColumns = @JoinColumn(name = "category_id),
inverseJoinColumns = @JoinColumn(name = "item_id"))

 

@JoinTable

-객체는 컬렉션이 있어 다대 다관계가 가능하지만

 관계형 DB는 컬렉션관계를 양측에 가질 수 있는 것이 아니기 때문에 1대 다, 다대 1 관계의

 중간테이블을 이용한다.

 

@JoinTable어노테이션

-중간테이블에 있는 외래 키를 매핑 할 때 먼저 사용

 

joinColumns = @joinColumn(name="category_id)

-중간테이블에 있는 category_id 외래키 매핑

 

inverseJoinColumns = @JoinColumn(name = "item_id")

-중간테이블에 있는 item_id 외래키 매핑(item과 연관관계 매핑하기 위함)

 

b.Item클래스에서 카테고리와 맵핑

실습

설명

@ManyToMany(mappedBy ="items")

private List(Category> categories = new ArrayList<>();

 

*foreign key가 있는 items 클래스에 있는 item이 연관관계의 주인이다.

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

 

주의

실무에서 @ManyToMany는 사용하지 말자.

-실무에서는 다대 다관계로 연관관계를 풀어내지 말 것

-이러한 상태의 테이블만 구현이 가능하고, 다른 필드를 추가하는 것이 불가하다.

 

 

3. 카테고리 구조

 

카테고리가 계층구조로 내려간다.

위의 부모구조 아래에는 자식구조

 

실습

@ManyToOne
@JoinColumn(name ="parent_id")
private Category parent;

@OneToMany(mappedBy = "parent")
private List<Category> child = new ArrayList<>();

설명

-자식 카테고리는 여러개 가질 수 있다.

-셀프로 category안에서 이름만 다를 뿐이지 양방향 연관관계 매핑하듯이 해주면 된다.

 

자 이제 작성한대로 데이터베이스 테이블이 제대로 구성이 되었는지 확인해 보자.

그리고 실제 데이터베이스 테이블구성 및 데이터베이스 명령어 작성/실행

 

실습

create table orders (

order_id bigint not null,

order_date timestamp,

status varchar(255),

delivery_id bigint,

member_id bigint,

primary key (order_id)

);

-> 이것으로 실행시키면 원래 작성했던 코드대로 테이블 구성이 된다.

*JPAalter할 때 작성한 foreign키 컬럼을 전부 잡아준다.

 

참고

foreign key를 꼭 걸어야 되요 안 걸어야 되요?

-시스템마다 다르다.

-실시간 트래픽이 중요하고, 정확성보다는 잘 서비스가 되는 유연한 것이 중요하면

 foreign key를 빼고, 인덱스만 잘 잡아주면 된다.

-하지만, 돈과 관련된 중요한 것이라던가, 데이터가 항상 맞아야 하는 시스템이라면

 foreign key를 넣어주면 된다.

+ Recent posts