단순히 Member만 뽑아 주는줄 알았지만 관련된 Team객체도 프록시로만 일단 전달은 해준다는 것이다.
Team 프록시 객체에서 Team 관련 작업을 하는 순간 Team 프록시가 초기화가 되고, 그때 Team select 쿼리도 날라온다.
아래는 예제 코드이고 빨간 글씨에 다다르면 그때 Team 프록시 객체도 초기화 된다.
Team team = new Team(); team.setName("teamA"); Member member1 = new Member(); member1.setUserName("member1"); member1.setTeam(team); em.persist(team); em.persist(member1); em.flush(); em.clear(); Member m = em.find(Member.class, member1.getId()); System.out.println("m = " + m.getTeam().getClass()); System.out.println(" ============================ "); m.getTeam().getName(); System.out.println(" ================================== "); tx.commit(); //이시점에 DB 쿼리가 날라감
JOINED 은 SINGLE_TABLE과는 달리 @DiscriminatorColumn 을 안써줘도 된다.
나는 굳이 써준거다.
빼면 이렇다.
굳이 타입을 정하지 않아도 뭐 개발하는 사람 입장에서는 무엇인지 유추가 가능하니까 안써도 된다.
시스템 운영할때는 사용하는것이 편하다.
JOINED는 테이블이 어떻게 생성될까.
create table Item ( id bigint not null, name varchar(255), price integer not null, primary key (id) )
create table Movie ( actor varchar(255), director varchar(255), id bigint not null, primary key (id) )
알아서 이렇게 생성해준다.
FK는? 이것도 뭐 자동이지 뭐.
alter table Movie add constraint FK5sq6d5agrc34ithpdfs0umo9g foreign key (id) references Item
ㅋㅋ대박이네!
아래는 실습코드다.
@Entity @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorColumn(name="TYPE_NAME") public class Item { @Id @GeneratedValue private Long id; private String name; private int price; public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getPrice() { return price; }
public void setPrice(int price) { this.price = price; } }
@Entity @DiscriminatorValue("MV") public class Movie extends Item{ private String director; private String actor; public String getDirector() { return director; }
public void setDirector(String director) { this.director = director; }
public String getActor() { return actor; }
public void setActor(String actor) { this.actor = actor; } }
단점 : 자식 entity가 안가지는 컬럼의 값을 null 허용해야함....(치명적, DBA 개빡침), 테이블이 커질수있다. 오히려 역효과 날수 있다.
상속을 받아서 테이블을 만들수도 있다.
기본적으로 @Entity는 당연히 써줘야 하는거고.
단순히 Movie클래스가 Item 클래스를 extends로 상속받는다고 입력하면 됨.
그리고 부모에 @Inheritance를 입력하면 default 값으로 상속 타입을 SINGLE_TABLE을 사용한다.
그럼 성능상 좋긴하다.
그리고 싱글 타입은 DTYPE이라고 자동 생성을해준다.
무슨 클래스를 가져왔는지 표시를 해준다는 것이다.
실행해보면 테이블 생성시 DTYPE이라고 자동 생성된다.
그리고 DTYPE이 아니라 컬럼명을 바꾸고 싶다면 @DiscriminatorColumn(name="~~~") 을 써주면 된다.
진짜 너무 JPA에서 자동으로 이놈이 무슨클래스지, 어디서 온놈이지? 라는것을 자동으로 생각해주니까 좀 이상하다.
적응이 안된다.
설마 이것까지 자동으로 해줄까? 라는 의심을 품고 실행하면 해주고 있다.
테이블을 DB에서 쿼리칠 필요가 없어서 미친듯이 편하다. 이런 미띤 ㅡㅡ
아래는 싱글 테이블 실습.
create table Item ( TYPE_NAME varchar(31) not null, id bigint not null, name varchar(255), price integer not null, artist varchar(255), autor varchar(255), isbn varchar(255), actor varchar(255), director varchar(255), primary key (id) )
@Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="TYPE_NAME") public class Item { @Id @GeneratedValue private Long id; private String name; private int price; public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getPrice() { return price; }
public void setPrice(int price) { this.price = price; } }
@Entity @DiscriminatorValue("MV") public class Movie extends Item{ private String director; private String actor; public String getDirector() { return director; }
public void setDirector(String director) { this.director = director; }
public String getActor() { return actor; }
public void setActor(String actor) { this.actor = actor; } }