Currently, I am working on one project in spring and hibernate.I struck here. It is taking more time to fetch records and show those records in JSP. I kept Timestamps everywhere to see where it is taking more time:
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
From above analysis, it is taking almost 5 sec to go from Service layer to DAO layer and I am giving code of Service and DAO below:
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;
}
So, It is taking 5 sec to go from line (1) to line (2). Can anyone explain why and how to reduce that time?
I am getting database connection from properties file :
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
And below is the configuration in XML file :
<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>
Now, I used HikariCP and I am getting Timeout Error :
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)
<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>
In your configuration you are using the DriverManagerDataSource
whilst this is a proper datasource implementation it is only that. It is not a connection pool. What happens is that each connection is created on demand and as soon it needs to be closed it will be actually closed. This is a killer for performance.
If you want to have performance use a connection pool. There are plenty of implementations out there
Simply replace your dataSource
bean definition with a proper connection pool. For instance if you would want to replace it with HikariCP something like this would work.
<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>
And of course you will have to add the dependency for the pool itself.
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>1.4.0</version>
<scope>compile</scope>
</dependency>
For information on which properties you can set see the HikariCP documentation and Oracle Datasource documentation
Another thing is that your codebase is scattered with lines to measure performance, this really isn't the wisest thing todo nor very efficient. I suggest use a bit of AOP to apply performance measuring to your code, you can then easily remove it in production for instance. Now you have to cleanup your whole codebase.
Spring already has a PerformanceMonitorInterceptor
which you can use and configure. If you want more elaborate measuring you can use the 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>
Now you have an unobtrusive way of measuring and logging performance. Keeps your code clean and tidy and you can measure what you want.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments