论坛首页 Java企业应用论坛

有关OpenSessionInView模式的问题

浏览 16234 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-12-23  
第2个问题,看Juergen Hoeller的设计说明:
http://opensource.atlassian.com/projects/spring/browse/SPR-453
0 请登录后投票
   发表时间:2004-12-23  
看了Juergen Hoeller的设计说明我想我可以理解第一个问题了。

引用

Of course, you usually shouldn't have many transactions per request, so the number of Sessions kept open should be very small - hardly ever more than 2. The only effect to pay attention to here is that you cannot load an object in one transaction and save it in another, as both Sessions will still be open... (A persistent object should only be associated with one Session at the same time.)

这个正是第一个问题的所在吧,我在delete一个Parent的时候,传入的参数是getParentById(persistentClass, id)的结果。这就出现了和上面所说的一样的问题,我不能load an object in one transaction and save it in another, as both Sessions will still be open,同样道理应该也不能delete一个object吧。
而如果调用的是getHibernateTemplate().delete("FROM parent in class com.joa.po.Parent WHERE parent.id =" + id);,并没有load一个Object作为参数传入,而是直接采用语句删除,就不会有上述问题了。


至于我的第二个问题,就是iterator的问题,我还是没有得到答案,我把错误描述得清楚一点吧:
我在在web.xml中定义OpenSessionInView模式:
<filter>
        <filter-name>OpenSessionInViewFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate.support.OpenSessionInViewFilter</filter-class>
    	<init-param> 
            <param-name>singleSession</param-name> 
            <param-value>false</param-value> 
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>OpenSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

调用DAO函数:
public int getParentCount(); { 
                Iterator iter = getHibernateTemplate();.iterate("SELECT count(*); FROM parent in class com.joa.po.Parent");; 
                return ((Integer);iter.next(););.intValue();; 
        } 

可以正确返回结果。
如果我把web.xml中的OpenSessionInView模式去掉。再调用同样的DAO函数,却出现了以下的错误:
引用

java.sql.SQLException: Operation not allowed after ResultSet closed
at com.mysql.jdbc.ResultSet.checkClosed(ResultSet.java:4579)
at com.mysql.jdbc.ResultSet.next(ResultSet.java:2423)
at org.apache.commons.dbcp.DelegatingResultSet.next(DelegatingResultSet.java:168)
at net.sf.hibernate.impl.IteratorImpl.postNext(IteratorImpl.java:85)
at net.sf.hibernate.impl.IteratorImpl.next(IteratorImpl.java:127)
...
net.sf.hibernate.LazyInitializationException: Hibernate lazy instantiation problem
at net.sf.hibernate.impl.IteratorImpl.next(IteratorImpl.java:133)
               ...

我感觉我只是要得到所有parent的数量而已,和lazy应该无关吧,为什么会出现现在的问题呢?
0 请登录后投票
   发表时间:2005-02-04  
session关不掉和你用了直接getSession有关系:
Session session=getSession();
并且还没有closee session

改成用inner class多方便? 让Spring的template method帮你擦屁股就是了:
getHibernateTemplate();.execute(new HibernateCallback(); {
    public Object doInHibernate(Session session); throws HibernateException, SQLException {
    //session do what ever
    }
}



singleSession true和false的区别, 在那个链接里面Juergen Hoeller已经说得非常清楚了, 按照你的需求不同, 选择适合的就可以了, 偶反正都是用true的.

至于什么readOnly的东东, 没有遇到过, 弄一个简单的可以重现错误的包出来看看.
0 请登录后投票
   发表时间:2005-06-29  
inner class里怎么传参数啊?
public void deleteObject(Long id) {
  getHibernateTemplate().execute(new HibernateCallback() {
    public Object doInHibernate(Session session) throws HibernateException, SQLException {
      session.delete(id);
    }
});
}
0 请登录后投票
   发表时间:2005-06-30  
向内部类传递参数都是final的。
public void deleteObject(final Long id) {
getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
session.delete(id);
}
});
}
0 请登录后投票
   发表时间:2005-10-14  
downpour 写道
早上写了简单的测试,还是会遇到这样的问题。
环境:Tomcat5,mysql4.0,结构:struts+spring+hibernate
数据库表:parent( id, name)  child(id, name, parent_id)构成父子关系。
测试的DAO如下:

	public void saveOrUpdateParent(Parent p); {
		getHibernateTemplate();.saveOrUpdate(p);;
	}

	public void deleteParentById(Class persistentClass, Serializable id); {
		getHibernateTemplate();.delete(getObjectById(persistentClass, id););;
	}

	public Object getParentById(Class persistentClass, Serializable id); {
		return getHibernateTemplate();.get(persistentClass, id);;
	}

	public List getAllParent(Class persistentClass); {
		return getHibernateTemplate();.loadAll(persistentClass);;
	}

	public void deleteParent(Serializable id); {
		getHibernateTemplate();.delete("FROM parent in class com.joa.po.Parent WHERE parent.id =" + id);;
	}

	public int getParentCount(); {
		Iterator iter = getHibernateTemplate();.iterate("SELECT count(*); FROM parent in class com.joa.po.Parent");;
		return ((Integer);iter.next(););.intValue();;
	}


applicationContext.xml大致如下:
<beans>
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>/WEB-INF/jdbc.properties</value>
            </list>
        </property>
    </bean>
    
    <!-- dataSource -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName">
            <value>${jdbc.driverClassName}</value>
        </property>
        <property name="url">
            <value>${jdbc.url}</value>
        </property>
        <property name="username">
            <value>${jdbc.username}</value>
        </property>
        <property name="password">
            <value>${jdbc.password}</value>
        </property>
    </bean>

    <!-- Hibernate SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
        <property name="dataSource"><ref local="dataSource"/></property>
        <property name="mappingResources">
            <list>
                <!-- Add list of .hbm.xml files here -->
                <value>com/joa/po/Parent.hbm.xml</value>
                <value>com/joa/po/Child.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.Provider</prop>             
            <prop key="hibernate.show_sql">true</prop>
        </props>
        </property>
    </bean>

          
    <!-- Add DAOs here -->
    <bean id="parentDAO" class="com.joa.dao.impl.ParentDAOImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
    </bean>
    
        
    <!-- Add Managers here -->
       <bean id="parentServiceTarget" class="com.joa.service.impl.ParentServiceImpl"> 
    	<property name="parentDAO"><ref local="parentDAO"/></property>
    </bean>
    
    <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref local="sessionFactory"/>
        </property>
    </bean>
    
    <bean id="service" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    	<property name="transactionManager"> 
    		<ref local="transactionManager"/> 
    	</property> 
    	<property name="target">
    	              <ref local="parentServiceTarget"/>
    	</property>
    	<property name="transactionAttributes">
            <props>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="delete*">PROPAGATION_REQUIRED</prop>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>				
            </props>
        </property> 
    </bean>
    
     
</beans>

测试的结果大概是这样:
1、在使用OpenSessionInView模式的情况下,调用deleteParentById这个函数,测试不通过,报的错是:有两个session存在,无法绑定。但是调用deleteParent(Serializable id); 却是通过的,可以正确删除。
2、在使用OpenSessionInView模式的情况下,调用getParentCount(); 这个函数可以正确得到结果,但是如果在不用OpenSessionInView模式的情况下,调用这个函数,会报一个lazy problem的错。我不明白的是,这个地方难道用到lazy了嘛?



<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
</props>


getHibernateTemplate().delete(getObjectById(persistentClass, id));
这样会嵌套两个事务。一个是delete,一个是getObjectById! getHibernateTemplate里的Session创建了两次,这是出错的原因吧
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics