I was wondering if there is a specific way to override database connection timeout in the properties file in my Java web project? I am using Hibernate, Spring, and MySQL DB. I have tried several different property fields and reduced the timeout time to 1 millsecond, yet the connection is still completed with transactions still being processed properly.
These are the property fields I have used to no avail...
spring.jpa.properties.javax.persistence.query.timeout=1
spring.jdbc.template.query-timeout=1
hibernate.c3p0.timeout=1
Is hibernate overriding this timeout value or am I just setting it improperly?
Thanks in advance!
Assuming that you're using Spring Boot you can try:
spring.transaction.defaultTimeout=1
This property sets defaultTimeout for transactions to 1 second.
(Looking at the source code of TransactionDefinition it seems that it is not possible to use anything more precise than seconds.)
See also: TransactionProperties
javax.persistence.query.timeout
This is a hint for Query. It is supposed to work if you use it like this:
entityManager.createQuery("select e from SampleEntity e")
.setHint(QueryHints.SPEC_HINT_TIMEOUT, 1)
.getResultList();
See also QueryHints
spring.jdbc.template.query-timeout
Remember that according to the JdbcTemplate#setQueryTimeout javadoc:
Any timeout specified here will be overridden by the remaining transaction timeout when executing within a transaction that has a timeout specified at the transaction level.
hibernate.c3p0.timeout
I suspect that this property specifies timeout for getting from the connection pool, not for a query execution
Related
I have spring boot application, that makes update in two database Postgres. I use Atomikos for distributed transaction management.
I see that my application makes query in both database each 10 seconds:
"SELECT gid FROM pg_prepared_xacts where database = current_database()"
I'm wonder why? Has atomikos some property for changing period? For example 1 minute. What will be if query returns some gids?
I had looked internet hard about this question, but didn't find the answer.
I have some assumption, and I want to know the right answer.
Why does Atomikos ping pg_prepared_xacts?
It calls "recovery scan" and aim is recovering after failing of application, or error in application. Because of it, in database will not be "orphaned" prepared transactions created by Atomikos.
Has atomikos some property for changing period?
Yes, it has: com.atomikos.icatch.recovery_delay. Other useful properties are here: JtaProperties
What will be if query returns some gids?
Atomikos checks if returned gids are in atomikos transaction log and have status "to commit". If it's so, he will commit prepare transactions, else he will rollback transactions. Note, that Atomikos will handle prepare transactions, that were created by him, and will not handle other prepare transactions.
I'am adding some record in db using hibernate, but when i try to get the same record in some millis then it is returning 0 results.
This is the flow:
Create a put request.
Put result in db.
Response received 202 accepted.
Then same controller sends the request to another controller which then tries to update that record.
It returns result as failure.
Environment:
JDK 8
Spring boot 1.2.5
Hibernate 4.3.11.Final
I tried following ways:
Set session flush mode to ALWAYS and COMMIT.
Manually did session.flush() and session.clear()
Please provide the solution as soon as possible.
We do use Spring Boot Health Checks in our application. On one of the checked applications it looks like the DB cannot answer in a timely manner. We are using the DataSourceHealthIndicator, and this is answering after several seconds with an exception which is fine, but takes different timeframes to come back.
Could we set a timeout on this HealthIndicator (and most probably on others as well), so that the HealthIndicator reports back after say 2s in the latest with an error, if no connection to the DB can be established?
Or could we ask the Datasource if there are still any open connections available?
I know, that we should fix the problem with these connections and we are already working on this one, but a HealthCheck for something like this would be nice as well.
You could disable the default db health indicator in your application.properties
management.health.db.enabled=false
and implement custom HealthIndicator that has desired behavior, as described here.
In your custom HealthIndicator implemetation you could use a different JdbcTemplatethat will have desired timeout value of 2 seconds, something like this:
JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource);
jdbcTemplate.setQueryTimeout(2);
jdbcTemplate.execute(...);
If execute call throws an exception, your indicator should return Health.down(), otherwise Health.up() should be returned.
I would like to set a timeout on a javax.persistence.TypedQuery.
I've found this easy method :
TypedQuery<Foo> query = ... ;
query.setHint("javax.persistence.query.timeout", 1000);
query.getReturnList();
But it seems that does not work, it's just ignored.
From the PRO JPA 2 book:
"Unfortunately, setting a query timeout is not portable behavior. It
may not be supported by all database platforms nor is it a requirement
to be supported by all persistence providers. Therefore, applications
that want to enable query timeouts must be prepared for three
scenarios.
The first is that the property is silently ignored and has no effect.
The second is that the property is enabled and any select, update, or
delete operation that runs longer than the specified timeout value is
aborted, and a QueryTimeoutException is thrown. This exception may be
handled and will not cause any active transaction to be marked for
rollback.
The third scenario is that the property is enabled, but in doing so
the database forces a transaction rollback when the timeout is
exceeded. In this case, a PersistenceException will be thrown and the
transaction marked for rollback. In general, if enabled the
application should be written to handle the QueryTimeoutException, but
should not fail if the timeout is exceeded and the exception is not
thrown."
Does anyone knows any other method to specify a timeout on a TypedQuery?
Or how can I make this "hint" working?
Thanks
EDIT: Oracle 11.2.0.4.0 and PostgreSql 9.2.9
with JPA 2.1 / Hibernate
I know its late to reply, but we faced similar problem Oracle 11g, JPA2.0 and this hint wasn't working.
Actually the problem was we were using it as #NamedQuery hint and were calling the function inside #transactional aspect. As #NamedQuery gets loaded and compiled at the time of context load this timeout was overridden by transaction timeout.
You can find more info at http://javadeveloperz0ne.blogspot.in/2015/07/why-jpa-hints-on-namedquery-wont-work.html.
Solution would be fetching named query again and then applying timeout.
Query query = entityManager.createNamedQuery("NamedQueryName");
query.setHint("org.hibernate.timeout", "5");
query.getSingleResult();
Hope it helps!
Yeah Hint ignored and its not work please review this question . you should set timeout for javax.persistence.query.timeout
Set timeout on EntityManager query
I'm currently working on a java application. It's a standalone client with Spring and Hibernate. Also C3P0.
In the previous version we used a standard user(hardcoded in the configuration file) for the database connection but now we changed it so that every user has to provide his own credentials.
The beans with the code for the database are basically created on-demand.
I changed the XML-files and added a postprocessor which sets the credentials as well as some connection settings. It looks similar to this now:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
configurer = new PropertyPlaceholderConfigurer();
// properties are retrieved from a private method
configurer.setProperties(getProperties());
context.addBeanFactoryPostProcessor(configurer);
context.setConfigLocations(new String[] { "first.xml","second.xml" });
context.refresh();
return context.getBean("myClass", MyClass.class);
This all works as expected but now we reach the part where I'm currently stuck.
I want to provide a test functionality for the connection, so that the user can click a button and then is told if his credentials were accepted or not.
My first idea was to do a simple select on the database. Sifting through the logs however, I noticed that Spring tries to connect to the database during the refresh() (or rather the instantiation of the bean) anyway. I can see exceptions in the logs, for example: java.sql.SQLException: Connections could not be acquired from the underlying database!
Unfortunately, Spring doesn't seem to actually care. The exceptions are logged away but refresh() finishes and is not throwing any exceptions because of this. I had hoped that I could simply catch the exception and then I would know that the connection failed.
I could just do the select as planned, but I want to limit the connection attempts as much as possible, because the database server will block the user after several attempts. Even permanently if there are to many attempts(already had some fun with that, before I changed the settings for the connection pool).
My searches regarding this problem came up with practically nothing. Is there a way to get the exception somehow? Or does Spring provide an API of sorts that would tell me about the connection error during the instantiation/refresh?
Failing that, any ideas for an alternative approach? Preferably one that needs only a single attempt to determine if a connection is possible.
Edit: For anyone interested: I went with the suggestion from Santosh and implemented a connection test in JDBC.
Unfortunately there seems to be no easy way to make use of the database errors/exceptions encountered during the bean instantiation.
The kind of functionality you are looking for would be very tricky to accomplish using spring+hibernate.
The connection properties are set at the session-factory level and if credentials are incorrect, the session-factory is not instantiated.
Quoting #Bozo from his answer here.
What you can do is extend LocalSessionFactoryBean and override the
getObject() method, and make it return a proxy (via
java.lang.reflect.Proxy or CGLIB / javassist), in case the
sessionFactory is null. That way a SessionFactory will be injected.
The proxy should hold a reference to a bare SessionFactory, which
would initially be null. Whenever the proxy is asked to connect, if
the sessionFacotry is still null, you call the buildSessionFactory()
(of the LocalSessionFactoryBean) and delegate to it. Otherwise throw
an exception. (Then of course map your new factory bean instead of the
current)
There is also a simple and rudimentary approach wherein before creating ClassPathXmlApplicationContext, simply try to obtain a connection using raw JDBC calls. If that succeed then proceed or else give use appropriate message.
You can limit the connection attempts here as you are in full control.