最近用ssh框架(struts2+spring+hibernate)开发一个查询系统,一张表对应一个查询页面,一共大概10张表,10张表之间没联系,但10张表都通过外键与另一张主表相关联。 表里面也没什么数据
tomcat跑起来后,我查询7、8次后就慢了,并且一直停在那里,我设置断点后,发现它停在:  Query query = createQuery(session, sql, null);那里,但没有错误信息输出,所在的方法是分页查询方法: 
/** 
 * 分页查询 
 * @param sql      查询的sql语句 
 * @param startRow 分页开始显示的纪录数 
 * @param pageSize 每页显示的数据条数 
 * @return 
 */ 
public List find(final String sql,final int startRow,final int pageSize) { 
log.debug("querying with no parameter"); 
try{ 
List result = this.getHibernateTemplate().executeFind(new HibernateCallback() { 
public Object doInHibernate(Session session) throws HibernateException, SQLException { 
    Query query = createQuery(session, sql, null); 
    query.setFirstResult(startRow); 
    query.setMaxResults(pageSize); 
    return query.list(); 

}); 
if (result == null || result.size()==0) { 
log.debug("query successful, no result found"); 
}  
else { 
log.debug("query successful, result size: " + result.size()); 

return result; 

catch(RuntimeException e){ 
log.error("query failed", e); 
throw e; 

} ssh框架的数据库以及事务配置: 
  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>        
     <property name="url" value="jdbc:oracle:thin:@210.1.4.38:1521:sscdev"/> 
    <property name="username" value="ssemem"/> 
    <property name="password" value="ssemem"/> 
  </bean> 
   
  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
     <property name="dataSource" ref="dataSource" /> 
  </bean> 
   
  <bean id="nativeJdbcExtractor" lazy-init="true" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"/>  
 <bean id="lobHandler" lazy-init="true" class="org.springframework.jdbc.support.lob.OracleLobHandler"> 
          <property name="nativeJdbcExtractor" ref="nativeJdbcExtractor"/> 
  </bean> 
   
  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
      <property name="dataSource" ref="dataSource"/> 
      <property name="mappingResources"> 
    <list>     
<!-- 一些映射文件的配置--> 
     <value>com/mem/entity/MmYcMembers.hbm.xml</value> 
     <value>com/mem/entity/MmItMainOfferMachine.hbm.xml</value> 
     <value>com/mem/entity/MmItMainInfo.hbm.xml</value> 
     <value>com/mem/entity/MmItMainOfferDatabase.hbm.xml</value> 
     <value>com/mem/entity/MmItMainCounterSystem.hbm.xml</value> 
     
        </list> 
</property> 
     <property name="hibernateProperties"> 
         <value>                 
            hibernate.show_sql=false 
            hbm2ddl.auto=update 
            hibernate.dialect=org.hibernate.dialect.OracleDialect 
         </value> 
      </property>  
  </bean> 
  <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory"/> 
  </bean> 
    <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> 
        <property name="transactionManager" ref="transactionManager"/> 
        <property name="transactionAttributes"> 
            <props> 
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> 
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> 
                <prop key="list*">PROPAGATION_REQUIRED,readOnly</prop> 
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> 
            </props> 
        </property> 
  </bean> 
  <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
       <property name="interceptorNames"> 
           <list> 
               <value>transactionInterceptor</value> 
           </list>              
       </property> 
        <property name="beanNames"> 
           <list> 
               <value>mainMachineService</value> 
           </list> 
       </property> 
  </bean> 
</beans> 
不知道什么原因,有没有人可以帮助我; 

解决方案 »

  1.   

    连接池没关吧.. 有
    conn.close()?
      

  2.   

    不用开启事务是什么意思?spring配置文件怎么配置呢?
      

  3.   

    ssh框架都是通过配置文件自动关闭的吧
      

  4.   

    是通过配置关闭的,但是是在web.xml里面配置的,你配置了吗,是一个过滤器,叫做OpenSessionInViewFilter
      <filter>
      <filter-name>hibernateFilter</filter-name>
      <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    </filter>

    <filter-mapping>
      <filter-name>hibernateFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
      

  5.   

    spring集成hibernate后session会自动关闭的吧?
      

  6.   

    session没关,我确定,我也遇到过
      

  7.   

    用了spring集成后
    get和load可以不用关session
    但是query还是要关吧
      

  8.   

    今天又看了下,是在分页查询记录总数时,查询了8次后停掉的。设置断点后发现停的地方是:Object result = query.uniqueResult();(见下),停了后又不报异常
    得到查询总数的代码为:
    /**
     * 得到查询的总记录数
     */

    public int getCount(String queryStr)throws Exception {
    String sql = "select count(*) ";
    sql += queryStr;
    Object result=this.get(sql);
    return Integer.parseInt(result.toString());
    }
    /**
     * 查询一条记录
     * @param sql 查询语句
     * @return
     */
    public Object get(String sql)throws Exception  {
    log.debug("querying with no parameter");
    try{
    Query query = this.createQuery(this.getSession(), sql, null);
    Object result = query.uniqueResult();
    if (result == null) {
    log.debug("query successful, no result found");
    } else {
    log.debug("query successful, result found");
    }
    return result;
    }
    catch(RuntimeException e){
    log.error("query failed", e);
    throw e;
    }
    catch(Exception ex){
    throw ex;
    }
    }
      

  9.   

    没啥,你去看看数据库连接,是不是
    1 已经满了
    2 有死锁我认为你的连接没有了,也就是你忘了关闭session来释放连接了。
      

  10.   

    怎么关闭呢?SSH框架不是自动帮你关闭吗?
      

  11.   

    你可以试试hibernate中设置二级缓存能不能解决你的问题
      

  12.   

     你可以对你的代码优化以下了,还可以在 hibernate 中设置缓存
      

  13.   

    还有就是不要每一次读数据都创建一个QUERY
    尽量减少与数据库的交互,
      

  14.   

    操作结束后忘了调用session.close()方法了吧
      

  15.   

    Spring会自动开启和关闭事务,这个不用担心。一般保存或更新开启事务就行了,查询是不需要开启事务的。置于查询速度很慢,可能有以下几点原因:1.Hibernate没有设置缓存,每次查询、保存、更新都会连接数据库。设置缓存后,如果是更新的话hibernate会自动同步数据库。如果是保存,保存后hibernate会将新保存的对象放到一级、二级缓存里面,下次更新直接从缓存拿数据就行了,不用每次都重新读取修改数据库。2.SessionPool满了,所以会造成长时间等待,可以把poolSize设大点。3.数据库死锁了,可以参考下所使用的数据库默认支持的事物级别,然后把它设置低一些,可以提高效率,当然是在保证满足业务需求不会出现问题的情况下。关于Spring中设置查询方法不开启事务的方法有如下两种:
    (1)基于xml方式配置不开启事务:
    部分配置如下:
    <bean id="txManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- 采用@Transanctional注解方式使用事务 -->
    <tx:annotation-driven transaction-manager="txManager" />
    <bean id="personService" class="com.yakoo5.service.impl.PersonServiceBean">
    <property name="dataSource" ref="dataSource" />
    </bean>
    <aop:config>
    <aop:pointcut expression="execution(* com.yakoo5.service.impl.*.*(..))" id="transanctionPointcut"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="transanctionPointcut"/>
    </aop:config>
    <tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
    <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>
    <tx:method name="*"/>
    </tx:attributes>
    </tx:advice>
    此配置会拦截所有的com.yakoo5.service.impl包和子包下的所有已采用注解方式配置事务的类的所有get方法。已只读方式访问数据库,且不会开启事务。(2)采用注解方式配置不开启事务
    以下是我以前写的一个类,可作参考用:
    package com.yakoo5.service.impl;import java.util.List;import javax.annotation.Resource;
    import org.hibernate.Query;
    import org.hibernate.SessionFactory;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;import com.yakoo5.bean.Person;
    import com.yakoo5.service.PersonService;@Transactional
    public class PersonServiceBean implements PersonService {
    @Resource
    private SessionFactory sessionFactory; public void save(Person person) {
    sessionFactory.getCurrentSession().persist(person);
    } public void update(Person person) {
    sessionFactory.getCurrentSession().merge(person);
    } public void delete(int personId) {
    sessionFactory.getCurrentSession()
    .delete(
    sessionFactory.getCurrentSession().load(Person.class,
    personId));
    } @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Person getPersonById(int personId) {
    return (Person) sessionFactory.getCurrentSession().get(Person.class,
    personId);
    } @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    @SuppressWarnings("unchecked")
    public List<Person> queryAll() {
    Query q = sessionFactory.getCurrentSession().createQuery("from Person");
    return q.list();
    }}注意红色部分的配置!已注解方式配置事务时要在bean.xml文件中加入以下配置信息<tx:annotation-driven transaction-manager="txManager" />还有记得引入tx命名空间。
      

  16.   

    由于以上代码没有正确显示红色,所以在此标注下(在Spring中采用注解方式配置不开启事务):
    只需在需要不开启事务的方法前加入如下注解即可:
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
      

  17.   

    资源的关闭很重要啊,不论 sql或 io 文件读写
      

  18.   

    后来问题找到了,是我在spring的applicationContext.xml的配置文件里,将service的id写成大写的了,就在:
    <property name="beanNames"> 
              <list> 
                  <value>mainMachineService </value> 
              </list> 
          </property> 
    里,我这里list中的value只写了一个,实际写了很多个,结果就粗心把其中的某个错写成大写了.
    不过还是谢谢大家了