Существует проблема с стратегией наследования «таблица на подкласс» в Hibernate (5.2.2).Hibernate. Декартовы продукты при ленивой загрузке
Классы с картографирования (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;
}
Коллекция tests
от TestClass
мачте быть загружена из базы данных только тогда, когда доступ к нему (Ленивая загрузка).
При обращении к коллекциям после загрузки TestClass
сформированный sql-запрос с декартовым продуктом, где нет связи между таблицами (без 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)
}
}
Что такое неправильно в моем пример?