I am migrating an application from WAS7 to Liberty.
The existing code usesWSCallHelper.clearStatementCache(connection) in some scenarios(example : package not found in case of procedure calls).
I found WSCallHelper doesn't exist in liberty server.
Could you please help me with an alternative solution for this in liberty.
It can be either specific liberty or a general approach which will support all servers.
It would be helpful to know more about the scenario where you need to call WSCallHelper.clearStatementCache(connection), but based on what you have described I'll assume that it is only called on an error path.
In Liberty, there is no API to programmatically clear the statement cache. However, cached statements will only be matched if a number of properties are the same such as: SQL string, RS holdability, schema, isolation level, and several others.
Why you don't need clearStatementCache:
The example scenario you described for calling clearStatementCache is when the package is not found in the DB, but the package should be reflected in either the SQL string or Schema. So, assuming that your application does not retry a failed SQL string, you should not need to invoke clearStatementCache at all.
If you really really want to clear the statement cache:
As defined by the JDBC spec, Statements are child objects of a Connection. So a creative way of clearing the statement cache would be to get rid of the connection with the bad statements. Invoking connection.close() may not accomplish this because connections can be pooled by the application server, but invoking connection.abort() will get rid of the underlying connection and therefore clear your statement cache.
We should also point out that if you want a more targeted approach and have a specific statement that you want removed from the cache (or to never go into the cache in the first place), you can use JDBC spec API java.sql.Statement.setPoolable(false)
. Invoke this prior to closing the statement handle. The application server will not cache statements that are marked as poolable=false.
Related
One of the requirements on my current project is to be able to log the SQL statement generated by either Hibernate or Ibatis, and save them to a specific table (on SQLServer), so an administrator can come back and see what queries were run and who ran them, or even reuse the statements on demand. While I don't agree with this approach, I would like to know if there actually exists a library that can achieve this. I am using Spring framework for my web application.
There are 3rd party SQL Server tools that can capture T-SQL statements, and store them for later manipulation and analysis, such as Idera SQL Compliance Manager and ApexSQL Comply
Disclaimer: I work as a Product Support Engineer at ApexSQL
If you want to catch all queries of a middleware like Hibernate or Ibatis, the simplest way is to use SQL Server profiler or to create a trace with SQLTrace stored procedures (sp_trace_create, sp_trace_setevent).
With SQL Profiler you can save traces directly to a table, with SQLTrace stored procedure who produces a trc file, you will have to insert them in your table with sql statements.
they are lot of examples on the web, for example here
SQL Profiler have an option to generate the SQLTrace SQL script once you have defined your trace (File/export)
The SQL Profiler is in the developper edition but not in the Express edition.
SQLTrace stored procedures are in all editions (IIRC).
You can generate the trace script on your developper edition and run it on your express edition.
You can also create a stored proc that create and start the trace on server startup.
You can do it on the server, with database audit if you have the enterprise edition of SQL Server. Or you can use Extended Events. You just need to filter by the application name, which should mention the ORM. To help you further, please provide the version and edition of SQL Server.
I know a way though it's not easy to implement. Make a custom DataSource - a wrapper over a real DataSource like Apache BasicDataSource. It will intercept getConnection calls and wrap Connection returned by the target DataSource. This wrapped Connections will intercept createStatement / createPreparedStatement calls and wrap Statements / PreparedStatements returned. The Statement wrapper can now intercept SQL executions and log them.
Yet another way to do it would be to enable SQL statement logging in the Hibernate configuration settings, and then "hoover" the statements out of the log files.
But I think that a database-server-side solution is probably the best, because it can also captures queries and updates performed using the database's interactive query tool.
For our application to work properly we need to execute a SQL Statement on every new connection, before that connection is handed out to the application.
How do I configure a data source in WAS 7 accordingly?
We found the (deprecated) option to validate the datasource using a sql statement, which hopefully does the trick (coworker is testing it right now). This sounds wrong, since we are not 'testing' the connection, but setting it up properly. Also its deprecated so this probably will stop working with future versions of websphere
Is there a clean and correct way to do this?
The statement we'd like to execute is
ALTER SESSION NLS_SORT='GERMAN_AI'
One alternative approache: The application is hibernate based, so if we could convince hibernate to execute the statement before using a connection, this would work as well.
If it were me, I would just use the "connection test" approach:
It works!
The YAGNI principle says "worry about deprecation when it happens... if it ever happens" - probably years away or never
You will not add any business value by finding the "correct" way
You can drop this and get on with some real work that actually adds value to your project
The only downside is that it will be executed every time a connection is tested, which may be many times during the life of the connection, but so what - it's a very fast executing statement and is idempotent, so no problem.
Not a WAS expert by any means, but if you can set up Tomcat JDBC to provide your database connection pooling, it has a parameter amongst others called "initSQL". You can set that to a SQL statement that you want the connection pool to run whenever a connection is created.
Tomcat JDBC Connection Pool
A.
One way to go would be to use a custom Hibernate dialect, since you are actually specifying a 'different' way to talk with the database. I have no idea where to add the initialization code though.
For a security system which works as a big brother (like a watched mandatory access control), we have to intercept and handle all select statements hibernate is generating. We store the user, the timestamp and the sql select in a database to enable some profiling with other tools. The informations allow to determine what a user tried to look at. For the select statements the prepared properties are valuable. We need the complete SQL statement including all parameters.
Is there any listener or interceptor where we can join and handle all these things? The biggest outstanding problem so far is collecting of the statement parameters.
Thank you
The actual parameter values happen to be made available (atleast to my knowledge), when the logging level of the org.hibernate package is set to DEBUG, and with the hibernate.show_sql property set. Use a JDBCAppender, if you want the logger output in the database itself.
Alternatively, you could take a look at the log4jdbc project, which claims the following:
In the logged output, for prepared
statements, the bind arguments are
automatically inserted into the SQL
output. This greatly Improves
readability and debugging for many
cases.
If that is not suitable, you could investigate whether P6Spy can be used in your situation. On WebLogic Server, the equivalent functionality is achieved via the WebLogic JDBC Spy, which comes out of the box with the WebLogic JDBC drivers for certain databases. Both of these write to System.out and not to a database (unless I'm mistaken), so it might not be that useful.
You can use Interceptor.prepareSQL() (3.1+) to intercept the prepared statements.
I don't think you can get the actual parameters without going down in the abstraction layer. A possible solution would be to use a JDBC proxy driver (see P6Spy).
Hope that helps.
A simple question: what is the more efficient way to access a db in Java/JDBC?
I'm a web developper and I'd like to write some reusable and scalable code. What is interesting for me is the use of tools like the ResultSupport: is it too expansive in terms of resource usage?
What can you suggest?
Not just JDBC specific, just general SQL stuff
If you have to rerun a query multiple times, use PreparedStatement. Use stored procedure if it is available. This is obviously not portable so YMMV.
Always close your ResultSet or Statement if you are not using it. Closing a Statement will auto close all ResultSet associated with the Statement. Still it is a good habit to close the ResultSet.
Try to restrict what can be queried eg. select * from orders where order_date between XXX and yyy. In MySQL the query may either be a full table scan or 'range' depending on how much data is returned. So deciding a how 'flexible' you want your queries to be
If you are using MySQL, use explain to optimize your query. If you are using JPA, then you don't get to see the SQL generated. (This is not strictly JDBC) You might want to enable logging on the ORM manager to display the SQL statement used. Then use explain to optimize that. You may want to use #NamedNativeQuery if the ORM generates a really convoluted query
If your JDBC driver supports batch update then use that. Batch updates is supported in PreparedStatement and ResultSet.
You can also control the commit. Good idea to turn it off if you are performing lots of updates. The call commit() yourself.
Best answer to this simple question is: "it depends".
There are many API's you can use for database access. Nearly all of them will use the JDBC API as their means to communicate with the database. So in theory, nothing can beat raw low level JDBC (just as machine code is in theory always faster than higherlevel programming languages).
But as you also like to write reusable code, I suggest you look into JPA. It's the Java standard for object persistence to relational databases. It’s performance is quite good and it’s very portable.
As JPA is just a specification, you can choose you’re own implementation: Hibernate, OpenJPA or any compliant Java EE server.
It is very important to use always a connection pool DataSource such as c3p0.
There is a project that maps java objects to mysql databases. Azirt.
Use connection pooling (either the one from your container or a standalone connection pool like c3p0 or DBCP) and something like DBUtils or Spring's JdbcTemplate.
I think the easiest and most common way is to use Spring and their JDBCTemplate.
The best approach likely depends on the stack you are using to create your web app. If you're starting afresh then Spring is a good way to go.
I have never connected to a database in java before. May I know if I should go about accessing a derby database with servlet?
I have checked this: How do I access a database from my servlet or JSP?
But I saw comments on the article saying that this is a bad way to connect. Could any one explain or show me the best way to that I should code to access my derby database?
Thank you very much.
They are all right indeed, in suggesting that. We don't don't access database directly from Servlets or JSPs, these both are meant to be web tier, isn't it?
So, what to do? Grab a JDBC tutorial. The official one is an excellent choice here. That will give you a good idea about connecting to database from Java, and grasp over JDBC API. After that you should go and read about DAO pattern, and how we employ that in real apps.
Moreover, I think you also should read about MVC pattern, because it seems to me that you are not very clear on that as well.
Once you understand all these and come up with a toy like application using all these stuff. Next step would be to have a look into Connection Pooling mechanism.
Since you are using servelt you must be using a container line Apache Tomcat. You should look to define a connection pool like this http://tomcat.apache.org/tomcat-5.5-doc/jndi-datasource-examples-howto.html. If you are using any other container then that will also have similar setup.
Other option is to create a separate DBManager kind of class which looks after initializing and returning connection. This class you can use in the servlet.
Using JDBC and having your app server's application pool is a good start. You can also use some API to make your life easier like Hibernate.
It is a "bad way", because it doesn't make use of a (JNDI-managed) connection pool to obtain connections. Although acquiring a connection costs "only" a few hundred milliseconds, this has impact in a busy multiuser environment. A connection pool will worry about opening and closing connections and release them immediately on every getConnection() call so that it effectively costs almost zero milliseconds. If you sum that up in a busy multiuser environment, then the differences are noticeable.
A connection pool is usually to be configured in flavor of a JNDI datasource which is managed by the servletcontainer in question. As you didn't mention which one you're using, I can at highest point to one of my answers which contains a Tomcat 6.0 targeted example: here.
Hope this helps.