Can jOOQ be used to check native SQL string - java

I want to integrate jOOQ in a project which uses native SQL and org.springframework.jdbc.core.JdbcTemplate. The database schema changes often and developers have to search the code for a column that has been removed and update the queries. Hibernate or another ORM solution isn't an option as queries are sometimes very large and developers get them and just have to insert into the application code. This is very error-prune. So I thought to integrate jOOQ but gradually.
Can jOOQ throw compile time errors if a native SQL cannot be executed?
I've tried the following:
// Existing code
JdbcTemplate jdbcTemplate = ...
String sql = "select ...";
// Check code
try {
DSLContext dslContext = DSL.using(jdbcTemplate.getDataSource().getConnection());
Query query = dslContext.parser().parseQuery(sql + " order by NON_EXISTING_COLUMN");
} catch (SQLException e) {
...
}
// Existing code
return jdbcTemplate.query(sql, ...)
But it compiles well although NON_EXISTING_COLUMN doesn't really exist. Maybe I know the jOOQ API not very well yet. But I thought that it should be capable of doing it. The table classes are generated, so it can check whether the query which is build from a native SQL string is executable without executing it. Isn't it?

why don't use generated class files rather than typing native SQL?
dslContext.selectFrom(GENERATED_TABLE)...
PS: If you use JOOQ DSL(with generated classes) for generating SQL it would be work but not completely in some cases if you do mistakes even on generated classes (relations or some aggregate functions) it will not complain about it and will compile successfully.

Older versions of jOOQ did not implement meta data lookups in the parser, or only to some limited extent, and just accepted all valid identifiers. Starting with jOOQ 3.14, there will be an improved implementation as of:
https://github.com/jOOQ/jOOQ/issues/9061
You will need to provide jOOQ with a Configuration.metaProvider() (it defaults to the JDBC DatabaseMetaData backed implementation. You might prefer using generated code), and then jOOQ will try to resolve all identifiers.
Prior to jOOQ 3.14, you could implement a VisitListener which traverses the parsed SQL query, and validate all the identifiers yourself.

Related

Building CosmosDB Query strings with escaping

I want to build a cosmosdb sql query, because I'm using a rest interface, which accepts SQL querys (don't ask why, I can't change that :( )...
Now I want to build that query with some parameters, which affects the WHERE clause.
I think it is a good idea to escape these parameters, to prevent sql injection.
But I just found these way to build a query:
var param = new SqlParameter();
param.add("#test", "here some string to inject");
var query = new SqlQuerySpec("SELECT #test FROM table", param);
Now I could do sql calls to the cosmos's without sql injection. But I don't want this. I just want to get the query string.
But I need the full query from "query". But there seems to be just the method query.getQueryText(). But this just returns the string "SELECT #test FROM table".
Do know a workaround for me? Or maybe just a good package I can use to to my own string escapes.
T
I found the information that this escalation stuff doesn't happen on client site. It happens in the dbms. So I need a rest interface, where I can pass the parameters.
Azure Cosmos DB SQL Like, prepared statements

JOOQ: generating update SQL for table named by String

I just want to use JOOQ to generate SQL without it validating tables, columns, etc., and without it generating classes for said tables, columns, etc.
How can I generate a SQL update, and just specify the name of the schema & table with Strings?
Maybe later I'll setup the table-generated Java code, but it's not necessary right now. If I can't use JOOQ without such generated code, then I'll use some other library for now.
Thanks.
You don't have to use source code generation to use jOOQ's DSL API. See, for instance:
http://www.jooq.org/doc/latest/manual/getting-started/use-cases/jooq-as-a-standalone-sql-builder
http://www.jooq.org/doc/latest/manual/sql-building/plain-sql
http://www.jooq.org/doc/latest/manual/sql-building/names
In your case, given you want to generate a SQL update, how about:
// Assuming this static import
import static org.jooq.impl.DSL.*;
using(configuration)
.update(table("my_table"))
.set(field("id", Integer.class), 1)
.set(field("value", String.class), "A")
.where("x > ?", 3)
.execute();

Utility to display select with queries on console

I'm looking for an utility to run a JPA query and display the query along with its results in console. Just like running a select statement in native sql client:
ij> select * from standalonejpa.Emp_PHONE;
EMPLOYEE_ID|PHONE_NUM |PHONENUMBE&
--------------------------------------------
1 |12938302 |0
I would like to write a method that would accept one parameter - table name - and produce above statement to console by running EntityManager's createQuery() and getResultList(). Do you know such utility or I have to carefully craft it myself?
Not sure about a utility, but you can enable logging to show the resulting SQL.
As for crafting one, I would create a listener that interfaces with EclipseLink's logger to capture the log output then display it on the screen.
You can send JPA queries directly through the persistence layer, the only thing you can't do (or can't do easily) at runtime is adding new classes as the JPA enabled classes have to be known at startup. Though there should be an implementation specific way to register new JPA classes at runtime.
I ended up with the solution that uses JDBC query and pretty print the results with Derbytools utility class. I'm selecting all tables from the JPA project like that:
Connection conn = em.unwrap(Connection.class);
Statement st = conn.createStatement();
for(EntityType<?> et : emf.getMetamodel().getEntities()) {
String query = "SELECT * FROM " + et.getName();
System.out.println("> " + query);
st.execute(query);
JDBCDisplayUtil.DisplayResults(System.out, st, conn);
}
As a result I have pretty formatted results like:
> SELECT * FROM Employee
ID
-----------
1
51
Here comes the information to keep completeness of this post:
I used EclipseLink java.sql.Connection unwrapping and added to my pom.xml dependency to Derbytools:
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbytools</artifactId>
<version>10.10.2.0</version>
</dependency>
Actually you can use pretty-printing from Derbytools with any database, not only Apache Derby.
The whole hassle I make was to create a "testing" project for JPA mappings, that will be displaying generated tables along with data in there. The whole project is called "jpa-testing" and it is available from my github.

What are alternatives to JDBC driver for access PostgreSQL database

