精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2004-07-29
不知道,你们在PO传递到View层的时候,是怎么处理这种延迟装载的问题。如果大家有讨论的兴趣,我可以继续贴上我差不多开发好的的代码,更详细的讨论这个话题。 当然,对于绝对反对PO传递到View的人来说,这个帖子就不是他们来讨论的地方了。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2004-07-29
引用 当然,对于绝对反对PO传递到View的人来说,这个帖子就不是他们来讨论的地方了。
这种没有意义的话就不用说了吧。 这论坛上好像不少人说问题不说重点,扯东扯西,敲敲打打。 |
|
返回顶楼 | |
发表时间:2004-07-29
简单的应用当然好。特别是连上来的用户不多的应用。
要用也简单,使用spring吧,不要你写一行代码--指的是opensessioninview的,至于配置当然也是要的,不过这比自己写可简单多了 |
|
返回顶楼 | |
发表时间:2004-07-29
BeanUtil类目的是为了对延迟装载集合进行装载。他这是调用get方法进行装载,我就在session中调用它来实现集合装载。多用户情况下,性能将是大的损失!这个很严重哦,但是对于一些需要访问集合数据的action来说,可以在DAO中限定这个方法,
package com.eibm.persistence.springhibernate; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.util.Collection; import java.util.Iterator; /** *@author firebody * utility class for dealing with java beans */ public class BeanUtil { /** * dumps the properties names and values of a bean * into a string * @param bean the JavaBean to be intropected * @return String a dump of the property names and values */ public static String toString( Object bean ); { StringBuffer buf = new StringBuffer();; if( bean != null ); { try { BeanInfo binfo = Introspector.getBeanInfo( bean.getClass(); );; PropertyDescriptor[] properties = binfo.getPropertyDescriptors();; if( properties != null ); { for( int i = 0; i < properties.length; i++ ); { Method readMethod = properties[i].getReadMethod();; if( readMethod != null ); { buf.append( properties[i].getName(); );; buf.append( " = " );; Object obj = readMethod.invoke( bean, null );; if( obj != null ); { buf.append( obj.toString(); );; } else { buf.append( "<empty>" );; } buf.append( "\n" );; } } } } catch( Exception e ); { // ignore exceptions thrown, this is a development aid } } return buf.toString();; } public static void loadCollectionsForLazy( Object bean ); { if( bean != null ); { try { BeanInfo binfo = Introspector.getBeanInfo( bean.getClass(); );; PropertyDescriptor[] properties = binfo.getPropertyDescriptors();; if( properties != null ); { for( int i = 0; i < properties.length; i++ ); { Method readMethod = properties[i].getReadMethod();; if( readMethod != null ); { Object object=readMethod.invoke( bean, null );; if(object instanceof Collection); initCollection(object);; /*System.out.println("In BeanUtil invokeAllReadMethods,The readed Methods:\n"+ "ReadMethod:\n"+readMethod.getName();+" Object:\n"+object);;*/ } } } } catch( Exception e ); { // ignore exceptions thrown, this is a development aid } } } /** * * @param o */ private static void initCollection(Object o);{ Collection collection=(Collection);o; Iterator iter=collection.iterator();; Object tmp; while(iter.hasNext(););{ tmp=iter.next();; } } } package com.eibm.persistence.springhibernate; import net.sf.hibernate.HibernateException; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.CleanupFailureDataAccessException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.orm.hibernate.SessionFactoryUtils; /** * Convenient super class for Hibernate data access objects. * * <p>Requires a SessionFactory to be set, providing a HibernateTemplate * based on it to subclasses. Can alternatively be initialized directly via a * HibernateTemplate, to reuse the latter's settings like SessionFactory, * flush mode, exception translator, etc. * * <p>This base class is mainly intended for HibernateTemplate usage * but can also be used when working with SessionFactoryUtils directly, * e.g. in combination with HibernateInterceptor-managed Sessions. * Convenience getSession and closeSessionIfNecessary methods are provided * for that usage. * * @author firebody * @since 28.07.2003 * @see #setSessionFactory * @see #setHibernateTemplate * @see org.springframework.orm.hibernate.HibernateTemplate * @see org.springframework.orm.hibernate.HibernateInterceptor */ public abstract class MyHibernateDaoSupport implements InitializingBean { protected final Log logger = LogFactory.getLog(getClass(););; private MyHibernateTemplate hibernateTemplate; /** * Set the Hibernate SessionFactory to be used by this DAO. */ public final void setSessionFactory(SessionFactory sessionFactory); { this.hibernateTemplate = new MyHibernateTemplate(sessionFactory);; } /** * Return the Hibernate SessionFactory used by this DAO. */ public final SessionFactory getSessionFactory(); { return hibernateTemplate.getSessionFactory();; } /** * Set the HibernateTemplate for this DAO explicitly, * as an alternative to specifying a SessionFactory. */ public final void setHibernateTemplate(MyHibernateTemplate hibernateTemplate); { this.hibernateTemplate = hibernateTemplate; } /** * Return the HibernateTemplate for this DAO, * pre-initialized with the SessionFactory or set explicitly. */ public final MyHibernateTemplate getHibernateTemplate(); { return hibernateTemplate; } public final void afterPropertiesSet(); throws Exception { if (this.hibernateTemplate == null); { throw new IllegalArgumentException("sessionFactory or hibernateTemplate is required");; } initDao();; } /** * Subclasses can override this for custom initialization behavior. * Gets called after population of this instance's bean properties. * @throws Exception if initialization fails */ protected void initDao(); throws Exception { } /** * Get a Hibernate Session, either from the current transaction or * a new one. The latter is only allowed if the "allowCreate" setting * of this bean's HibernateTemplate is true. * @return the Hibernate Session * @throws DataAccessResourceFailureException if the Session couldn't be created * @throws IllegalStateException if no thread-bound Session found and allowCreate false * @see org.springframework.orm.hibernate.HibernateTemplate */ protected final Session getSession(); throws DataAccessResourceFailureException, IllegalStateException { return getSession(this.hibernateTemplate.isAllowCreate(););; } /** * Get a Hibernate Session, either from the current transaction or * a new one. The latter is only allowed if "allowCreate" is true. * @param allowCreate if a new Session should be created if no thread-bound found * @return the Hibernate Session * @throws DataAccessResourceFailureException if the Session couldn't be created * @throws IllegalStateException if no thread-bound Session found and allowCreate false * @see org.springframework.orm.hibernate.SessionFactoryUtils#getSession(SessionFactory, boolean); */ protected final Session getSession(boolean allowCreate); throws DataAccessResourceFailureException, IllegalStateException { return (!allowCreate ? SessionFactoryUtils.getSession(getSessionFactory();, false); : SessionFactoryUtils.getSession(getSessionFactory();, this.hibernateTemplate.getEntityInterceptor();, this.hibernateTemplate.getJdbcExceptionTranslator();););; } /** * Convert the given HibernateException to an appropriate exception from * the org.springframework.dao hierarchy. Will automatically detect * wrapped SQLExceptions and convert them accordingly. * <p>Delegates to the convertHibernateAccessException method of this * DAO's HibernateTemplate. * @param ex HibernateException that occured * @return the corresponding DataAccessException instance * @see #setHibernateTemplate * @see org.springframework.orm.hibernate.HibernateTemplate#convertHibernateAccessException */ protected final DataAccessException convertHibernateAccessException(HibernateException ex); { return this.hibernateTemplate.convertHibernateAccessException(ex);; } /** * Close the given Hibernate Session if necessary, created via this bean's * SessionFactory, if it isn't bound to the thread. * @param session Session to close * @throws DataAccessResourceFailureException if the Session couldn't be closed * @see org.springframework.orm.hibernate.SessionFactoryUtils#closeSessionIfNecessary */ protected final void closeSessionIfNecessary(Session session); throws CleanupFailureDataAccessException { SessionFactoryUtils.closeSessionIfNecessary(session, getSessionFactory(););; } } /* * Created on 2004-7-29 * * To change the template for this generated file go to * Window&Preferences&Java&Code Generation&Code and Comments */ package com.eibm.persistence.springhibernate; import java.io.Serializable; import net.sf.hibernate.HibernateException; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; import org.springframework.dao.DataAccessException; import org.springframework.orm.hibernate.HibernateCallback; import org.springframework.orm.hibernate.HibernateTemplate; /** * @author firebody * To change the template for this generated type comment go to * Window&Preferences&Java&Code Generation&Code and Comments */ public class MyHibernateTemplate extends HibernateTemplate{ /** * Create a new MyHibernateTemplate instance. */ public MyHibernateTemplate(); { super();; } /** * Create a new MyHibernateTemplate instance. * @param sessionFactory SessionFactory to create Sessions */ public MyHibernateTemplate(SessionFactory sessionFactory); { super(sessionFactory);; setSessionFactory(sessionFactory);; afterPropertiesSet();; } /** * Create a new MyHibernateTemplate instance. * @param sessionFactory SessionFactory to create Sessions * @param allowCreate if a new Session should be created * if no thread-bound found */ public MyHibernateTemplate(SessionFactory sessionFactory, boolean allowCreate); { super(sessionFactory,allowCreate);; setSessionFactory(sessionFactory);; setAllowCreate(allowCreate);; afterPropertiesSet();; } public Object loadForBeanCollections(final Class entityClass, final Serializable id); throws DataAccessException { return execute(new HibernateCallback(); { public Object doInHibernate(Session session); throws HibernateException { Object object= session.load(entityClass, id);; System.out.println("load Entity:"+id+" "+"Now initial the "+id+" Entity 's collections-------------------------");; BeanUtil.loadCollectionsForLazy(object);; return object; } });; } } DAO : /* * Created on 2004-7-29 * * To change the template for this generated file go to * Window&Preferences&Java&Code Generation&Code and Comments */ package com.eibm.persistence; import java.util.Collection; import java.util.List; import java.io.Serializable; import com.eibm.domain.entity.Entity; import com.eibm.persistence.springhibernate.MyHibernateDaoSupport; /** * @author firebody * * To change the template for this generated type comment go to * Window&Preferences&Java&Code Generation&Code and Comments */ public class EntityDAOMyHibernateImpl extends MyHibernateDaoSupport implements EntityDAO { /* (non-Javadoc); * @see com.eibm.persistent.EntityDAO#addEntity(com.eibm.domain.entity.Entity); */ public Entity createEntity(Entity entity); throws Exception { Serializable id=getHibernateTemplate();.save(entity);; return (Entity);getHibernateTemplate();.load(entity.getClass();,id);; } /* (non-Javadoc); * @see com.eibm.persistent.EntityDAO#findEntity(java.lang.Class, long); */ public Entity findEntity(Class type, long id); throws Exception { return (Entity);getHibernateTemplate();.load(type,new Long(id););; } /* (non-Javadoc); * @see com.eibm.persistent.EntityDAO#updateEntity(com.eibm.domain.entity.Entity); */ public Entity updateEntity(Entity entity); throws Exception { getHibernateTemplate();.update(entity);; return (Entity);getHibernateTemplate();.load(entity.getClass(); , new Long(entity.getId();); );; } /* (non-Javadoc); * @see com.eibm.persistent.EntityDAO#delEntity(com.eibm.domain.entity.Entity); */ public Entity removeEntity(long id); throws Exception { Entity entity=(Entity);getHibernateTemplate();.load(Entity.class , new Long(id););; if(entity != null);{ getHibernateTemplate();.delete(entity);; return entity; } return null; } public void removeEntity(Entity entity); throws Exception{ getHibernateTemplate();.delete(entity);; } public List findAllEntities(); throws Exception{ return getHibernateTemplate();.find("from Entity as entity where entity.id != 0");; //return getHibernateTemplate();.find("from " + Entity.class.getName(););; } public void removeEntities(Collection entities); throws Exception{ getHibernateTemplate();.deleteAll(entities);; } } 上面代码带来的好处: 1)层次更清晰 2)对于view的操作更加简便,不用传递session到view中,比如这样举个例子: Group group=(Group);dao.findEntity(Entity.class , new Long(1););; req.setAttribute("group",group);; 视图编辑人员可以这样在视图开发: #foreach ($user in ${group.users} ); <br>$user.name <br>$user.email #end 上面的代码就已经很简洁了!当然这只是在实体类较为简单或者设计层次较为合理的情况下,才能发挥更好的更简洁的代码! |
|
返回顶楼 | |
发表时间:2004-07-31
这个做法不是open session in view吧?
通过调用getter,将延迟加载的数据读了进来。我也用过这种方式,事实上我认为这个方式更好。可以完全分开view与业务层。这个方式加载数据后就可以关闭session了。但由于没有元数据支持,还得手工指定哪些数据应该加载--我用了个笨方法,自己用类来封装元数据。否则的话,逐个调用getter,那不如不用延迟数据加载。 只加载需要的数据,加载完后关掉session,我认为这是改善性能最经济的办法。 我是用spring的beanwarpperimpl包装了一下object,然后就可以按名调用相应的getter了——当时还是用open session in view ,就把这个包装后的object直接丢到页面了,用velocity展现数据。通过按名调用增加了一点灵活性,做起来稍微好一点而已。 |
|
返回顶楼 | |
发表时间:2004-07-31
无明 写道 这个做法不是open session in view吧?
通过调用getter,将延迟加载的数据读了进来。我也用过这种方式,事实上我认为这个方式更好。可以完全分开view与业务层。这个方式加载数据后就可以关闭session了。但由于没有元数据支持,还得手工指定哪些数据应该加载--我用了个笨方法,自己用类来封装元数据。否则的话,逐个调用getter,那不如不用延迟数据加载。 只加载需要的数据,加载完后关掉session,我认为这是改善性能最经济的办法。 我是用spring的beanwarpperimpl包装了一下object,然后就可以按名调用相应的getter了——当时还是用open session in view ,就把这个包装后的object直接丢到页面了,用velocity展现数据。通过按名调用增加了一点灵活性,做起来稍微好一点而已。 呵呵,看看我的原文: 引用 open session在这种情况下,确实很不适合!作为替代,应该可以在DAO中对所有的延迟装载的集合进行初始装载,然后回传到view, 已经很强调了,不过这里还需要更改一下,不要覆写Load,而是另开一个load (booelan flag 。。)方法,不然会在删除或者更新集合的时候出现问题。 |
|
返回顶楼 | |
发表时间:2004-08-01
呵呵,我不是说这样做更好吗?这样分层更为彻底
我现在比较头疼的就是在对延迟装载的集合进行初始装载的方式 我并不想将所有延迟装载的集合都加载,只想加载页面要用的,因此觉得不该DAO中加载,而是在业务层加载 |
|
返回顶楼 | |
发表时间:2004-08-01
无明 写道 呵呵,我不是说这样做更好吗?这样分层更为彻底
我现在比较头疼的就是在对延迟装载的集合进行初始装载的方式 我并不想将所有延迟装载的集合都加载,只想加载页面要用的,因此觉得不该DAO中加载,而是在业务层加载 要实现你的需求应该也是很简单的!可以这样构造一个method Object load(Class type,Serializable id,boolean isLoadCollectionItem,String propertyName) { ...利用reflect与beanutil内省class,然后调用复合property的method,对集合进行遍历。 } 在你的业务层你可以这样写: 假设有个POJO: class BeanA{ ..... public Set getBeanBs(){ .... } .... public Set getBeanCs() { ... } .... } 如果要装载BeanCs集合的全部数据,你可以这样调用load parent=(Parent)dao.load(BeanA.class , id,true,"beanCs" ); 这样load出来的parent,即使在脱离session后,它对getBeanCs()返回的集合已经装载了所有数据,而别的集合我们并没有装载它的数据! 为了可扩展,你可以把这些配置写道XML文件,在load entity之前,读取配置文件的信息,来动态决定这个entity的那些集合需要装载数据! |
|
返回顶楼 | |
发表时间:2004-08-02
我有一个问题, 如果lazy loading的Collection里的元素, 其本身还有lazy loading的Collection, 那么不用open session in view的话, 如何能够简洁的处理呢?
我对于lazy loading的想法是, Hibernte为什么不采用re-open session的方式来处理呢? 查看过email list上关于这方面的讨论, hibernate team说这样会照成事务方面的问题. 但是我们对于这种lazy loading的应用, 通常都是在页面上做呈现, 不会对collection进行写的操作, 而对于读取到脏数据的问题, 影响不大. 所以我们是否可以考虑扩展Hibernate, 让其采用re-open a new session来处理lazy loading? 另外, 建议版主把这个帖子移动到hibernate讨论区去, 这样讨论的人可能会多一些. |
|
返回顶楼 | |
发表时间:2004-08-02
Quake Wang 写道 我有一个问题, 如果lazy loading的Collection里的元素, 其本身还有lazy loading的Collection, 那么不用open session in view的话, 如何能够简洁的处理呢?
我对于lazy loading的想法是, Hibernte为什么不采用re-open session的方式来处理呢? 查看过email list上关于这方面的讨论, hibernate team说这样会照成事务方面的问题. 但是我们对于这种lazy loading的应用, 通常都是在页面上做呈现, 不会对collection进行写的操作, 而对于读取到脏数据的问题, 影响不大. 所以我们是否可以考虑扩展Hibernate, 让其采用re-open a new session来处理lazy loading? 另外, 建议版主把这个帖子移动到hibernate讨论区去, 这样讨论的人可能会多一些. 移来移去,我都找不到了!!呵呵 re-open a new session可行吗?这个问题很值得探讨! re-open的概念也不是很清楚!是不是可以这样理解?: 1)re-oepn session代表一个全新设计的session实现对象!向sessionfactory声明,我需要一个re-open的session,sessioFactory创建一个特殊的session给你,再你调用close时并没有释放session cache,sessionfactory还需要为你保存这个session引用,以使得你在以后有可能的reopen而返回给你继续使用! 2)re-open session只是一个普通的现有的sesisonImpl,我们在关闭的时候这样调用:close(boolean reopenFlag),hibernate要做的就是在sessionFactory实现这个方法,以及对你的reopen提供一整套的实现!工作是不是很大呢? |
|
返回顶楼 | |