У меня проблема с управлением коллекциями, поддерживаемыми Hibernate. Проблема проиллюстрирована в коде ниже; кратко
- Запущены один сеанс и транзакция.
- Все экземпляры ClassA загружаются и проходят, чтобы заставить Hibernate загрузить все экземпляры ClassC. На данный момент все экземпляры ClassC фактически загружаются с помощью отложенной выборки.
- В одной транзакции и сеансе загружаются все экземпляры ClassB.
- Все экземпляры ClassC больше не доступны (содержащиеся коллекции пусты) и не лениво загружаются по запросу.
Какой лучший способ загрузить необходимые наборы данных и сохранить их в памяти?
Примечания
Проект находится в режиме быстрого прототипирования, поэтому я использую один сеанс и один
транзакция для загрузки двух больших порций данных приложения. Это также настольное приложение, поэтому использование одного сеанса и транзакции может даже не стать проблемой в долгосрочной перспективе, если код работал.
Я установил ehcache и отладчик, показывающий, что Hibernate обнаружил файл конфигурации ehcache. Кеш настроен так, что
maxElementsInMemory="5000000"
eternal="true"
тайм-ауты установлены на 20 минут, даже если для вечного задано значение true, просто чтобы убедиться, что время сеанса не истекло.
Размер набора данных не особенно велик, около 100 тыс. Записей.
Модуль Hibernate 3.0 в комплекте с NetBeans использовался для создания шаблонов классов из модели данных.
Файл сопоставления выглядит примерно так:
<hibernate-mapping>
<class catalog="myCatalog" name="ClassA" table="classA">
<id ... </id>
<set inverse="true" name="classCs" sort="natural">
<key>
<column length="12" name="mykey" not-null="true"/>
</key>
<one-to-many class="ClassC"/>
</set>
</class>
</hibernate-mapping>
Определения классов:
@Entity
@Table(name = "classA", catalog = "myCatalog")
public class ClassA implements java.io.Serializable {
private SortedSet<ClassC> classCs = new TreeSet<ClassC>();
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "ClassA")
public SortedSet<ClassC> getClassCs() {
return this.classCs;
}
}
@Entity
@Table(name = "classB", catalog = "myCatalog")
public class ClassB implements java.io.Serializable {
// ... It is possible to walk collections in this class to reach some instances of classA.
}
public class ClassC implements java.io.Serializable {
// ... contains no collections
}
Проявление проблемы:
// in Hibernate Util
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
public static void main(String[] args) {
Application.session = HibernateUtil.getSessionFactory().openSession();
Application.tx = session.beginTransaction();
// Load data set 'A' and force collections to load
List<ClassA> listClassA = new ArrayList<ClassA>();
Query q = Application.session.createQuery("from ClassA as a").setReadOnly(true);
Iterator<ClassA> iterator = q.list().iterator();
while (iterator.hasNext()) {
ClassA ca = (ClassA)iterator.next();
// force member collection to load -- at present this is necessary even though FetchType is EAGER
ca.getClassCs();
listClassA.add(ca);
}
// The collections of classCs are in are in memory here
for(ClassA a : listClassA){
log.info(a.getId() + "-" + a.getClassCs().size());
}
// Load data set 'B'
List<ClassB> listClassB = new ArrayList<ClassB>();
String sq = "from classB as b where ...";
Query q = Application.session.createQuery(sq);
listClassB.addAll(q.list());
// The collections of classCs are NOT in memory and touching collections does not force reload
// The collections exist but now all have size zero
for(ClassA a : listClassA){
log.info(a.getId() + "-" + a.getClassCs().size());
}
return;
}