目前,我在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)
答案 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
,而这只是一个正确的数据源实现。它不是连接池。会发生什么是每个连接都是按需创建的,一旦需要关闭,它就会被关闭。这是性能的杀手。
如果要使用性能,请使用连接池。那里有很多实现
只需用适当的连接池替换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>
现在,您有一种不显眼的测量和记录性能的方法。保持您的代码干净整洁,您可以衡量您想要的。