Announcement Announcement Module
Collapse
No announcement yet.
Preloading Set in HibernateCallback not working Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Preloading Set in HibernateCallback not working

    Hallo -- I have a DAO class that is preloading a Set that belongs to the class within a HibernateCallback. I have used this technique based on a tutorial in the IBM developerWorks, so the principle *should* be OK, unless anyone can tell me differently?
    This is the file AbstractDao.java where all the work is done:
    Code:
    package ukco.spint.dao;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.sql.SQLException;
    import java.util.Collection;
    import java.util.LinkedList;
    import java.util.List;
    
    import org.hibernate.HibernateException;
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.springframework.orm.hibernate3.HibernateCallback;
    import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
    
    public abstract class AbstractDao<domainObject>
    extends HibernateDaoSupport implements Dao<domainObject> &#123;
    	
    	private List<String> preloadProperties=new LinkedList<String>&#40;&#41;;
    	
    	public abstract domainObject getNewInstance&#40;&#41;;
    
    	@SuppressWarnings&#40;"unchecked"&#41;
    	public domainObject getById&#40;final long id&#41; throws PreloadPropertyException&#123;
    		HibernateCallback hc=new HibernateCallback&#40;&#41;&#123;
    			public Object doInHibernate&#40;Session session&#41; throws HibernateException, SQLException &#123;
    				domainObject obj=null;
    				Query query=session.createQuery&#40;"from "+getDaoClass&#40;&#41;.getName&#40;&#41;+" c where c.id=?"&#41;;
    				query.setString&#40;0,Long.toString&#40;id&#41;&#41;;
    				obj=&#40;domainObject&#41;query.list&#40;&#41;.get&#40;0&#41;;
    				try&#123;
    					doPreload&#40;obj&#41;;
    				&#125;catch&#40;PreloadPropertyException ppe&#41;&#123;
    					throw new HibernateException&#40;ppe&#41;;
    				&#125;
    				return obj;
    			&#125;
    		&#125;;
    		return &#40;domainObject&#41;getHibernateTemplate&#40;&#41;.execute&#40;hc&#41;;
    	&#125;
    	
    	@SuppressWarnings&#40;"unchecked"&#41;
    	public List<domainObject> getAll&#40;&#41; throws PreloadPropertyException&#123;
    		HibernateCallback hc=new HibernateCallback&#40;&#41;&#123;
    			public Object doInHibernate&#40;Session session&#41; throws HibernateException, SQLException &#123;
    				List<domainObject> lst=new LinkedList<domainObject>&#40;&#41;;
    				Query query=session.createQuery&#40;"from "+getDaoClass&#40;&#41;.getName&#40;&#41;&#41;;
    				List tmp=query.list&#40;&#41;;
    				try&#123;
    					for&#40;Object obj&#58;tmp&#41;&#123;
    						doPreload&#40;&#40;domainObject&#41;obj&#41;;
    						lst.add&#40;&#40;domainObject&#41;obj&#41;;
    					&#125;
    				&#125;catch&#40;PreloadPropertyException ppe&#41;&#123;
    					throw new HibernateException&#40;ppe&#41;;
    				&#125;
    				return lst;
    			&#125;
    		&#125;;
    		return &#40;List<domainObject>&#41;getHibernateTemplate&#40;&#41;.execute&#40;hc&#41;;
    	&#125;
    	
    	public void save&#40;domainObject obj&#41; &#123;
    		getHibernateTemplate&#40;&#41;.saveOrUpdate&#40;obj&#41;;
    	&#125;
    
    	public void delete&#40;domainObject obj&#41; &#123;
    		getHibernateTemplate&#40;&#41;.delete&#40;obj&#41;;
    	&#125;
    
    	@SuppressWarnings&#40;"unchecked"&#41;
    	public void delete&#40;long id&#41; &#123;
    		domainObject obj=&#40;domainObject&#41;getHibernateTemplate&#40;&#41;.load&#40;getDaoClass&#40;&#41;,new Long&#40;id&#41;&#41;;
    		delete&#40;obj&#41;;
    	&#125;
    	
    	public void addPreloadProperty&#40;String propName&#41; &#123;
    		String getterName=propertyNameToGetterName&#40;propName&#41;;
    		if&#40;!preloadProperties.contains&#40;getterName&#41;&#41;
    			preloadProperties.add&#40;getterName&#41;;
    	&#125;
    	public void removePreloadProperty&#40;String propName&#41; &#123;
    		String getterName=propertyNameToGetterName&#40;propName&#41;;
    		if&#40;preloadProperties.contains&#40;getterName&#41;&#41;
    			preloadProperties.remove&#40;getterName&#41;;
    	&#125;
    	public void addAllPreloadProperties&#40;&#41;&#123;
    		Class c=getDaoClass&#40;&#41;;
    		Method&#91;&#93; methods=c.getMethods&#40;&#41;;
    		for&#40;Method m&#58;methods&#41;&#123;
    			String methodName=m.getName&#40;&#41;;
    			if&#40;methodName.substring&#40;0,3&#41;.equals&#40;"get"&#41;&#41;
    				preloadProperties.add&#40;methodName&#41;;
    		&#125;
    	&#125;
    	public void clearPreloadProperties&#40;&#41;&#123;
    		preloadProperties.clear&#40;&#41;;
    	&#125;
    	
    	protected void doPreload&#40;domainObject obj&#41;
    	throws PreloadPropertyException&#123;
    		if&#40;preloadProperties.size&#40;&#41;==0&#41;
    			return;
    		Class c=obj.getClass&#40;&#41;;
    		try&#123;
    			for&#40;String methodName&#58;preloadProperties&#41;&#123;
    				Method getter=c.getMethod&#40;methodName,new Class&#91;&#93;&#123;&#125;&#41;;
    				Object tmp=getter.invoke&#40;obj,new Object&#91;&#93;&#123;&#125;&#41;;
    				if&#40;tmp instanceof Collection<?>&#41;&#123;
    					//TODO -- stop the display here
    					long s=&#40;&#40;Collection<?>&#41;tmp&#41;.size&#40;&#41;;
    					System.out.println&#40;"Collection length measured at&#58; "+Long.toString&#40;s&#41;&#41;;
    				&#125;
    			&#125;
    		&#125;catch&#40;NoSuchMethodException nsme&#41;&#123;
    			throw new PreloadPropertyException&#40;
    					"No such method name in class '"+c.getName&#40;&#41;+"'.",nsme&#41;;
    		&#125;catch&#40;IllegalArgumentException iae&#41;&#123;
    			throw new PreloadPropertyException&#40;
    					"Method has arguments in class '"+c.getName&#40;&#41;+"'.",iae&#41;;
    		&#125;catch&#40;IllegalAccessException iae&#41;&#123;
    			throw new PreloadPropertyException&#40;
    					"Cannot access the property in class '"+c.getName&#40;&#41;+"'.",iae&#41;;
    		&#125;catch&#40;InvocationTargetException ite&#41;&#123;
    			throw new PreloadPropertyException&#40;
    					"Cannot invoke the property in class '"+c.getName&#40;&#41;+"'.",ite&#41;;
    		&#125;
    	&#125;
    	
    	protected static String propertyNameToGetterName&#40;String propName&#41;&#123;
    		StringBuffer buf=new StringBuffer&#40;"get"&#41;;
    		buf.append&#40;propName.substring&#40;0,1&#41;.toUpperCase&#40;&#41;&#41;;
    		buf.append&#40;propName.substring&#40;1&#41;&#41;;
    		return buf.toString&#40;&#41;;
    	&#125;
    	
    	public abstract Class getDaoClass&#40;&#41;;
    &#125;
    The only two (abstract) methods here are getNewInstance() and getDaoClass(), which are overridden to create a new instance of a given class and to return the Class of that class respectively.
    I thought this class was very clever of me, until I realised I can't make it work.
    Basically, I wanted to subclass this, so that for any DAO I wrote, I would only have to call addPreloadProperty() before loading any POJO, and would have that POJO's desired properties (sets & other classes, etc.) force-loaded.
    & I really cannot see why this is not happening!
    A Set will load in doPreload(), it will still be there in getAll(), but when the POJO is returned, I get a Lazy Exception if I try to access it.
    I've tried to make my problem clear -- sorry if I failed!
    Can anybody suggest where I'm going wrong here?
    I've been trying to make this work for days, whilst deadlines are tearing my hair out!
    Thanks in advance,
    doug.

  • #2
    update

    Hmm. It appears it *does* work -- but only in debug mode when I very slowly step through the code!
    Can anyone advise?
    Cheers,
    doug.

    Comment

    Working...
    X