Intercept JDBC Connection - java

I've a superclass that have a java.sql.Connection. There are a lot of subclasses that uses the connection to execute selects.
I need to intercept all statements executed through the connection, and log the executed SQL.
How can I do it?

Use log4jdbc. It's a proxying JDBC driver that logs all your SQL and passes the SQL and parameters on to the underlying driver. That way your code doesn't even have to be aware of the logging, it's all contained within the third-party library.
The configuration consists mostly of changing your JDBC connection string to use the proxy instead of the real driver, and telling log4jdbc what the real JDBC driver is. Then you pick logging categories in your log4j configuration to tell what kind of things you want to log. You can get the SQL, timing information, connection opening and closing events, and result set contents.
If you want an in-depth explanation of how it works see Jack Shirazi's book Java Performance Tuning. There's an extended example of building a proxying driver in the chapter on JDBC.

Related

Can we interface with the JDBC Driver to see the currently executing queries ?

Is there any way we can see the currently executing queries initiated from a java dynamic web application ? Is it possible to do so by interfacing with the JDBC Driver ?
P6Spy can be used for that.
P6Spy functions like proxy, intercepting and logging JDBC calls and forwarding them to the real driver afterwards. In the application is the JDBC connection configured to go to the P6Spy driver and then inside the P6Spy configuration is the real connection configured to which P6Spy forwards.
There is also number of alternatives.

How can I find all the SQL updates run in a Java Connection (from transaction start to commit)?

How can I find all the SQL update queries run in a Java Connection (from transaction start to commit)?
You can't do that with a normal Connection.
You could create wrapper classes for the actual Connection/Statement classes, that would track which statements have been executed. A better idea would be to just enable logging of SQL if your driver supports it, otherwise you're just recreating an existing functionality.
Some other options (on database level):
Enable and configure AUDITING; or
Enable SQL tracing of the relevant database session(s)

JDBC, Hibernate and Implicit Transactions on SQL Server 2008

We're having some problems with connections getting 'stuck' on SQL Server 2008 when issued from Hibernate, running on a Glassfish instance.
Occasionally, there will be 10 or 20 calls to a stored procedure, that are all 'sleeping', and are holding open a number of transactions.
When i use DBCC INPUTBUFFER to find out more about them, it has:
Name : implicit_transaction
Does this mean that the java app, is setting 'SET IMPLICIT_TRANSACTIONS ON' as part of the batch? The only way I was able to replciate that transaction name DB side, was to use that syntax.
It appears that the java app is hanging on to the connection, but somehow losing context of the call itself, as such it never comes back to commit the transaction.
The java developers say that they are not explicitly defining any connections, and are not away that they are setting any other connection properties on purpose. The calls are all being made under the READ COMMITTED isolation level.
How can I found out whether there's some hidden attribute set, or if some hibernate setting is causing this annoying behaviour?
You can ask Hibernate to log the sql statements it's executing.
This article describes two ways to do that.
SessionFactory sf = new Configuration()
.setProperty("hibernate.show_sql", "true")
// ...
.buildSessionFactory();
or in the log4j configuration
log4j.logger.org.hibernate.SQL=DEBUG, SQL_APPENDER
log4j.additivity.org.hibernate.SQL=false

What is faster: JDBC or JNDI?

