일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 앙버터마카롱
- graphql mutation error
- 예쁜술집 예술
- 화이트해커를 위한 웹 해킹의 기술
- 금별맥주
- 운정 소바동
- 홍대 토라비
- apolloclient
- graphql react native
- 비동기배열
- graphql 400
- 신촌 소문난집
- 잠실새내 도그존
- 지보싶 신촌점
- promise메서드
- typescript
- graphql with reactnative
- promise처리
- 홍대 예술
- apollo react native
- 홍대 카페 장쌤
- graphql
- 화이트 해커를 위한 웹 해킹의 기술
- 도그존
- useMutation error
- 고르드
- graphql with RN
- 비동기배열처리방법
- 토라비
- 잠실새내
- Today
- Total
yehey's 공부 노트 \n ο(=•ω<=)ρ⌒☆
[BE/spring boot] JPA ManyToMany 테이블 수정하기 본문
Background
2023.11.27 - [개발/프로젝트] - [DB/RDBMS] ERD 설계
ERD 설계를 보면 one to many로 내역과 태그 테이블이 있다. 사실은 Many to Many 관계지만, many to many는 분리하는게 좋다고 들어서 one to many로 설계하고 관계 관련 테이블을 따로 만들도록 구성했었다.
현재 spring boot 의 ORM으로 JPA를 사용하고 있다. 그리고 JPA에서 entity를 정의하고 있고 내역 테이블과 태그 테이블을 many to many를 사용해서 관계를 정의해주었다. JPA에서 many to many로 정의하면 두 테이블의 관계 테이블이 자동으로 생성되는 것을 보고 적용해도 괜찮다고 판단해서 many to many로 두었다.
Issue
통계 기능을 추가하는 과정에서, tag 를 기반으로 내역을 가져와야하는 경우와 그 반대 경우로 조회하는 기능이 필요했다. JPA 쿼리를 사용해서 두 테이블의 관계 테이블을 사용하려 했으나, 해당 관계 테이블은 숨겨져 있기 때문에 임의로 사용하는게 불가능(혹은 내가 못찾았을 수도)했다. 또한 전체 합 SUM 과 같은 기능을 제공하려 했고, 필연적으로 쿼리를 사용했어야했다. 그래서 현 상태로는 내가 원하는 쿼리를 날리고 결과를 받을 수 없다.
My Solution
필요한 테이블은 내역과 태그의 연결 관계 테이블이었기 때문에, many to many로 연결하며 숨겨진 테이블로 자동 생성된 테이블을 entity로 명시해서 다루도록 수정할 것이다. ERD 에 그렸던 그대로 테이블을 수정한다.
기존 data는 혹시 모르니 통째로 덤프 뜨고 시작했다.
mysqldump -u root -p household_ledger > test.sql
Contents
기존 테이블에서의 @ManyToMany
를 지워줬다. tag,ledger에서는 @OneToMany
를, 관계 정의 테이블에서는 @ManyToOne
을 걸어줬다.
//TagLedger 관계 테이블
public class TagLedgerRelation {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "relation_id")
private Long id;
@ManyToOne
@JoinColumn(name = "tag_id")
private Tag tag;
@ManyToOne
@JoinColumn(name = "ledger_id")
private Ledger ledger;
}
지금와서 든 생각은 relation_id 는 굳이 없었어도 될거같다. tag_id, ledger_id를 복합키로 구성하는게 더 나았을 듯.
public class Ledger {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ledger_id")
private Long ledgerID;
@Column(name="date",nullable = false)
private LocalDate date;
@Column(name = "amount",nullable = false)
private Long amount;
@Column(name = "title",nullable = false)
private String title;
@Column(name="memo")
private String memo;
@OneToMany(mappedBy = "ledger") //TagLedgerRelation 테이블과의 관계
List<TagLedgerRelation> relation;
}
public class Tag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "tag_id")
private Long tagID;
@Column(name = "tag_name",nullable = false)
private String name;
@OneToMany(mappedBy = "tag") //TagLedgerRelation 테이블과의 관계
private List<TagLedgerRelation> relation;
}
관계를 위와 같이 정의해주고, entity 변경으로 인해 서비스 로직 등 다른 곳에서 발생한 오류들을 수정해주면 된다.
기존 덤프데이터가 있다면 반영해주면 된다.
나는 기존 table과 다르게 TABLE name 도 다르고 relation_id 열이 하나 늘어서 이를 수정하고 덤프데이터를 반영해주었다.
test.sql을 dumptest DB 로 불러오고
use dumptest;
create table tag_ledger_relation(
relation_id bigint NOT NULL auto_increment,
tag_id bigint,
ledger_id bigint,
PRIMARY KEY(relation_id)
); // entity가 된 ledger-tag 관계정의 테이블
// 기존 many to many에서 생성된 관계 테이블의 데이터를 새롭게 생성한 테이블에 insert
insert into tag_ledger_relation(tag_id,ledger_id)
select tag_id, ledger_id from ledger_tag_relation;
필요 없는 테이블은 정리하고 dumptest DB를 dump 뜨고, 실제 DB 날려주고 (test.sql 백업본이 있고, 개발환경이니까 가능..), 새롭게 dump 뜬 DB로 복구해준다.
잘 생성됐고 다행히도 데이터 손실 없이 수정할 수 있었다. 수정된 코드에서도 기존 코드들은 잘 동작했다.
이제 relation 테이블을 JPA repository에서 쿼리로 사용할 수 있다.
public interface TagLedgerRelationRepository extends JpaRepository<TagLedgerRelation,Long> {
@Query(value="select COALESCE(sum(r.ledger.amount),0) from TagLedgerRelation r where r.tag.tagID=:tagID and r.ledger.date>=:start and r.ledger.date<=:end and r.ledger.archiveTypeID.archiveTypeID=:archiveTypeID")
Long getTotalSumByTagAndDate(@Param(value = "tagID")Long tagID, @Param(value="start") LocalDate start, @Param(value = "end") LocalDate end,@Param(value = "archiveTypeID")Long archiveTypeID);
}
희희... 이제 통계 API 만들어야지......
Error Review
DB 설계할 때는 잘 해놓고.. 잘 안읽어서 이 사단을 내다니!!!! 그리고 many to many는 사용하는게 권장되지 않기 때문에 앞으로는 one to many 로 관계를 정의하는 방식으로 진행해야겠다.
참조
https://ict-nroo.tistory.com/127
https://www.baeldung.com/jpa-many-to-many
'개발 > 프로젝트' 카테고리의 다른 글
[spring boot] JPA table에 Boolean column 추가하기 (1) | 2024.01.21 |
---|---|
[Next js] recoil 전역 상태관리 적용하기 (0) | 2024.01.17 |
[Next js/react-query] react query 설치 및 적용하기 (0) | 2023.12.31 |
[FE/next js] 프론트 스택 정하기 및 next js 설치 (app router) (0) | 2023.12.17 |
[BE/spring boot] custom Response DTO 만들기 (0) | 2023.12.15 |