How can I check that a connection to db is active or lost using spring data jpa?
Only the way is to make a query "SELECT 1"?
Nothing. Just execute your query. If the connection has died, either your JDBC driver will reconnect (if it supports it, and you enabled it in your connection string--most don't support it) or else you'll get an exception.
If you check the connection is up, it might fall over before you actually execute your query, so you gain absolutely nothing by checking.
That said, a lot of connection pools validate a connection by doing something like SELECT 1 before handing connections out. But this is nothing more than just executing a query, so you might just as well execute your business query.
our best chance is to just perform a simple query against one table, e.g.:
select 1 from SOME_TABLE;
https://docs.oracle.com/javase/6/docs/api/java/sql/Connection.html#isValid%28int%29
if you can use Spring Boot. Spring Boot Actuator is useful for you.
actuator will configure automatically and after it has activated ,
you can get know database status to request "health"
http://[CONTEXT_ROOT]/health
and it will return , database status like below
{"status":"UP","db":{"status":"UP","database":"PostgreSQL","hello":1}}
Related
I've created a mariadb cluster and I'm trying to get a Java application to be able to failover to another host when one of them dies.
I've created an application that creates a connection with "jdbc:mysql:sequential://host1,host2,host3/database?socketTimeout=2000&autoReconnect=true". The application makes a query in a loop every second. If I kill the node where the application is currently executing the query (Statement.executeQuery()) I get a SQLException because of a timeout. I can catch the exception and re-execute the statement and I see that the request is being sent to another server, so failover in that case works ok. But I was expecting that executeQuery() would not throw an exception and silently retry another server automatically.
Am I wrong in assuming that I shouldn't have to handle an exception and explicitely retry the query? Is there something more I need to configure for that to happen?
It is dangerous to auto reconnect for the following reason. Let's say you have this code:
BEGIN;
SELECT ... FROM tbl WHERE ... FOR UPDATE;
(line 3)
UPDATE tbl ... WHERE ...;
COMMIT;
Now let's say the server crashes at (line 3). The transaction will be rolled back. In my fabricated example, that only involves releasing the lock on tbl.
Now let's say that some other connection succeeds in performing the same transaction on the same row while you are auto-reconnecting.
Now, with auto-reconnect, the first thread is oblivious that the first half of the transaction was rolled back and proceeds to do the UPDATE based on data that is now out of date.
You need to get an exception so that you can go back to the BEGIN so that you can be "transaction safe".
You need this anyway -- With Galera, and no crashes, a similar thing could happen. Two threads performing that transaction on two different nodes at the same time... Each succeeds until it gets to the COMMIT, at which point the Galera magic happens and one of the COMMITs is told to fail. The 'right' response is replay the entire transaction on the server that was chosen for failure.
Note that Galera, unlike non-Galera, requires checking for errors on COMMIT.
More Galera tips (aimed at devs and dbas migrating from non-Galera)
Failover doesn't mean that application doesn't have to handle exceptions.
Driver will try to reconnect to another server when connection is lost.
If driver fail to reconnect to another server a SQLNonTransientConnectionException will be thrown, pools will automatically discard those connection.
If connection is recovered, there is some marginals cases where relaunching query is safe: when query is not in a transaction, and connection is currently in read-only mode (using Spring #Transactional(readOnly = false)) for example. For thoses cases, MariaDb java connection will then relaunch query automatically. In those particular cases, no exception will be thrown, and failover is transparent.
Driver cannot re-execute current query during a transaction.
Even without without transaction, if query is an UPDATE command, driver cannot know if the last request has been received by the database server and executed.
Then driver will send an SQLException (with SQLState begining by "25" = INVALID_TRANSACTION_STATE), and it's up to the application to handle those cases.
I have configure mongo uri in property file as below,
spring.data.mongodb.uri=mongodb://db1.dev.com,db2.dev.com,db3.dev.com
spring.data.mongodb.database=mydb
I use mongoowl as a monitoring tool.
When i do a get request, it shows hits in every mongodb which ideally should be show only in one db right?
No, You are actually opening a cluster replica set connection, in this connection type spring actually connects to all 3 databases to maintain fail over conditions or to full fill "read from secondary" option(hence you see hits on all 3 databases), but however the read and write operations happen only on primary unless you have specified it to read from a secondary.
In batch script I use a loop to execute a bunch of sql (hql) against
a Teradata databse. After some iterations I receive the following error:
Teradata databse: 3130 Response limit exceeded
Now the documentation suggests (as well the answer on this question) that this is due to to many open result sets for the same session.
Now the session and the ResultSet are managed by the EntityManager, and I wonder if there is a way to avoid closing and reopening the connection in this case via jpa/hiberate.
I have tried entityManager.clear or flush without any effect.
is there a way to handle this better? maybe I am missing something. My "batch" runes under spring 2.5. in a "cli" mode.
in my case it turned out to be a row with large blob data. after refining steps I could retrieve data without 3130 popping out.
I'm using latest derby10.11.1.1.
Doing something like this:
DriverManager.registerDriver(new org.apache.derby.jdbc.EmbeddedDriver())
java.sql.Connection connection = DriverManager.getConnection("jdbc:derby:filePath", ...)
Statement stmt = connection.createStatement();
stmt.setQueryTimeout(2); // shall stop query after 2 seconds but id does nothing
stmt.executeQuery(strSql);
stmt.cancel(); // this in fact would run in other thread
I get exception "java.sql.SQLFeatureNotSupportedException: Caused by: ERROR 0A000: Feature not implemented: cancel"
Do you know if there is way how to make it work? Or is it really not implemented in Derby and I would need to use different embedded database? Any tip for some free DB, which I can use instead of derby and which would support SQL timeout?
As i got in java docs
void cancel() throws SQLException
Cancels this Statement object if both the DBMS and driver support aborting an SQL statement. This method can be used by one thread to cancel a statement that is being executed by another thread.
and it will throws
SQLFeatureNotSupportedException - if the JDBC driver does not support this method
you can go with mysql.
there are so many embedded database available you can go through
embedded database
If you get Feature not implemented: cancel then that is definite, cancel is not supported.
From this post by H2's author it looks like H2 supports two ways to timeout your queries, both through the JDBC API and through a setting on the JDBC URL.
Actually I found that there is deadlock timeout in derby as well only set to 60 seconds by default and I never have patience to reach it :).
So the correct answer would be:
stmt.setQueryTimeout(2); truly seems not working
stmt.cancel(); truly seems not implemented
But luckily timeout in database manager exists. And it is set to 60 seconds. See derby dead-locks.
Time can be changed using command:
statement.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
"'derby.locks.waitTimeout', '5')");
And it works :)
I have created a desktop application and I have connect it to a MySQL database with a database connection (bean/class) and I can CRUD. I have seen on the NetBeans site that they create a connection pool on a web application.
Is a connection pool the same with the class/bean on a desktop application?
Does this mean that i create a bean/class like a desktop application that is connected with to DB model(MVC), or do i have to do something else?
On a Glassfish server you do the connection pool with a wizard; on Apache you do not. Do I have to create the DB connection bean for Apache?
What are the practices (beans, something else?) to connect a DB to a web application?
I have also read about Hibernate, but I don't understand the use of it. Where can hibernate help? I mean, it's ORM, but what can Hibernate do for me so that my code is easier? I think I'm missing the point of ORM
Hibernate will help you with your transaction management. It will enable you to open several different connections to the database, and also give you warnings when you are using unavailable objects (like beans that gets pulled in from different threads).
A concrete example of where Hibernate's ORM will make your code easier is when you are querying the DB. Instead of writing the standard SQL queries as strings, you can use Criteria-queries.
In Java, DB connections always use a JDBC driver. No DB that I know of allows to run more than a single SQL command over a single connection at the same time, so each connection becomes bottleneck if your application can run several SQL commands at the same time (the usual case for web servers where hundreds of users can interact with the database at the same time).
UPDATE: What I'm saying is: You can easily daisy-chain commands over a single connection (like UPDATE ... ; COMMIT) but you can't send two UPDATE commands at the same time -- you always have to wait for the first command to complete before you can send the next. Some databases allow to send several commands in a single query but they are executed one after the other and not all at the same time. Think about it: If you could run several commands concurrently over a single connection, how would you know in which order they were executed?
On top of that, creating DB connections is expensive for most DBs. Hence they are created in advance during application startup and held in a pool. As soon as you "connect" to the database with the pooled JDBC driver, it picks an unused connection from the pool and returns it. That (almost) takes no time. When you "close" the connection, it's returned to the pool.
As an additional benefit, the pool can keep the connections alive. So you never need to worry about connection errors when you need a new connection (well, as long as the DB is running).
From the application side, this is either transparent (most JDBC drivers either pool internally today or they have a pooling API). If your JDBC driver doesn't, you can always use a pool like DBCP. The pool handles all the nasty details and you write your application against the pool API instead of using JDBC directly. The docs will tell you how to do it.
How Hibernate is a different beast. Hibernate is a layer on top of JDBC that can transform POJOs into SQL and back.
So instead of saying INSERT INTO data(ID, VALUE) values (?, ?), you can say
class Pojo { long id; String value; }
Pojo demo = new Pojo();
demo.value = "Test";
session.persist(demo);
and Hibernate will create the SQL for you and send it to the DB. At this stage, it doesn't make your life easier. Hibernate starts to shine when you change your Pojos:
class Pojo { long id; String value;
String name; // Oops ... forget the name
}
Pojo demo = new Pojo();
demo.name = "John";
demo.value = "Test";
session.persist(demo);
Hibernate will change the DB definition accordingly and update all the SQL commands it needs to load and save the objects.