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 가 필요가 없음.
'Spring > Spring Data JPA' 카테고리의 다른 글
IntelliJ + Gradle로 Spring Data Jpa @ManyToOne 양방향 Mapping하기 (5) | 2017.06.28 |
---|---|
Spring Data Jpa @Discriminator 다대일 Mapping (0) | 2017.06.28 |
@DiscriminatorColumn을 이용한 Spring Data Jpa 상속관계(Inheritance) 매핑 하기 (2) | 2017.06.22 |
Spring Data Jpa로 Restful API구축 할 때 날짜 출력 설정 (0) | 2017.06.02 |
그래들(gradle)로 스프링 부트 JPA 빌드하고 DB연동 하는 예제 (2) | 2017.05.09 |
Spring Data JPA 날짜 between (4) | 2017.04.27 |
왜 ItemRepository가 필요 없나요??
아주 오래전에 있었던 이슈네요. 그때 후루룩 정리해서 잘 기억은 나지 않지만,
제가 고전했던 이유는 부모 클래스인 ItemRepository로 db 액세스를 시도했기 때문입니다.
Item클래스는 추상클래스 이기 때문에 Item클래스를 구현한 클래스인 Album Repository만 있으면 Item과 Album table에 crud를 할 수 있습니다.