0

我正在使用Hibernate 和 Struts

我们在休眠中使用延迟加载。

现在在 JSP 中我面临延迟加载异常,另一种解决方案是使用 EAGER,但我无法更改为其他应用程序的 Eager 依赖项。

专注于延迟加载有什么方法可以控制延迟加载异常?

4

3 回答 3

1

默认加载策略是LAZY对关联的集合使用获取。推荐的解决方案是通过在代码中在运行时覆盖此默认策略来加载关联的集合。QueryCriteria接口都支持这一点。

例如,如果您有以下实体关联映射:

public class XEntity {
...
private Set<YEntity> yentities;
}
}

然后使用Query接口,yentities可以XEntity像这样获取关联的内容:

String xSelect = "select x from XEntity "
                + "x left join fetch x.yentities "
                + "where x.xName=:xname";
Query query = session.createQuery(xSelect);

并且使用Criteria接口,可以这样做:

Criteria criteria = session.createCriteria(XEntity.class);
criteria.setFetchMode("yentities", FetchMode.JOIN);

这两个都将在单个选择中获取关联yentities的, 。XEntity

你也可以使用Hibernate#initialize来初始化集合:

XEntity xentity = (XEntity) session.get(XEntity.class, id);
Hibernate.initialize(xentity.getYentities());
tx.commit();
session.close();

但首先使用HQLorCriteria查询来获取完整的所需图表是一个好习惯。

于 2013-11-10T15:24:41.753 回答
0

避免延迟加载异常的常用方法是使用 fetch 连接。如果您有一个Employee延迟加载属性的实体projects,您将像这样重写查询:

SELECT e FROM Employee e
LEFT JOIN FETCH e.projects

您可能希望使用LEFT JOIN此处来获取所有员工,无论是否有项目。一个简单的JOIN FETCH会导致内部连接,只返回带有项目的员工。

触发延迟加载属性的加载的另一种不太明确的方法是在事务提交之前访问它们:

tx.begin(); // for illustration, also works for container managed transactions  
...
Employee emp = // get the employee
emp.getProjects().size();
...
tx.commit();

emp.getProjects()请注意,调用触发加载是不够的。您实际上需要执行一个需要属性值来触发加载的操作。

我通常更喜欢第一种方法,因为它更清楚地传达了意图。

于 2013-11-10T14:57:19.923 回答
0

只需在休眠和@NotFound 注释中使用事务管理器。

@Entity
public class OurEntity {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department")
    @NotFound(action=NotFoundAction.IGNORE)
    private LazyObject lazyObject;

    // ... getters, setters

}

public class SomeOtherClass {

@Autowired
private SessionFactory sessionFactory;

@Transactional(readOnly = false, rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public LazyObject getSomethingLazy(Long id){

     final OurEntity ourEntity = sessionFactory.getCurrentSession().get(OurEntity.class, id);
     LazyObject lazyObject = null;
     if(ourEntity != null){
         //this will never throw lazy loading exception if Transactional annotation is used
         lazyObject = ourEntity.getLazyObject();
     }
     return lazyObject;
}

和配置:

<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
   <property name="driverClass"><value>${public.jdbc.driverClassName}</value></property>
   <property name="jdbcUrl"><value>${public.jdbc.url}</value></property>
   <property name="username"><value>${public.jdbc.username}</value></property>
   <property name="password"><value>${public.jdbc.password}</value></property>

   <property name="idleConnectionTestPeriod" value="60"/>
   <property name="idleMaxAge" value="240"/>
   <property name="maxConnectionsPerPartition" value="1"/>
   <property name="minConnectionsPerPartition" value="1"/>
   <property name="partitionCount" value="3"/>
   <property name="acquireIncrement" value="5"/>
   <property name="statementsCacheSize" value="100"/>
   <property name="releaseHelperThreads" value="3"/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

    <property name="dataSource">
        <ref bean="dataSource" />
    </property>

    <property name="packagesToScan">
        <list>
            <value>packages.to.scan</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">DATABASE.DIALECT.CLASS.PATH</prop>
            <prop key="hibernate.connection.CharSet">utf8</prop>
            <prop key="hibernate.connection.characterEncoding">utf8</prop>
            <prop key="hibernate.connection.useUnicode">true</prop>
        </props>
    </property>
</bean>

<!--Transaction management -->
<bean id="transactionTemplate"
    class="org.springframework.transaction.support.TransactionTemplate">
    <property name="transactionManager" ref="transactionManager" />
</bean>

<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />

<!-- Transaction Manager is defined -->
<bean id="transactionManagerPublic" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
   <property name="sessionFactory" ref="sessionFactory"/>
</bean>
于 2015-08-27T20:18:22.390 回答