I'm using official JDBC driver for PostgreSQL, but I'm stuck with the following issues:
No support for PostgreSQL-ish data structures such as UUIDs.
Common JDBC weirdness, such as:
No function to escape values for consuming by PostgreSQL.
Limited support for executing heterogeneous statements in batch.
No rewriting of multiple insert statements into single insert statement when inserting many rows in one table.
So, the question — is there any PostgreSQL database driver which can leverage full power of PostgreSQL without much boilerplate? I'm also use Scala language for development, so if driver is designed specifically for Scala it would be so much awesome awesome.
Some of this seems to be (unless I'm not understanding) user error in using JDBC. JDBC is a pretty ugly API, so never ask if you can do it elegantly, just ask if you can do it at all.
Escaping and inserting multiple rows should be handled, as #ColinD and #a_horse pointed out, with Prepared statements and batch operations. Under the hood, I would expect a good JDBC implementation to do the things you want (I am not familiar with PostgreSQL's implementation).
Regarding UUIDs, here is a solution:
All that PostgreSQL can do is convert string literals to uuid.
You can make use of this by using the data type
org.postgresql.util.PGobject, which is a general class used to
represent data types unknown to JDBC.
You can define a helper class:
public class UUID extends org.postgresql.util.PGobject {
public static final long serialVersionUID = 668353936136517917L;
public UUID(String s) throws java.sql.SQLException {
super();
this.setType("uuid");
this.setValue(s);
}
}
Then the following piece of code will succeed:
java.sql.PreparedStatement stmt =
conn.prepareStatement("UPDATE t SET uid = ? WHERE id = 1");
stmt.setObject(1, new UUID("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"));
stmt.executeUpdate();
The driver supports batched statements to speed up bulk inserts.
And using batched statements is a lot more portable than using proprietary INSERT syntax (and as far as I can tell, there is no big different between a multi-row insert and batched inserts)
Check out PreparedStatement.addBatch()
The reason why UUID is not supported is probably that UUID is not part of the Postgres core, just a contrib module.
Edit
Regarding the execute heterogeneous statements
The Postgres driver does support different types of statements in the a batch.
The following works fine:
Connection con = DriverManager.getConnection("jdbc:postgresql://localhost/postgres", "foo", "bar");
con.setAutoCommit(false);
Statement stmt = con.createStatement();
stmt.addBatch("create table foo (id integer, data varchar(100))");
stmt.addBatch("insert into foo values (1, 'one')");
stmt.addBatch("insert into foo values (2, 'two')");
stmt.addBatch("update foo set data = 'one_other' where id = 1");
stmt.executeBatch();
con.commit();
Although you do lose the automatic escaping that PreparedStatement gives you.
I realise this doesn't answer your entire question, but hopefully it will be useful all the same.
I'm using Java 6 and Postgres 8.4. The driver I'm using is in my Maven POM file as:
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-702.jdbc4</version>
</dependency>
I'm using PreparedStatement.getObject() and PreparedStatement.setObject() with Java's java.util.UUID class to retrieve and store UUIDs.
For example:
pstm.setObject(1, guid); //where pstm is a PreparedStatement and guid is a UUID
and:
//where rs is a ResultSet
UUID myGuid = (UUID) rs.getObject("my_uuid_column_name");
Works fine.
With newer drivers, the following is alsow supported
UUID myGuid = rs.getObject("my_uuid_column_name", UUID.class);
No support for PostgreSQL-ish data structures such as UUIDs.
On the contrary, the current JDBC driver (9.2-1002 JDBC 4) for Postgres 9.x does indeed support UUID via the setObject and getObject commands. You cannot get any more direct or simpler than that (in any database, Postgres or any other) because JDBC does not recognize UUID as a data type.
As far as I can tell, there is no need to create a helper class as suggest in another answer by Yishai.
No need to do any casting or go through strings.
See my blog post for more discussion and code example.
Code example excerpt:
java.util.UUID uuid = java.util.UUID.randomUUID();
…
preparedStatement.setObject( nthPlaceholder++, uuid ); // Pass UUID to database.
Take a look at O/R Broker, which is a Scala JDBC-based library for relational database access.

Pattern for creating a database schema using JDBC

I have a Java-application that loads data from a legacy file format into an SQLite-Database using JDBC. If the database file specified does not exist, it is supposed to create a new one. Currently the schema for the database is hardcoded in the application. I would much rather have it in a separate file as an SQL-Script, but apparently there is no easy way to execute an SQL-Script though JDBC. Is there any other way or a pattern to achieve something like this?
Your sentence "there is now easy way to execute an SQL-Script though JDBC" confused me for a minute, but I reckon you are saying "there is no easy way". :)
Based on what others have said, yes... the perfect world scenario is to use an ORM tool, like Hibernate, but I also understand the fact when you are dealing with legacy stuff at work, your team may not want to spend too much time refactoring that project.
I agree that you should refactor out the database schema into a separate file. You can actually execute the SQL script using JDBC. I do that all the time when I run my certain testcases.
Here's how I do it. I use SQL Server database in my case. So, you need to tweak the code to fit your needs.
String ddl = ... // load your SQL script file into this string
String delimiter = "GO"; // in my case, SQL Server uses GO as delimiter, you use whatever you want here.
private void executeDDL(String ddl, String delimiter) {
Connection con = null;
try {
con = ... // get the connection
// enable transaction
con.setAutoCommit(false);
Statement statement = con.createStatement();
// for every DDL statement, execute it
for (String sql : ddl.split(delimiter)) {
if (StringUtils.isNotBlank(sql)) {
statement.executeUpdate(sql);
}
}
statement.close();
con.commit();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
con.close();
}
catch (Exception ignored) {
}
}
}
The "right" way is to use Hibernate. Among all other benefits it is capable of creating/updating a DB schema automatically (SO1, SO2).
In case you are working in a development environment, I would advice you to use an ORM tool like Hibernate that forward engineers based on your Java Domain Models to create the DB tables. Hibernate has the feature to auto create/update the tables in case there are changes to DB schema.
As you are using SQLite you could have a look at Hibernate for SQLite
I have read somewhere that it not advisable to use this feature in a production environment because the incremental table creation might negatively affect the existing data.

Categories

Resources