保持开放的休眠会话,以使许多人恢复到一个POJO

问题描述 投票:1回答:1

我有2个POJO,事件和OrganizerProfile。他们的关系是一对多的。如果我从数据库中检索事件,则OrganizerProfile在调试器中显示为空,而不是应为空。另外,我必须将休眠会话保持打开状态才能调用event.getOrganizerProfile。

如果获得事件,请关闭休眠会话,则无法检索事件中的OrganizerProfile。

        new EventDTO(this.getEvtByDateAddress(_event.getDate(), _event.getAddress(), /*dont close sess*/false));

您能解释一下吗?

谢谢

<hibernate-mapping package="com.example.client.serializable">
   <class name="Event" table="event">
   <id name="oid" type="long" column="oid">
     <generator class="increment">
        <param name="initial_value">1</param>
     </generator>
  </id>
  <property name="evtName">
     <column name="evtName"/>
  </property>
  <property name="address">
     <column name="address"/>
  </property>
  <property name="date" type="date">
     <column name="date"/>   
  </property> 
  <many-to-one name="organizerProfile" cascade="all"></many-to-one>
</class>
</hibernate-mapping>

<hibernate-mapping package="com.example.client.serializable">
<class name="OrganizerProfile" table="organizerprofile">
  <id column="oid" name="oid" type="long">
  <generator class="increment">
    <param name="initial_value">1</param>
  </generator>
  </id>
  <property generated="never" lazy="false" name="acctOid">
    <column name="acctOid"/>
  </property>
  <property generated="never" lazy="false" name="email">
    <column name="email"/>
  </property>
  <property generated="never" lazy="false" name="name">
    <column name="name"/>
  </property>
  <property generated="never" lazy="false" name="contact">
    <column length="5120" name="contact"/>
  </property>
  <property name="profilePicName">
    <column name="profilePicName"/>
  </property>
</class>
</hibernate-mapping>

public Event getEvtByDateAddress(Date _date, String _address, boolean _closeSess)
{
    try
    {
        if(!session.isOpen())
        {
            session = HibernateUtil.getSessionFactory().openSession();
        }
        session.beginTransaction();
        Criteria criteria = session.createCriteria(Event.class);
        criteria.add(Restrictions.eq("date", _date));
        criteria.add(Restrictions.eq("address", _address));
        Event evt = (Event)criteria.uniqueResult();
        if(_closeSess)
        {
            session.close();
        }
        if (evt==null)
        {
            LogUtils.logInfo("The event does not exist: " + _date + " " + _address);
            return null;
        }
        else
        {
            return evt;
        }
    }
    catch(Exception e)
    {
        LogUtils.logInfo(e.toString());
        if(_closeSess)
        {
            session.close();
        }
        return null;
    }
}

public EventDTO(Event _event)
{
    this.oid=_event.getOid();
    this.evtName=_event.getEvtName();
    this.address=_event.getAddress();
    this.date=_event.getDate();
    this.evtPicName=_event.getEvtPicName();
    this.organizerProfile=new OrganizerProfileDTO(_event.getOrganizerProfile());
}
java hibernate one-to-many
1个回答
1
投票

<many-to-one name="organizerProfile" cascade="all"></many-to-one>

由于您没有在多对一映射中指定属性lazy,因此将对关联实体进行代理(请参见hibernate mapping documentation point 12),因此不会获取相关实体,并且无法在会话外部,内部访问您可以访问它的会话,因为当您尝试访问它时,休眠将自动获取它。

[如果要在会话外部访问相关实体,则必须手动获取它,让休眠在会话中都对其进行初始化-或者可以将获取类型设置为渴望(<many-to-one name="organizerProfile" cascade="all" lazy="false"></many-to-one>),我不建议这样做(N+1 selects Problem)。

使用代码手动获取的示例:

Criteria criteria = session.createCriteria(Event.class);
criteria.setFetchMode("organizerProfile", FetchMode.JOIN);
criteria.add(Restrictions.eq("date", _date));
criteria.add(Restrictions.eq("address", _address));

也可能有助于阅读:Hibernate 4.3 docs #20: Performance fetching

© www.soinside.com 2019 - 2024. All rights reserved.