`
liuye
  • 浏览: 53843 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

延迟加载异常时自动open session-Hibernate Lazy Loading patch

阅读更多

Hibernate Lazy Loading patch08-1-21

I was frustrated with the way that Hibernate handles lazy initialization, because there are certain cases, especially in a Swing application, where it is very difficult to efficiently preload all the data, and where unacceptable architecture modifications are required to ensure that all objects which might be lazy loaded are in an open, connected session.

To fix this, I've created what I think is a very small, non-disruptive patch to allow lazy loading outside of an open, connected session.

Steps 1 through 3 add pluggable collection loading to Hibernate, but do not actually change the way that Hibernate currently functions. Steps 4 and 5 are optional steps that takes advantage of this pluggable loading behavior to implement lazy loading with closed or disconnected sessions.

Step 1:

Modify the AbstractPersistenceCollection class. This is the only change to existing Hibernate code. Overwrite the initialize(boolean) method with the following code:

	protected final void initialize(boolean writing) {
		if (!initialized) {
			ProxyInitializer.sharedInstance().initializeCollection( this, initializing, session, getCollectionSnapshot() );
		}
	}
Step 2:

Create two new subclasses of LazyInitializationException:

public class SessionDisconnectedException extends LazyInitializationException {
	public SessionDisconnectedException(String msg) {
		super(msg);
	}
}

public class SessionMissingException extends LazyInitializationException {
	public SessionMissingException(String msg) {
		super(msg);
	}
}
Step 3:

Create a new class, org.hibernate.ProxyInitializer:

public class ProxyInitializer {
	private static ProxyInitializer sharedInstance;
	
	public static ProxyInitializer sharedInstance() {
		if( sharedInstance == null ) {
			sharedInstance = new ProxyInitializer();
		}
		return sharedInstance;
	}
	
	public static void setSharedInstance( ProxyInitializer initializer ) {
		sharedInstance = initializer;
	}
	
	public void initializeCollection(PersistentCollection collection, boolean initializing, SessionImplementor session, CollectionSnapshot snapshot) throws SessionMissingException, SessionDisconnectedException {
		if (initializing) {
			throw new LazyInitializationException("illegal access to loading collection");
		}
		if( session == null ) throwSessionMissingException("no session", snapshot);
		if( ! session.isOpen() ) throwSessionMissingException("session was closed", snapshot);
		if( ! session.isConnected() ) throwSessionDisconnectedException("session is disconnected", snapshot);
		
		session.initializeCollection( collection, false );
	}
	
	private void throwSessionMissingException(String msg, CollectionSnapshot snapshot) {
		String name = snapshot==null ? "" : " of role: " + snapshot.getRole();
		throw new SessionMissingException("failed to lazily initialize a collection" + name + " - " + msg);
	}
	
	private void throwSessionDisconnectedException(String msg, CollectionSnapshot snapshot) {
		String name = snapshot==null ? "" : " of role: " + snapshot.getRole();
		throw new SessionDisconnectedException("failed to lazily initialize a collection" + name + " - " + msg);
	}
}
Step 4:

If you do nothing at this point, then Hibernate will continue to work exactly as it previously did. However, you may choose to subclass ProxyInitializer and override the initializeCollection() method. You can call the super method, catch the exception, and then take some other action if you wish. For example, here is how I've implemented my lazy loading. Feel free to use this verbatim, or come up with your own implementation:

private class MyLazyLoader extends ProxyInitializer {
	public void initializeCollection(PersistentCollection collection, boolean initializing, SessionImplementor session, CollectionSnapshot snapshot) {
		try {
			super.initializeCollection(collection, initializing, session, snapshot);
		} catch( SessionDisconnectedException e) {
			session.reconnect();
			try {
				fetchInOpenSession(session, collection, initializing, snapshot);
			} finally {
				session.disconnect();
			}
		} catch(SessionMissingException e) {
			SessionImplementor lazySession = (SessionImplementor)mySessionFactory.openSession();
			try {
				fetchInOpenSession(lazySession, collection, initializing, snapshot);
			} finally {
				lazySession.close();
			}
		}
	}

	private void fetchInOpenSession(SessionImplementor lazySession, PersistentCollection collection, boolean initializing, CollectionSnapshot snapshot) {
		Transaction tx = null;
		try {
			tx = lazySession.beginTransaction();
			lazySession.lock( collection.getOwner(), LockMode.NONE );
			super.initializeCollection( collection, initializing, lazySession, snapshot );
			tx.commit();
		} catch(HibernateException e1) {
			if( tx != null ) tx.rollback();
			throw e1;
		}
	}
}
Step 5:

If you create your own subclass as in step 4, you need to set it as the shared static instance in ProxyInitializer, like this:

ProxyInitializer.setSharedInstance( new MyLazyLoader() );

That should be it... please let me know how well this works for you. I've tested this and it seems to work fine, but I have not used it in a complex application yet. I'd love to know what you think of this.

分享到:
评论

相关推荐

    Hibernate lazy延迟加载

    在Java的持久化框架Hibernate中,懒加载(Lazy Loading)是一种重要的优化策略,它的核心思想是“延迟加载”或“按需加载”。默认情况下,当一个实体被加载时,并不会立即加载其关联的对象或集合,而是在真正需要...

    blazor-lazy-loading:支持Blazor的自动延迟加载(服务器和WebAssembly)

    "blazor-lazy-loading"项目是针对这两种Blazor模式的一个解决方案,旨在提供自动延迟加载(lazy loading)功能。延迟加载是一种优化策略,它允许应用程序仅在需要时才加载资源,而不是一次性加载所有内容,从而减少...

    Laravel开发-eloquent-log-lazy-loading

    本话题主要关注Eloquent中的一个特性——延迟加载(lazy loading)以及如何记录或禁用它。延迟加载是一种优化策略,用于在需要时才加载关联的数据,而不是在查询时一次性加载所有数据,以此来提高性能。 1. Eloquent...

    基于Vue的延迟加载插件vue-view-lazy

    基于Vue的延迟加载插件vue-view-lazy 基于Vue的延迟加载插件vue-view-lazy是一款功能强大且灵活的插件,可以使图片或者其他资源进入可视区域后加载。该插件的主要目的是为了解决图片或者其他资源的延迟加载问题,...

    Hibernate延迟加载以及利用Spring

    延迟加载(Lazy Loading)是一种设计模式,其核心思想是在真正需要数据时才加载数据,而不是一开始就加载所有数据。这种策略能够有效地减少应用程序启动时的内存占用,提高系统的性能。 在Hibernate中,延迟加载...

    hibernate延迟加载解决

    在大型项目中,由于数据量庞大,为了提高性能和减少数据库的负载,Hibernate引入了“延迟加载”(Lazy Loading)机制。标题和描述提到的“hibernate延迟加载解决”主要涉及如何理解和解决与之相关的常见问题。 **1....

    yii2-lazy-loading-module:内容延迟加载模块

    Yii2 的延迟加载模块用于内容延迟加载的 Yii2 模块主要特点: 显示项目模式。 在后端和前端使用的概率灵活的模块配置安装安装此扩展的首选方法是通过 。 要么跑 ...

    hibernate 延迟加载深入剖析

    其中,延迟加载(Lazy Loading)是一种非常重要的特性,它可以显著提高应用程序的性能和响应速度。本文将对Hibernate中的延迟加载技术进行深入剖析,帮助读者更好地理解和运用这项技术。 #### 二、基本概念 ##### ...

    Lazy loading - eager loading

    In this article I want to discuss the lazy loading mechanism provided by NHibernate. It is recommended for maximum flexibility to define all relations in your domain as lazy loadable. This is the ...

    图片延迟加载-juery-lazyload

    图片延迟加载是一种优化网页性能的技术,它通过在用户滚动页面时才加载可见区域内的图片,而不是一次性加载所有图片。这显著减少了初次加载页面时的数据量,提升了网页的加载速度,尤其是对于图片丰富的网站来说,...

    markdown-it插件,支持Chrome 75的本机图像延迟加载-JavaScript开发

    安装$ npm install markdown-it-image-lazy-loading用法const md = require('markdown-it')(); const lazy_loading = require('markdown-it-im一个markdown-it插件,支持Chrome 75的本机图像懒加载。安装$ npm ...

    Hibernate延时加载与lazy机制.doc

    Hibernate的延迟加载(Lazy Loading)和懒加载机制(Lazy Initialization)是优化ORM框架性能的重要策略。这个机制的主要目的是提高程序的效率,减少不必要的数据库交互,只在真正需要数据时才去加载它们。以下是对...

    hibernate 延迟加载.docx

    在Java的持久化框架Hibernate中,延迟加载(Lazy Loading)是一种优化数据库访问性能的技术。它允许我们在需要时才加载关联的对象,而不是在初始查询时就一次性加载所有数据。这有助于减少不必要的数据库交互,从而...

    前端项目-vue-lazyload.zip

    Vue-lazyload 只会在图片进入浏览器视口时才开始加载,从而减少初始加载时的网络请求。 2. **改善用户体验**:由于图片的延迟加载,用户可以更快地看到页面主要内容,无需等待所有图片完全加载。这显著提升了用户...

    gilead hibernate lazyload例子

    懒加载是一种延迟加载策略,只在真正需要时才加载关联的数据,以减少内存消耗和提高响应速度。 Gilead,全称为Hibernate for Flex,是用于Flex和Hibernate之间的数据绑定工具,它提供了一种在Flex客户端和Hibernate...

    Hibernate集合属性的延迟加载.doc

    在 Hibernate 框架中,延迟加载(Lazy Loading)是一种优化数据访问性能的重要技术。它允许我们只在真正需要数据时才从数据库加载,避免一次性加载大量数据导致的内存消耗和性能瓶颈。当我们处理与实体相关的集合...

    Hibernate lazy加载FOR Connection

    标题中的“Hibernate lazy加载FOR Connection”指的是Hibernate框架中的一种特性,即懒加载(Lazy Loading)。在Hibernate中,懒加载是一种优化策略,它推迟对关联对象的加载,直到真正需要使用这些对象时才进行加载...

    Hibernate延迟加载

    延迟加载(Lazy Loading)策略允许我们仅在需要访问一个对象或其属性时才从数据库加载它们,而不是在初始加载实体时就一次性加载所有数据。这种机制可以避免在不必要的时候消耗额外的数据库资源,特别是当数据量大...

    react-list-lazy-load:延迟加载包装器,用于react-list

    React列表延迟加载 ...import LazyLoading from 'react-list-lazy-load' ; const MyList = ( { items , onRequestPage } ) => ( < LazyLoading length = { items . length } items = { items } onRe

Global site tag (gtag.js) - Google Analytics