当前位置: 首页 > 面试题库 >

防止推土机触发休眠延迟加载

乐正烨熠
2023-03-14
问题内容

我正在使用Spring事务,因此当POJO到DTO转换时,该事务仍然处于活动状态。

我想防止Dozer触发延迟加载,以使隐藏的sql查询永远不会发生:所有获取都必须通过HQL显式完成(以获得对性能的最佳控制)。

  1. 这是一个好习惯吗(我在任何地方都找不到它)?

  2. 如何安全地做?

我在DTO转换之前尝试了这个:

PlatformTransactionManager tm = (PlatformTransactionManager) SingletonFactoryProvider.getSingletonFactory().getSingleton("transactionManager");
tm.commit(tm.getTransaction(new DefaultTransactionDefinition()));

我不知道事务会发生什么,但是Hibernate会话不会关闭,并且仍然会发生延迟加载。

我尝试了这个:

SessionFactory sf = (SessionFactory) SingletonFactoryProvider.getSingletonFactory().getSingleton("sessionFactory");
sf.getCurrentSession().clear();
sf.getCurrentSession().close();

并且它可以防止延迟加载,但是在直接在应用程序层(在我的项目中称为“
facade”)中操纵会话是否是一种好习惯?我应该担心哪些副作用?(我已经看到涉及POJO->
DTO转换的测试不能再通过AbstractTransactionnalDatasource
Spring测试类启动,因为此类试图触发不再与活动会话链接的事务的回滚)。

我还尝试将传播设置为NOT_SUPPORTED或REQUIRES_NEW,但它会重用当前的Hibernate会话,并且不会阻止延迟加载。


问题答案:

我发现管理此问题的唯一通用解决方案(在研究了定制转换器,事件监听器和代理解析器之后)是实现定制字段映射器。我在Dozer
API中发现了该功能(我不相信它在《用户指南》中有记录)。

一个简单的例子如下:

public class MyCustomFieldMapper implements CustomFieldMapper 
{
    public boolean mapField(Object source, Object destination, Object sourceFieldValue, ClassMap classMap, FieldMap fieldMapping) 
    {       
        // Check if field is a Hibernate collection proxy
        if (!(sourceFieldValue instanceof AbstractPersistentCollection)) {
            // Allow dozer to map as normal
            return false;
        }

        // Check if field is already initialized
        if (((AbstractPersistentCollection) sourceFieldValue).wasInitialized()) {
            // Allow dozer to map as normal
            return false;
        }

        // Set destination to null, and tell dozer that the field is mapped
        destination = null;
        return true;
    }   
}

这会将所有未初始化的PersistentSet对象返回为null。我这样做是为了将它们传递给客户端时,我可以区分NULL(非加载)集合和空集合。这使我可以在客户端中定义通用行为,以使用预加载的集合,或进行另一个服务调用以检索集合(如果需要)。另外,如果您决定在服务层中急于加载任何集合,则它们将照常进行映射。

我使用spring注入自定义字段映射器:

<bean id="dozerMapper" class="org.dozer.DozerBeanMapper" lazy-init="false">
    <property name="mappingFiles">
        ...
    </property>
    <property name="customFieldMapper" ref="dozerCustomFieldMapper" />
</bean>
<bean id="dozerCustomFieldMapper" class="my.project.MyCustomFieldMapper" />

我希望这对任何寻求解决方案的人有所帮助,因为我在搜索Internet时找不到任何示例。



 类似资料:
  • 问题内容: 我遇到了一个问题,JPA试图在我不想要的时候延迟加载我的数据。从本质上讲,正在发生的事情是我正在使用Service检索一些数据,并且当我将这些数据解析为JSON时,JSON库正在触发hibernate模式以尝试懒惰地加载数据。有什么办法可以阻止这种情况?我在下面给出一个例子。 是否可以将JPA /hibernate设置为不尝试并延迟加载数据? 更新: 我意识到您可以使用FetchTyp

  • 问题内容: 我遇到了 一个 问题,即 一对一的延迟加载 在hibernate状态下不起作用。我 已经解决了它 ,但仍然 无法 正确 理解 会发生什么。 我的代码( 延迟加载在这里不起作用 ,当我拉人时-地址也被获取): 但是 :如果我添加 OneToOne关系,则延迟加载 效果很好 ! 问题/完整性: 请向我解释注释如何帮助实现延迟加载。 PS 我已经阅读了post1和post2的帖子,并了解了为

  • 问题内容: 我在spring使用Hibernate。 我有这样的模型班。 它通常可以正常工作,但是Category不会延迟加载,而是在ForumEntry加载后急切加载。 `` 完全没有将getter称为ForumCategory是在ForumTopic之后立即加载的。 这个问题出现在我所有的@ManyToOne关联中。但是,@OneToMany关联会延迟加载。 我正在使用maven2进行构建。这

  • 问题内容: 我的多对一映射存在性能问题。当我在日志文件中调试SQL查询时,可以进行主体查询,但是在我有其他表示多对一对象映射的查询之后。 Entity.hbm.xml: Object1.hbm.xml: Object2.hbm.xml: 查询HBM: 在pom.xml中 问题答案: 您是否尝试过像这样的FetchMode.SELECT?

  • 延迟异步函数的执行。 延迟执行 async 函数的一部分,通过把它放到 sleep 状态,返回一个 Promise 。 const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); async function sleepyWork() { console.log("I'm going to sleep for 1

  • 问题内容: 我相信只有两种使用Hibernate加载对象的方法,即延迟加载和一种渴望加载。延迟加载有其自身的优势,它不会加载很多对象,而只是在需要时才加载它们。我还了解到,如果您想强制为一个对象加载所有子代,则只需调用即可。假设我们有以下对象 假设我们有一些客户在我们的系统中有订单,并且该订单可能不止一个甚至为空。所以我的问题是,在这种情况下始终使用渴望加载会更好吗?我们需要与客户相关的订单的大小