티스토리 뷰

Spring Data Jpa 상속관계(Inheritance) 매핑 하기

 

Spring Data Jpa를 이용해 Restful Api를 구축하는데 Domain설계부터 다시 하고있습니다. 그런데 Dynamic으로 해야 할 일이 있어서 이 기능을 알아보게 되었습니다.

 

시나리오

교보문고에 가면 물건들(Item)을 파는데 앨범(Album)도 판다.

 

사용한것

Spring Data Jpa, Lombok.

MySql

Lombok을 사용했기 때문에 @Data 어노테이션이 있습니다.

사용한 전략은 조인 전략 매핑을 사용했습니다.

 

구조

item 이라는 table이 parent(부모), album 이라는 table이 child(자식)구조입니다.

 

Table

item과 album 2개만 해보았습니다.

item

CREATE TABLE `item` (
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(50) NOT NULL,
 `price` INT(11) NOT NULL,
 `dtype` VARCHAR(50) NOT NULL,
 PRIMARY KEY (`id`)
)

COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=2;

item(부모) 테이블을 만들 때 dtype컬럼을 추가 해주고 타입은 VARCHAR로 합니다.

 

album

CREATE TABLE `album` (
 `id` BIGINT(20) NOT NULL,
 `artist` VARCHAR(50) NOT NULL
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

table에 id는 만들어 주어야 합니다. id필드 이름은 부모 테이블의 id필드 이름과 동일한 이름을 쓰는게 기본값입니다. 이걸 바꿀려면 다른 어노테이션을 써야합니다.

 

엔티티(Entity)

Item.java

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="dtype")
@Data
public abstract class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private long id;
private String name;
private int price;

    }

부모 클래스는 추상(abstract) 클래스로 선언 해야 합니다.

 

Album.java

@Entity
@DiscriminatorValue("A")
@Data
public class Album extends Item {
private String artist;

   }

자식 클래스는 Id를 만들면 안됩니다.

 

리포지토리 인터페이스(Repository)

public interface AlbumRepository extends JpaRepository<Album, Long> { }

자식 클래스로 선언해야한다. 부모클래스로는 선언할 필요가 없습니다. ItemRepository 가 필요가 없음.

 

실행 코드

ItemRepositoryTest.java

    @RunWith(SpringRunner.class)

@SpringBootTest
@ActiveProfiles("dev")
public class ItemRepositoryTest {

    @Autowired
    AlbumRepository albumRepository;

    @Test
    public void saveAndFind() throws Exception {

        Album album = new Album();
        album.setName("hello");
        album.setPrice(2000);
        album.setArtist("kyeongrok");

        albumRepository.save(album);

    }
}

Test Class로 만들었는데 안에 있는 내용만 main()에 넣고 써도 됩니다.

부모 클래스(Item)가 abstract Class이므로 사용은 구현체인 자식(Album) 클래스를 사용해주는게 흐름상도 맞고 실제로도 맞는 사용 방법입니다.

이 예제를 마땅히 찾을만한데가 없어서 이 포스트를 쓰는것도 있습니다.

 

결과

Hibernate: insert into item (name, price, dtype) values (?, ?, 'A')

Hibernate: insert into album (artist, id) values (?, ?)

 

했던 났던 실수

1.부모 클래스를 추상(abstract) 클래스로 선언 하지 않은 것

2. missing column [id] jpa inheret - 1번 문제 때문에 났음

3. java.sql.SQLException: Parameter index out of range - 1번 문제 때문에 났음

4.자식 클래스에 @Id 넣은것 - 넣으면 안됨

5.부모 클래스로 Repository만든 것. ItemRepository 가 필요가 없음.

 

 

 

 

 

 

728x90
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함