2016-09-22 3 views
0

Hibernate (5.2.2)의 상속 전략 "table per subclass"에 문제점이 있습니다. 매핑최대 절전 모드. 게으른 로딩 콜렉션의 데카르트 제품

클래스 (gettters 및 호텔은 나열되지 않습니다) :

//Class with shared fields 
@MappedSuperclass 
public class DBObject { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    protected Integer id; 

    @Column(name = "correctdt") 
    @Temporal(TemporalType.TIMESTAMP) 
    protected Date correctDate; 

    @Override 
    public boolean equals(Object o) { 
     boolean result = false; 
     if (o != null && (o instanceof DBObject)) { 
      DBObject oo = (DBObject) o; 
      if (id != null) { 
       result = id.equals(oo.id); 
      } 
     } 

     return result; 
    } 

    @Override 
    public int hashCode() { 
     return (id != null) ? id.hashCode() : 0; 
    } 
} 


//Class with a collection of items with inheritance. 
@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
@Table(name = "tmp_test_class") 
public class TestClass extends DBObject implements Serializable{ 
    @OneToMany(mappedBy = "testClass") 
    protected Collection<TestParent> tests = new ArrayList<>(); 
} 


//Parent class 
@Entity 
@Table(name = "tmp_test_parent") 
@Inheritance(strategy = InheritanceType.JOINED) 
public class TestParent extends DBObject implements Serializable{ 
    @Column 
    private String name; 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "test_id") 
    protected TestClass testClass; 
} 


//Subclass 
@Entity 
@Table(name = "tmp_test_child1") 
public class TestChild extends TestParent{ 
    @Column 
    private String field1; 
} 

컬렉션 TestClass 비만에서 tests가 데이터베이스에서로드 할 경우에만 접근이 (게으른 로딩).

TestClass을로드 한 후 콜렉션에 액세스 할 때 테이블간에 연결이없는 데카르트 제품과 함께 구성된 sql-query (LEFT OUTER JOIN 제외).

SELECT tests0_.test_id AS test_id4_2_0_, 
    tests0_.id   AS id1_2_0_, 
    tests0_.id   AS id1_2_1_, 
    tests0_.correctdt AS correctdt2_2_1_, 
    tests0_.name   AS name3_2_1_, 
    tests0_.test_id  AS test_id4_2_1_, 
    tests0_1_.field1  AS field1_0_1_, 
    CASE 
    WHEN tests0_1_.id IS NOT NULL 
    THEN 1 
    WHEN tests0_.id IS NOT NULL 
    THEN 0 
    END AS clazz_1_ 
FROM tmp_test_parent tests0_, 
    tmp_test_child1 tests0_1_ 
WHERE tests0_.test_id=? 

FetchType = EAGER으로 설정하면 수집이 올바르게로드됩니다. 그러나 컬렉션이 대부분의 경우 필요하지 않으므로 요청시로드해야합니다. 상속 클래스

테이블 :
tmp_test_parent (3 기록)

"ID" "NAME" "TEST_ID" "CORRECTDT" 
    1  "11"  1  14.09.16 12:31:40 
    2  "22"  1  21.09.16 12:31:46 
    3  "33"  1  21.09.16 12:31:51 

tmp_test_child (2 개 기록) 시험에

"ID" "FIELD1" "CORRECTDT" 
1   111  21.09.16 12:32:26 
3   333  21.09.16 12:32:28 

등급 :

//Class for testing 
public class MainClass { 
    public static void main(String[] args) throws Exception { 

     Session session = HibernateSessionFactory.getSessionFactory().openSession(); 

     //Loading class, that contains collection 
     TestClass test = session.get(TestClass.class, 1); 
     //Loading collection 
     Collection<TestParent> tests = test.getTests(); 

     System.out.println(tests.size()); //Incorrect result (6 entries) 

     //Loading collection directly 
     Collection<TestParent> tests2 = session.createCriteria(TestParent.class) 
       .add(Restrictions.eq("testClass.id", 1)) 
       .list(); 

     System.out.println(tests2.size()); //Correct result (3 entries) 
    } 
} 

은 무엇인가 내 잘못이야. 예?

답변

0

이 문제는 오라클 데이터베이스에서만 발생하는 것으로 실험적으로 밝혀졌습니다. MySQL에서는 Hibernate가 정확한 sql-query를 생성한다 :

SELECT tests0_.test_id AS test_id4_2_0_, 
    tests0_.id   AS id1_2_0_, 
    tests0_.id   AS id1_2_1_, 
    tests0_.correctdt AS correctd2_2_1_, 
    tests0_.name   AS name3_2_1_, 
    tests0_.test_id  AS test_id4_2_1_, 
    tests0_1_.field1  AS field1_0_1_, 
    CASE 
    WHEN tests0_1_.id IS NOT NULL 
    THEN 1 
    WHEN tests0_.id IS NOT NULL 
    THEN 0 
    END AS clazz_1_ 
FROM tmp_test_parent tests0_ 
LEFT OUTER JOIN tmp_test_child1 tests0_1_ 
ON tests0_.id  =tests0_1_.id 
WHERE tests0_.test_id=? 
관련 문제