У меня возникли проблемы с загрузкой списка объектов из моей базы данных с использованием режима Hibernate и lazy = true.Надеюсь, что кто-то может помочь мне здесь.
У меня есть простой класс здесь, называемый UserAccount, который выглядит следующим образом:
public class UserAccount {
long id;
String username;
List<MailAccount> mailAccounts = new Vector<MailAccount>();
public UserAccount(){
super();
}
public long getId(){
return id;
}
public void setId(long id){
this.id = id;
}
public String getUsername(){
return username;
}
public void setUsername(String username){
this.username = username;
}
public List<MailAccount> getMailAccounts() {
if (mailAccounts == null) {
mailAccounts = new Vector<MailAccount>();
}
return mailAccounts;
}
public void setMailAccounts(List<MailAccount> mailAccounts) {
this.mailAccounts = mailAccounts;
}
}
Я отображаю этот класс в Hibernate через следующий файл сопоставления:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="test.account.UserAccount" table="USERACCOUNT">
<id name="id" type="long" access="field">
<column name="USER_ACCOUNT_ID" />
<generator class="native" />
</id>
<property name="username" />
<bag name="mailAccounts" table="MAILACCOUNTS" lazy="true" inverse="true" cascade="all">
<key column="USER_ACCOUNT_ID"></key>
<one-to-many class="test.account.MailAccount" />
</bag>
</class>
</hibernate-mapping>
Как видите, в элементе отображения пакетов для lazy установлено значение "true".
Сохранение данных в базе данных работает нормально:
Загрузка такжеработает, вызывая loadUserAccount(String username)
(см. код ниже):
public class HibernateController implements DatabaseController {
private Session session = null;
private final SessionFactory sessionFactory = buildSessionFactory();
public HibernateController() {
super();
}
private SessionFactory buildSessionFactory() {
try {
return new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public UserAccount loadUserAccount(String username) throws FailedDatabaseOperationException {
UserAccount account = null;
Session session = null;
Transaction transaction = null;
try {
session = getSession();
transaction = session.beginTransaction();
Query query = session.createQuery("FROM UserAccount WHERE username = :uname").setParameter("uname", username));
account = (UserAccount) query.uniqueResult();
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw new FailedDatabaseOperationException(e);
} finally {
if (session.isOpen()) {
// session.close();
}
}
return account;
}
private Session getSession() {
if (session == null){
session = getSessionFactory().getCurrentSession();
}
return session;
}
}
Проблема заключается в следующем: когда я получаю доступ к элементам в списке "mailAccounts", я получаю следующее исключение:
org.hibernate.LazyInitializationException: не удалось лениво инициализировать коллекцию ролей: test.account.UserAccount.mailAccounts, ни один сеанс или сеанс не был закрыт
Я предполагаю, что причиной этого исключения является то, чтоСессия была закрыта (не знаю, почему и как), поэтому Hibernate не может загрузить список.Как вы можете видеть, я даже удалил вызов session.close()
из метода loadUserAccount()
, но сессия все еще кажется закрытой или замененной другим экземпляром.Если я установлю lazy=false
, то все будет работать гладко, но это не то, что я хотел, потому что мне нужна функция загрузки данных «по требованию» из-за проблем с производительностью.
Итак, если я не уверенчто мой сеанс все еще действителен после завершения метода loadUserAccount(String username)
, какой смысл иметь эту функцию и как мне обойти это?
Спасибо за вашу помощь!
Ps: Яновичок в Hibernate, так что, пожалуйста, извините меня за noobishness.
Обновление: Вот мой config.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">foo</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mytable</property>
<property name="hibernate.connection.username">user</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<!-- Auto create tables -->
<!-- <property name="hbm2ddl.auto">create</property>-->
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Mappings -->
<mapping resource="test/account/SmampiAccount.hbm.xml"/>
<mapping resource="test/account/MailAccount.hbm.xml"/>
</session-factory>
</hibernate-configuration>
hibernate