addBatch support in Spring JDBCTemplate? - spring

I want to execute multiple, separate SQL statements like in the JDBC cookbook:
Statement stmt = con.createStatement();
stmt.addBatch(
"update registration set balance=balance-5.00
where theuser="+theuser);
stmt.addBatch(
"insert into auctionitems(
description, startprice)
values("+description+","+startprice+")");
Must I use the Statement object directly? I'm looking for some spring JDBCTemplate service that provides the same functionality.
Extra points: Even better would be a service that takes a text with multiple SQL statements separated with ; and executes them all.
Thanks, Ido

JdbcTemplate has two batchUpdate methods that provide this functionality (javadoc). Which one you use depends on how much control you need. If you need full control, you can use the execute(StatementCallback) or even execute(ConnectionCallback) methods.

Related

Intetcept JdbcTemplate without using AOP or wrapper

What all I want to do is automatically collect statistical values from DB for each DML or DQL has been executed in Spring or Spring Boot application.
Take Oracle for example, if I execute a query - select 1 from dual, then I can execute a next query - select * from v$mtstat a, v$statnameb where a.statistic# = b.statistic# to retrieve statistical values for current session.
Therefore, once I use JdbcTemplate or NamedParameterJdbcTemplate to access DB (SELECT/UPDATE/INSERT/DELETE), I also want to collect those statistical values initiatively for further analysis.
I have surveyed several techniques such as datasource-proxy or P6Spy, but they didn't meet my requirement.
So does anyone knows how to achieve this without using AOP or wrapping it?
Any advice and suggestions will be greatly appreciated.

Passing dynamic queries in spring JPA

I want to know how do we pass a query in spring JPA that has been prepared dynamically while program execution. The required query may vary according to the user input. So after framing the query manually using a for loop how do i execute this query ?
I have tried executing the query using the JDBC concept. but i want something more like :
#Query ( query_String)
public <return_type> filterNodes(String query_String);
Is this possible ?
The approach you sketched does not work.
Depending on how you create the query there are various options that might fit the bill:
Query by Example is quite limited but has it's uses
Specifications or their Querydsl equivalent are rather flexible and I'd expect them to work in your case but that is just guessing since you don't describe how you create your query.
If everything fails you can write a custom method implementation that takea s the query as parameter and uses an EntityManager to execute it.

JOOQ vs JDBC+tests

What advantage have JOOQ over JDBC+tests?
In JDBC you can write SQL queries direct in code, with JOOQ we calls methods, so JOOQ is by default more slow.
In JOOQ is harder to do mistakes but not impossible. This mistakes can be caught in tests, with JOOQ you also should write these tests, so, no advantage here for JOOQ.
I completely agree with you. It's always better to have tests, regardless if you're using a "dynamic language" (SQL as an external DSL, e.g. JDBC) or a "static language" (SQL as an internal DSL, e.g. jOOQ)
But there's much more than that:
You seem to have scratched only the surface of what jOOQ can do for you. Sure, type safe, embedded SQL is a great feature, but once you have that, you get for free (list is far from exhaustive):
Active records: With JDBC, you're back to spelling out each individual boring INSERT, UPDATE, DELETE statement manually. jOOQ's UpdatableRecord greatly simplifies this, while offering things like:
RecordListener for record lifecycle management
Optimistic locking
Batching of inserts, updates, deletes
Dynamic SQL is very easy. Instead of that JDBC string concatenation mess that you'd be getting otherwise, you can just dynamically add clauses to your SQL statements.
Multi tenancy: You can easily switch schema references and/or table references at runtime in order to run the same query against a different schema.
Standardisation: The same jOOQ query runs on up to 21 RDBMS because the jOOQ API standardises the generated SQL. This can be seen in the jOOQ manual's section about the LIMIT clause, for instance - one of SQL's most poorly standardised clauses
Query Lifecycle: There's a simple SPI called ExecuteListener that allows you to hook into the various JDBC interaction steps, including:
SQL generation
Prepared statement creation
Variable binding
Execution
Result fetching
Exceptions
SQL transformation: The VisitListener SPI allows you to intercept the SQL generation at any arbitrary position in your query expression tree. This can be very useful, e.g. to implement powerful things like row level security.
Stored procedures: These are rather tedious to bind to with JDBC, especially if you're using more advanced features like:
Oracle's TABLE and OBJECT types (imagine implementing SQLData et al.)
Oracle's PL/SQL types
Implicit cursors
Table-valued functions
Of course, you get the compile-time type safety that you've mentioned (and IDE autocompletion) for free. And if you don't want to go all in on the internal DSL that jOOQ is offering, you can still just use plain SQL and then use jOOQ's API in a non-type safe way (which still has tons of features):
// Just one example: CSV exports
String csvExport =
ctx.fetch("SELECT * FROM my_table WHERE id = ?", 3)
.formatCSV();
TL;DR:
JDBC is a wire protocol abstraction API
jOOQ is a SQL API
Disclaimer:
(Of course, this answer is biased as I work for the company behind jOOQ)

jdbc Statement or PreparedStatement without where

If I don't have a WHERE clause in a query then should I use Statement or PreparedStatement. Which one will be efficient.
For Ex,
SELECT ID, NAME FROM PERSON
A prepared statement is precompiled to enhance efficiency. Also the database caches the statement which gains performance on later execution. Both can be of use even if you don't have variables in your statement. Especially if the statement is executed often.
If executed once or very seldomly I'd say a normal Statement is fine. Otherwise I would use a PreparedStatement. But there's no way of beeing sure about it without benchmarking.
Depends on the implementation of the JDBC driver. Some vendors save that statement in a cache, regardless if is a instance of java.sql.Statement or java.sql.PreparedStatement. For simplicity, you could use java.sql.Statement. On the other hand, if you plan to add a parameter and execute the statement several times (in the same connection), uses an instance of java.sql.PreparedStatement.
In the javadoc for java.sql.PreparedStatement says:
This object can then be used to efficiently execute this statement multiple times.
Apart from what has been mentioned by stonedsquirrel, another point is in future if you would want to add where condition then it is easy to make a change, all you need to add the following in your code
PreparedStatement ps = con.prepareStatement("SELECT ID, NAME FROM PERSON WHERE NAME= ?");
ps.setString(1, getName(""));
....
...
However if you are using Statement, then you need to make more changes in your code.
So by using PreparedStatement you will do minimal change if you need to add where conditions.
On the contrary by using Statement, it is quite easy to log or print the sql query, however if
PreparedStatement is used, logging or printing sql statement is quite difficult or there are no direct approaches available.

JDBC - Multiple queries in NamedParameterJdbcTemplate

Is there any way I can execute more than 1 query using a NamedParameterJdbcTemplate in one single call?
The simple answer: You can't. JDBC statements should execute only one query / statement at a time.
The longer answer: You usually can't, because either the driver or the database server doesn't support it, and formally the JDBC specification doesn't allow for it (if you read a bit between the lines in both the specification and the Javadoc). However, some driver (ie MySQL Connector/J) do allow you to execute multiple queries in one go (though you might need to specify a connection property to enable it, not sure).

Resources