继承策略存在问题"每个子类的表"在Hibernate(5.2.2)。
带有映射的类(未列出gettters和setter):
//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;
}
来自tests
的集合TestClass
只有在访问它时才会从数据库加载(延迟加载)。
在加载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 :(得分:0)
实验上发现问题只发生在Oracle数据库上。在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=?