I've been using c3p0 for connection pooling in my Spring Boot Application for a few months now. Everything was fine until about 2 weeks ago when I started experiencing connection issues especially in the morning. Every morning when I try to log-in to my application, it would throw a Could not open connection error. I would then restart my application in order to remove the problem. I am unable to figure out the root cause of the problem.
Here's my hibernate.cfg.xml:
hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydb?autoReconnect=true</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">abc123</property>
<property name="hibernate.dialect">config.CustomDialect</property>
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.initialPoolSize">5</property>
<property name="hibernate.c3p0.minPoolSize">5</property>
<property name="hibernate.c3p0.maxPoolSize">100</property>
<property name="hibernate.c3p0.checkoutTimeout">3000</property>
<property name="hibernate.c3p0.maxStatementsPerConnection">30</property>
<property name="hibernate.c3p0.unreturnedConnectionTimeout">3000</property>
<property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces">true</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="hbm2ddl.auto">update</property>
...
POJO mappings
</session-factory>
</hibernate-configuration>
Here's my HibernateUtil Class:
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
Configuration configuration = new Configuration().configure();
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties());
sessionFactory = configuration.buildSessionFactory(builder.build());
} catch (Exception ex) {
throw new ExceptionInInitializerError(ex);
}
}
public Session openSession() {
return sessionFactory.openSession();
}
}
I've added c3p0 debug configuration to my application to cull unreturned connections(in-case of a memory leak) and generate a stack-trace for it but nothing shows up in the logs.
Here's some of the logs from this morning :
https://pastebin.com/MGb4Miau
Can anyone here help me figure where the problem lies?
EDIT: CustomDialect Class:
public class CustomDialect extends MySQL5InnoDBDialect {
public String getTableTypeString() {
return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
}
}
This problem appear because you ran out of database connections.
too slow queries that hold the connection.
you have a lot of connection demands that can't fit the max pool size 100, it is the expected cause since the problem appear after a day of running.
or you have source leak, because you have not close the connection after ether the transaction success or failed.
From C3P0 logs on debug try to see how many connections are requested.
Also
Ideally, YOU must not use unreturnedConnectionTimeout in production, so you have to debug the connection leaks and when you have no more leaks remove
both unreturnedConnectionTimeout and debugUnreturnedConnectionStackTraces config.
Edit
try these config:
<property key="hibernate.connection.characterEncoding">UTF-8</property>
<property key="hibernate.connection.useUnicode">true</property>
Because sometimes the encoding in Hibernate is different from the encoding in MySQL db.
I finally figured out a solution to the problem. I made the following changes to my hibernate.cfg.xml:
<property name="hibernate.c3p0.maxIdleTime">10800</property>
<property name="hibernate.c3p0.maxIdleTimeExcessConnections">600</property>
And it works! The maxIdleTime property removes connections that have been idle from the pool for more than the specified time period(in seconds) which ensures that my connections are refreshed from time-to-time and maxIdleTimeExcessConnections lets me cull connections from the pool in excess of minPoolSize that have been idle for more than the specified time period(in seconds). This way I ensure that I don't have too many connections in the pool and that they all are fresh.
Related
In one of my question asked earlier I got to know that DriverManagerDataSource is NOT intended for production use. So I changed my configuration. I know I am using DBCP which is also outdated and a lot of other connection pools are available like HIkariCP and BOneCP but
I wish to understand the way how to verify that a pool has been setup
or not?
On searching a lot I got some answer at the following link
How would you test a Connection Pool
but I didn't get a way to verify programmatically. Also I cannot debug my jar files used for connection pooling because no source code is available. I dont know why but I can't change my jars for offical reasons.
The following are my configuration (OLD and NEW)
OLD
<bean id="webLogicXADataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="#[csa.db.driver]" />
<property name="url" value="#[csa.db.url]" />
<property name="username" value="#[csa.db.username]" />
<property name="password" value="#[csa.db.password]" />
</bean>
NEW
Using DBCP connection pool
<bean id="webLogicXADataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="#[csa.db.driver]" />
<property name="url" value="#[csa.db.url]" />
<property name="username" value="#[csa.db.username]" />
<property name="password" value="#[csa.db.password]" />
</bean>
OTHER ELEMENTS:(Thus far I have kept them same like they were earlier)
Place holder
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:${DB_PROPERTIES}</value>
</list>
</property>
<property name="placeholderPrefix" value="#[" />
<property name="placeholderSuffix" value="]" />
</bean>
Transaction Manager
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="webLogicXADataSource" />
<qualifier value="inventoryTxManager"/>
</bean>
DAOIMPL SAMPLE BEAN
<bean id="inventoryDao"
class="com.lxnx.fab.ce.icce.inventoryRoutingInvoice.dao.InventoryDaoImpl">
<property name="dataSource" ref="webLogicXADataSource" />
<property name="transactionManager" ref="transactionManager" />
Right now all the DAO classes in my project are singleton(no prototype property set for any of the beans)
The following is the sample java code of the DAOImpl.java class where I need to do all the transactions:
DAOImpl.java
public class InventoryDaoImpl implements InventoryDao {
private final static ISmLog iSmLog = Instrumentation
.getSmLog(LNConstants.SYSTEM_LOG_NAME);
private JdbcTemplate jdbcTemplate;
private DataSource dataSource;
private PlatformTransactionManager transactionManager;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.dataSource = dataSource;
}
public void setTransactionManager(
PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
#Transactional private void insertRelatedInfoData(
InventoryModel inventoryModel) {
final List<String> relatedLniList = inventoryModel.getArrRelatedLni();
final String documentLni = inventoryModel.getDocumentLNI();
String sql = "INSERT INTO SCSMD_REPO.INV_RELATED_INFO(LNI, RELATED_LNI) VALUES(?,?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
String relatedLni = relatedLniList.get(i);
ps.setString(1, documentLni);
ps.setString(2, relatedLni);
}
#Override
public int getBatchSize() {
return relatedLniList.size();
}
});
}
}
I am not getting any errors. Just wanted to verify If a pool has been setup U wish to verify the same
Are all configurations fine or did I miss something?? Please help me out with you valuable answers. thanks
If you don't have logs enable then you can't verify it. however there is one more donkey logic.
every database server will have timeout functionality. if db not hit by application after some time connection will break. for example mysql server will break it's connection from application after 8 hour (if there is no hit from application). you check modify timeout to minimum time (say 30 min)in mysql config file and check after 30 minutes you get connection close exception in you appication, when you hit db
The easiest way, as explained, would be to examine the logs. It's quite likely that a connection pool will log something, at least if your logging level is low enough.
Another way would be to examine the class of the Connection that the datasource returns. If you're dealing with a connection pool, the class will be a wrapper or a proxy class for that pool. The wrapper/proxy class makes sure that when you call close() the connection isn't really closed, it's just returned to the pool for further use. For example if you were to use HikariCP as your pool, you could check if(connection instanceof IHikariConnectionProxy) to see if the pool is being used.
Adding that kind of code in your software would be a bad idea in practically all cases. If you don't know whether a connection pool is being used or not, it's not something you solve with code. It's something you solve by reading and studying more.
You've also named your bean webLogicXADataSource even though nothing seems to support it being an XA datasource. Are you perhaps working on things a bit too advanced for you?
I'm using Hibernate 4.3.10 with Java 8.
To be more explicit see the following code example :
public static long createBlindStructure(BlindStructure pBlindStructure){
Transaction tcx = null;
SessionFactory factory = HibernateUtil.getSessionFactory();
Session session = factory.openSession();
int id = -1;
try{
tcx = session.beginTransaction();
id = session.save(pBlindStructure);
tcx.commit();
}
catch( Throwable e){
tcx.rollback();
}
finally{
session.close();
}
return id;
}
In my mind this method save() open session and transaction, save my object and close session and transaction. From save() I tried to get back the identifier as describe in javadoc. But It doesn't work, I see the request execute in my log (thanks to Hibernate debug mode).
Hibernate: insert into PokerLeagueManager.blindStructure (structureJson) values (?)
But when I try this :
public static long createBlindStructure(BlindStructure pBlindStructure){
Transaction tcx = null;
SessionFactory factory = HibernateUtil.getSessionFactory();
Session session = factory.openSession();
try{
tcx = session.beginTransaction();
session.save(pBlindStructure);
tcx.commit();
}
catch( Throwable e){
tcx.rollback();
}
finally{
session.close();
}
return pBlindStructure.getIdBlindStructure();
}
It correctly saved my object.
I test one more case :
Just returning a constant and don't put Id in the variable like first example and It work. It seems that object is not save in case I get the ID directly with session.save() method.
Moreover, I observe something interesting. I made a first test with one of the solution which worked, it generated a database data with Id 117. Then I changed my code for the solution which difsn't work and reloaded it in Tomcat , I made 2nd try without success. I changed again my code for the one which succeded and the id was generated is 120. It missed 2nf id number (the 2nd try I've done ??)
To help you see my hibernate.cfg.xml file
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
'-//Hibernate/Hibernate Configuration DTD 3.0//EN'
'http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'>
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name='connection.driver_class'>com.mysql.jdbc.Driver</property>
<property name='connection.url'>jdbc:mysql://XXXXXX:XXXX/PokerLeagueManager</property>
<property name='connection.username'>XXXXX</property>
<property name='connection.password'>XXXXXX</property>
<property name="show_sql">true</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">120</property>
<property name="hibernate.c3p0.min_size">1</property>
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.timeout">120</property>
<property name="hibernate.c3p0.acquireRetryAttempts">1</property>
<property name="hibernate.c3p0.acquireRetryDelay">250</property>
<!-- Dev -->
<property name="hibernate.c3p0.validate">true</property>
<!-- SQL dialect -->
<property name='dialect'>org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name='show_sql'>true</property>
<mapping resource="mappings/BlindStructure.hbm.xml"/>
<mapping resource="mappings/Tournament.hbm.xml"/>
<mapping resource="mappings/LegalFee.hbm.xml"/>
</session-factory>
Edit: User3813463 answer for a part of a question. It explains that session are in AUTO flush mode by default which flush session in some case like :
flush occurs by default at the following points:
before some query executions
from org.hibernate.Transaction.commit()
from Session.flush()
But I my point of view (I maybe miss understand something), my first case should worked because I commit my transaction.
Secondly, I need advise to choose a flush mode. To my mind Commit mode is a good way to do for method which make only inserting or only reading data on database.
Do you agree with me, have you some sources where this is debate?
This all is the magic of FlushMode read docs here
According to docs default FlushMode is AUTO that means
The Session is sometimes flushed before query execution in order to
ensure that queries never return stale state.
According to another document (Here):
flush occurs by default at the following points:
before some query executions
from org.hibernate.Transaction.commit()
from Session.flush()
So when you say pBlindStructure.getIdBlindStructure(); hibernate actually perform flush on current session, resulting data is getting saved in DB.
The session save method returns an object for the generated id by the generator. This value you should cast to Long.
long id = -1;
try{
tcx = session.beginTransaction();
id = (Long) session.save(pBlindStructure);
tcx.commit();
}
catch( Throwable e){
tcx.rollback();
}
finally{
session.close();
}
return id;
I am using a library where I need to get a data source and feed it into it. is there anyway I can get a connection from a connection pool? I am using Hibernate 4 with C3p0 connection pool.
here is my hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/sampleDB</property>
<property name="connection.username">root</property>
<property name="connection.password">mypass</property>
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="c3p0.max_size">100</property>
<property name="c3p0.min_size">1</property>
<property name="c3p0.idle_test_period">30</property>
<!-- SQL dialect -->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!-- Shows Generated SQL Queries By Hibernate -->
<property name="show_sql">false</property>
<!-- Drop and re-create The Database Schema on Start up -->
<property name="hbm2ddl.auto">update</property>
<property name="cache.provider.class">org.hibernate.cache.NoCacheProvider</property>
</session-factory>
</hibernate-configuration>
If you are using hibernate and you want access to the c3p0 Connection pool it is already using , one easy approach would be to use the C3P0Registry class to find the DataSource, see here and here.
Probably you will find that getPooledDataSources() returns a Set containing single element, and that will be the DataSource hibernate has constructed. If you want to, you can also set the config param c3p0.dataSourceName (hibernate.c3p0.dataSourceName in hibernate config), and use C3P0Registry.pooledDataSourcesByName( dataSourceName ).
[If you will set your own name, it would probably be worth verifying that hibernate is not using the dataSourceName property itself. I don't think that it does, but I haven't checked. The easiest way to check would be to look at your logs for the pools config dump on init, and make sure that there's something like "dataSourceName -> z8kflt8uqkl8iymaxxkw|729f44" in it. If the name is a long random-ish String with a pipe in it, it's an instance-specific autogenerated identity token and you should feel free to set your own name. If you see a more sensible name, then hibernate has already set this property and may be expecting the name you see, so you should look up that name.]
Note that if you plan to use Connections from the DataSource directly, take care to ensure that all Connections get properly close()ed in finally blocks. If you "leak" Connections, i.e. if you check them out and fail to check them back in reliably, you'll eventually exhaust the pool and freeze your hibernate app.
Good luck!
Update: Example...
import java.util.Set;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.C3P0Registry;
// you probably want better Exception handling than this...
private DataSource findUniqueDataSource()
{
Set set = C3P0Registry.getPooledDataSources();
int sz = set.size();
if ( sz == 1 ) // yay, just one DataSource
return (DataSource) set.iterator().next();
else
throw new RuntimeException("No unique c3p0 DataSource, found:" + sz);
}
// be sure you have configured a dataSourceName in your c3p0 or hibernate config
private DataSource findDataSourceByName( String dataSourceName )
{ return C3P0Registry.pooledDataSourceByName(dataSourceName); }
And no, you should not "leak" Connections and expect the pool to clean up after you. You can forget to close Statements and ResultSets, and the pool will take care of them when you close() the Connection, but the pool doesn't know when it's safe to snatch a Connection back from a client that has failed to close it. Some applications hold Connections open for a long time (although that's bad practice, if you are using a Connection pool).
You can force c3p0 to clean up leaked Connections after a period of time, see the config parameter unreturnedConnectionTimeout. But this is an icky strategy; I recommend if you have a leak to use this in concert with debugUnreturnedConnectionStackTraces only temporarily, to understand where you are leaking Connections and then fix the problem.
c3p0 provides connection pool for Hibernate, as The built-in Hibernate connection pool is in no way intended for production use. It lacks several features found on any decent connection pool - According to Hibernate Community Documentation, for configuration of c3p0 with Hibernate you can refer to this or MKYong tutorial on Hibernate Community.
My Enviroment
Java 5
Spring 2.5.5
DBCP DataSource (org.apache.commons.dbcp.BasicDataSource)
MySQL
Similar posts
Setting session timezone with spring jdbc oracle
Links
http://www.mysqlfaqs.net/mysql-faqs/General-Questions/How-to-manage-Time-Zone-in-MySQL
My Problem
I need to set on my connection the timezone, aiming to prevent the conversions when dealing with TIMESTAMP columns.
My Idea/research
DBCP Connection Pool did not mention anything around timezone. LINK
What I investigate and thought that was oK is described on THIS post, exemplifying is:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="URL" value="${database.url}" />
<property name="user" value="${database.username}" />
<property name="password" value="${database.passwd}" />
<property name="connectionCachingEnabled" value="true"/>
<property name="sessionTimeZone" value="GMT-3"/>
</bean>
Asking for help area :)
But this is not working!!
What I want here is a simple way, preferentially using Spring to configure the timezone on jdbc connection.
Thanks in advance for any help/tips/advice/knowledge share
SOLUTION:
My Solution was based on tips collected on this post! Thanks for all!
(...)
#Override
public Connection getConnection() {
Connection conn = null;
Statement statement = null;
try {
conn = super.getConnection();
statement = conn.createStatement();
statement.execute("SET time_zone = \'" + timezone+"\'");
} catch (SQLException e) {
LOG.fatal("Error while SET time_zone", e);
} finally {
try {
statement.close();
} catch (SQLException e) {
LOG.warn("Error while closing statement", e);
}
}
if(LOG.isDebugEnabled())
LOG.debug("SET time_zone("+timezone+") for connection, succeed!");
return conn;
}
(...)
and on my Spring configuration file:
<bean id="dataSource" class="com.my.package.dbcp.TimezoneEnabledDataSource" destroy-method="close">
(...)
<property name="timezone" value="${database.timezone}" />
(...)
</bean>
I hope this post can help someone in the future. Any question ping me!
You should be able to put the same SQL statements in the initConnectionSqls property of the DBCP configuration element. Just add this to the DBCP configuration element
<property name="initConnectionSqls" value="SET time_zone = '${database.timezone}'"/>
Depending on your version of DBCP, you may have to use connectionInitSqls as the property name. This information is straight from DBCP configuration documentation.
If the data source doesn't have such a property, you can extend it and add that property:
public TimezoneEnabledDataSource extends BasicDataSource {
private String timezone;
//getter and setter for it
#Override
public Connection getConnection() {
Connection c = super.getConnection();
// execute a query: SET time_zone = '-8:00'
return c;
}
}
See here http://www.electrictoolbox.com/mysql-set-timezone-per-connection/ for the query details.
MySQL documentation writes:
Per-connection time zones. Each client that connects has its own time zone setting, given by the session time_zone variable. Initially, the session variable takes its value from the global time_zone variable, but the client can change its own time zone with this statement:
mysql> SET time_zone = timezone;
You can also check if c3p0 doesn't have something built-in.
One of the possible solutions:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="URL" value="${database.url}?serverTimezone=America/Los_Angeles" />
<property name="user" value="${database.username}" />
<property name="password" value="${database.passwd}" />
<property name="connectionCachingEnabled" value="true"/>
<property name="sessionTimeZone" value="GMT-3"/>
</bean>
There is no "sessionTimeZone" member in the BasicDataSource. Use C3P0 which is a "better" connection pool than DBCP, or even better, if you are in a Java EE web server, use it to initialize a JNDI datasource ;)
I'm using the Spring MVC to build a thin layer on top of a SQL Server database. When I began testing, it seems that it doesn't handle stress very well :). I'm using Apache Commons DBCP to handle connection pooling and the data source.
When I first attempted ~10-15 simultaneous connections, it used to hang and I'd have to restart the server (for dev I'm using Tomcat, but I'm gonna have to deploy on Weblogic eventually).
These are my Spring bean definitions:
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url" value="[...]"/>
<property name="username" value="[...]" />
<property name="password" value="[...]" />
</bean>
<bean id="partnerDAO" class="com.hp.gpl.JdbcPartnerDAO">
<constructor-arg ref="dataSource"/>
</bean>
<!-- + other beans -->
And this is how I use them:
// in the DAO
public JdbcPartnerDAO(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
// in the controller
#Autowired
private PartnerDAO partnerDAO;
// in the controller method
Collection<Partner> partners = partnerDAO.getPartners(...);
After reading around a little bit, I found the maxWait, maxActive and maxIdle properties for the BasicDataSource (from GenericObjectPool). Here comes the problem. I'm not sure how I should set them, performance-wise. From what I know, Spring should be managing my connections so I shouldn't have to worry about releasing them.
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url" value="[...]"/>
<property name="username" value="[...]" />
<property name="password" value="[...]" />
<property name="maxWait" value="30" />
<property name="maxIdle" value="-1" />
<property name="maxActive" value="-1" />
</bean>
First, I set maxWait, so that it wouldn't hang and instead throw an exception when no connection was available from the pool. The exception message was:
Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
There are some long-running queries, but the exception was thrown regardless of the query complexity.
Then, I set maxActive and maxIdle so that it wouldn't throw the exceptions in the first place. The default values are 8 for maxActive and maxIdle (I don't understand why); if I set them to -1 there are no more exceptions thrown and everything seems to work fine.
Considering that this app should support a large number of concurrent requests is it ok to leave these settings to infinite? Will Spring actually manage my connections, considering the errors I was receiving? Should I switch to C3P0 considering it's kinda dead?
DBCP maxWait parameter should be defined in milliseconds. 30 ms is very low value, consider increasing it to 30000 ms and try again.
As you already found out, the default dbcp connection pool is 8 connections, so if you want to run 9 simultaneous queries one of them will be blocked. I suggest you connect to your database and run exec sp_who2 which will show you what is connected, and active, and whether any queries are being blocked. You can then confirm whether the issue is on the db or in your code.
As long as you are using Spring's JdbcTemplate family of objects your connections will be managed as you expect, and if you want to use a raw DataSource make sure you use DataSourceUtils to obtain a Connection.
One other suggestion - prior to Spring 3, don't ever using JdbcTemplate, stick to SimpleJdbcTemplate, you can still access the same methods using SimpleJdbcTemplate.getJdbcOperations(), but you should find yourself writing much nicer code using generics, and remove the need to ever create JdbcTemplate/NamedParameterJdbcTemplate instances.
Let's change the perspective.
but the exception was thrown
regardless of the query complexity
It could be because the table or the records in the table, which you are querying against has been locked (by some other active transaction) and hence it times out.
Try running the same query from SQLServer Client and if it takes a long time, then you can be sure that it is the table or record lock that is causing this.