본문으로 바로가기

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 가 필요가 없음.


end.







저작자 표시 비영리
신고

댓글을 달아 주세요