I have two options to configure my application database connection - one is using JDBC, another one is using JNDI. What will be the best option in terms of how fast those connection types work with the database.
I understand those are two different types of database connections using different principles (JDBC is a direct db connection, JNDI is a database connection pool configuration on application server side). But are there other general JDBC/JNDI pros and cons which might be more important than operating speed? If yes, what are they?
A database connection always uses JDBC. With JNDI you register a datasource in a directory service which can be looked up by its name. Thus JDBC and JNDI are completly different and not interchangeable.
I bet what you mean is choosing from
creating datasource or jdbc connection manually in your application, or
setup the datasource in the container, and application lookup the datasource through JNDI
If it is the case, always stick to 2 if possible.
The main reasons for the choice is never the performance differences. The reason for sticking to 2 is in most cases is, you need 2 to gain more advanced features from container, for example, distributed transaction.
This is what i have found about JNDI and JDBC.
JNDI: This is a technology which works like a telephone directory which is used to search the name on server and datasource remotely.
JNDI creates a connection pool. Connection pool is an environment on the server where JNDI and Database encapsulated to for Type4 connectivity.
JDBC: A Java API that enables Java programs to execute SQL statements.
This allows Java programs to interact with any SQL-compliant database.
JDBC is similar to ODBC, but is designed specifically for Java programs, whereas ODBC is language-independent.
JDBC was developed by Sun Microsystems. JNDI is faster and efficient.
Not totally clear on the question.
JNDI isn't a type of database connection. You can use JNDI to look up a DataSource, which is a factory for connections. The DataSource is part of the JDBC API though, so JNDI works with JDBC as opposed to being alternatives here.
Are you talking about using JDBC against a database for directory information, vs. using JNDI against an LDAP repo?
The real speed benefit comes from being able to reuse database connections.
Hence, you need to use an approach which provides database connection pooling, and then use the appropriate technology to get to the pool. Depending on implementation this can be either JDBC (if the driver supports it itself) or JNDI or something completely different.
If your application runs inside a web container, it is common to use JNDI to allow the pool to be configured and managed in the web container instead of inside your application.
As mentioned in previous answers, using Datasource is the same as using JDBC in terms of technology.
Nevertheless, using a Datasource is usually the preffered way because that way you have the server managing your DB connection pools.
Whether connection pooling is used does not affect application code. It does not require any code changes to the application because the application performs a lookup on a JNDI name of a previously registered data source. If the data source specifies a connection pooling implementation during JNDI registration (as described in section Creating a Data Source Using the DataDirect Connection Pool Manager), the client application benefits from faster connections through connection pooling.
The question is meaningless. Faster at what? There is nothing to compare. JDBC is a general-purpose interface to relational databases. JNDI is a general-purpose interface to naming systems. The strong probability is that the efficiency of either depends 99% on the target system being communicated with. In any case relational databases and naming systems fulfil completely different needs that are largely non-comparable. Usually JNDI is used to obtain a connection, then JDBC is used to operate with that connection.

How do you determine if a JDBC Connection was retrieved from a JTA enabled DataSource or straight JDBC?

I'm using a vendor API to obtain a JDBC connection to the application's database. The API works when running in the application server or when running in a stand-alone mode. I want to run a series of SQL statements in a single transaction. I'm fine with them occurring in the context of the JTA transaction if it exists. However, if it doesn't then I need to use the JDBC transaction demarcation methods. (Calling these methods on a JDBC connection that is participating in a JTA transaction causes a SQLException.)
So I need to be able to determine whether the Connection came from the JTA enabled DataSource or if it's just a straight JDBC connection.
Is there a straight forward way to make this determination?
Thanks!
Even if it's straight JDBC, you can have a JTA transaction enabled. Checking the autoCommit flag will NOT help in this regard. You can be in a transaction, distributed or otherwise, with autoCommit set to false. autoCommit set to true would tell you you're not in a distributed transaction but a value of false just means you won't auto-commit... it could be in any kind of transaction.
I think you're going to have to call UserTransaction.getStatus() and verify that it is not equal to Status.NoTransaction(). This would tell you if you're in a JTA transaction.
What thilo says does make sense.
Otherwise, Not sure of a straight way BUT I will give you a "hack" way
write a BAD SQL which you know will give a DB exception.
That will result in a stack trace. From the stack trace, you can find out if it is a JTA derived connection or NOT ?
You could try to check the Connection's autoCommit flag to see if it is in a transaction (regardless of where it came from).
(Apparently, see the accepted answer, this does not work too well. I am not deleting this answer because the following still stands: )
But I think you should really modify your API to depend on external transactions exclusively. If you still want to support plain JDBC, wrap it into a separate API that just starts the transaction.
Update: Just re-read your question and saw that you are not providing an API, but want to use a container-managed connection. But still, can you just mandate (as part of your application's requirements) that JTA be in effect? If not, you could provide a configuration option to fall back to manually managed transactions. For such a critical feature it seems reasonable to require the proper configuration (as opposed to try to guess what would be appropriate).

Categories

Resources