Spring-hibernate花费更多时间的原因是什么?

时间:2014-07-09 13:38:16

标签: java spring hibernate

目前,我在spring和hibernate上正在开发一个项目。我来到这里。获取记录并在JSP中显示这些记录需要更多时间。我把时间戳保存在各处,看看它需要花费更多时间:

Time @ HomeController[start] : 2014-07-09 18:58:52.621
**Time @ userService[start] : 2014-07-09 18:58:52.622**
**Time @ UserDao[start] : 2014-07-09 18:58:57.678**
Time before executing Query : 2014-07-09 18:58:57.678
Time After executing Query : 2014-07-09 18:58:59.272
Time @ UserDao[end] : 2014-07-09 18:58:59.272
Time @ userService[End] : 2014-07-09 18:59:00.068
Time @ HomeController[end] : 2014-07-09 18:59:00.068
Time stamp in JSP :2014-07-09 18:59:00.129

从上面的分析,从服务层到DAO层花了将近5秒钟,我将在下面提供服务和DAO代码:

UserService :

     public class UserServiceImpl implements UserService {  
    @Override  
    public List<User> getUserpagination(int page) {
        System.out.println("Time @ userService[start] : "+new Timestamp(new Date().getTime())); ----------- (1)
        List<User> u = userDao.getUserpagination(page);
        System.out.println("Time @ userService[End] : "+new Timestamp(new Date().getTime()));
        return u;
     }
  }  

UserDao :

    public class UserDaoImpl implements UserDao { 
      @Override  
      @Transactional  
      public List<User> getUserpagination(int page) {  

        System.out.println("Time @ UserDao[start] : "+new Timestamp(new Date().getTime())); ------- (2)


        return userlist;  

    } 

因此,从第(1)行到第(2)行需要5秒。任何人都可以解释为什么以及如何减少这段时间?

我从属性文件获取数据库连接:

jdbc.properties:

database.driver=oracle.jdbc.driver.OracleDriver 
database.url=jdbc:oracle:thin:@xxx.xxx.xxx.xx:1521:osm
database.user=osm  
database.password=xxxxxx  
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
hibernate.show_sql=true  
hibernate.hbm2ddl.auto=create/update   

以下是XML文件中的配置:

<context:property-placeholder location="classpath:jdbc.properties" />

<tx:annotation-driven transaction-manager="hibernateTransactionManager" />


<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${database.driver}" />
    <property name="url" value="${database.url}" />
    <property name="username" value="${database.user}" />
    <property name="password" value="${database.password}" />
</bean>


<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="annotatedClasses">
        <list>
            <value>com.xxx</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>

        </props>

    </property>

 </bean>

<bean id="hibernateTransactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

现在,我使用了HikariCP,我收到超时错误:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/springhiber1] threw exception [Request processing failed; nested exception is    org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate  Session for transaction; nested exception is org.hibernate.exception.GenericJDBCException:  Cannot open connection] with root cause
java.sql.SQLException: Timeout of 30000ms encountered waiting for connection.
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:192)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:91)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81)

1 个答案:

答案 0 :(得分:5)

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${database.driver}" />
    <property name="url" value="${database.url}" />
    <property name="username" value="${database.user}" />
    <property name="password" value="${database.password}" />
</bean>

在您的配置中,您使用的是DriverManagerDataSource,而这只是一个正确的数据源实现。它不是连接池。会发生什么是每个连接都是按需创建的,一旦需要关闭,它就会被关闭。这是性能的杀手。

如果要使用性能,请使用连接池。那里有很多实现

  1. Tomcat JDBC
  2. Commons DBCP
  3. C3P0
  4. HikariCP
  5. 只需用适当的连接池替换dataSource bean定义即可。例如,如果你想用HikariCP替换它,那么这样就可以了。

    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="shutdown">
        <property name="dataSourceClassName" value="oracle.jdbc.pool.OracleDataSource" />
        <property name="connectionTestQuery" value="SELECT 1 FROM DUAL" />
        <property name="dataSource.user" value="${database.user}" />
        <property name="dataSource.password" value="${database.password}" />
        <property name="dataSource.url" value="${database.url}" />
    </bean>
    

    当然,您必须为池本身添加依赖项。

    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
        <version>1.4.0</version>
        <scope>compile</scope>
    </dependency>
    

    有关您可以设置哪些属性的信息,请参阅HikariCP documentation和Oracle数据源documentation

    另一件事是你的代码库分散了线来衡量性能,这真的不是最明智的事情,也不是非常有效。我建议使用一点AOP将性能测量应用到您的代码中,然后您可以在生产中轻松删除它。现在你必须清理整个代码库。

    Spring已经有PerformanceMonitorInterceptor你可以使用和配置。如果您想要更精细的测量,可以使用JamonPerformanceMonitorInterceptor

    <bean id="performanceInterceptor" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>
    
    <aop:config>
        <aop:pointcut id="ourMethods" expression="execution(* com.your.base-package..*.*(..))"/>
        <aop:advisor pointcut-ref="ourMethods" advice-ref="performanceInterceptor"/>
    </aop:config>
    

    现在,您有一种不显眼的测量和记录性能的方法。保持您的代码干净整洁,您可以衡量您想要的。