Is there a way to make jOOQ perform a SQL statement (in my case a CHECKPOINT) after each DELETE?
Ideally there would also be a way to specify the tables that this happens for.
The RDBMS I'm using (HSQLDB) doesn't allow this statement inside a trigger, otherwise I would have done it this way.
Is there a way to make jOOQ perform a SQL statement (in my case a CHECKPOINT) after each DELETE?
The easiest way forward would be to use an ExecuteListener which checks whether the current statement is a DELETE statement. You can do this:
Either using a regex on the generated SQL, if you also have plain SQL statements that are not generated using the jOOQ DSL
Or using an instanceof Delete check on ExecuteContext.query() if you're sure that you're only running jOOQ DSL statements.
This is to detect the execution of such a statement. Your follow up statement can be run in different ways, of course.
Ideally there would also be a way to specify the tables that this happens for.
This is a bit more tricky. You could implement your own VisitListener that finds all the delete statements on specific tables.
This only works if you use the DSL API, unless you're willing to run a VisitListener on a jOOQ query that you parse based on your plain SQL statements, in case of which you could also do this for arbitrary other statements. Assuming that the parser can parse your SQL.
You should be able to execute "checkpoint" from within jOOQ using the Execute statement, something like:
//create connection
String sql = "use [MyDatabase] checkpoint ";
connection.createStatement().executeQuery(sql);
Having said that, why run a checkpoint after each deleted record? If you're worried about the data being written to disc, just run "checkpoint" you iterate through all your delete operations.
Related
So basically, I would like to avoid stored procedures, but at the same time I would'nt want multiple round-trips to database to execute sequential statements.
Apparently this blog says Facebook uses mysql's multiple-statement-queries. Unfortunately, its a C API, is there a java equivalent of it?
So in brief, the question "is in java+mysql how can a second jdbc statement use the output of the first statement as input to execute, without a round-trip to database and without a storedproc" ?
If not how do other people approach this problem?
Yes, the JDBC driver for MySQL support the multi-statement queries. It is however disabled by default for security reasons, as multi-statement queries significantly increase the risks associated with eventual SQL injections.
To turn on multi-statement queries support, simply add the allowMultiQueries=true option to your connection string (or pass the equivalent option in map format). You can get more information on that option here: https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html.
Once this option enabled, you can simply execute a call similar to: statement.execute("select ... ; select ... ; select ..."). Returned ResultSets can be iterated from the Statement object: each call to statement.getResultSet() return the next one. Use statement.getMoreResults() to determine if there are indeed more ResultSet available.
It sounds like you want to do batch processing.
here is a duplicate question with an good answer:
How to execute multiple SQL statements from java
I have to confirm that can we execute multiple select statement in one shot and get multiple resultsets. Please give me some idea for doing this.
I have to execute two select query in one statement:-
String sql="select * form test;
select * from test where empid=1;"
I am expecting to run like this :-
statement.execute(sql);
thanks
I don't believe that standard JDBC supports this. Certainly the ResultSet interface is oriented towards "multiple rows, one row at a time" - but not "multiple sets of results".
That doesn't mean it's not feasible with your specific database, however - it's possible that there's a driver for your database which extends JDBC to allow it. If you specify which database and driver you're using, we could verify that more easily.
In my opinion JDBC does not allow executing multiple statements in one go. The language used in the JDBC specification and API doc indicates that the expectation is that one Statement execution is one statement, not multiple statements (eg it uses 'a SQL statement', which when reading the SQL spec means a single SELECT, INSERT, etc). However it never explicitly states it is not allowed.
Some drivers do support execution of multiple statements in one execution, but this usually has to be explicitly enabled using a connection property. Also some databases support executing a block of stored procedure code without explicitly defining a stored procedure (in that case the block is considered to be the statement).
Create a stored procedure with those set of select statements and use Statement.getMoreResults() to check whether you have more ResultSets and use
Statement.getResultSet() to get the next ResultSet
An example is given Here
I have a list of strings that contain valid SQL expressions.
I need to execute only those that do not modify the database.
What would be the best way to do this? Just doing something like:
if(sqlQuery.contains("DELETE")){
//don't execute this
}
seems like a bad hack
Update:
I'll make this more specific.
I already have a list of SQL queries that are allowed. I want to make sure only these are executed.
What would be the best way to match against these?
The easiest and best (most comprehensive) way to do this is to create a read-only user and only connect to the database with that user. In SQLServer, the easiest way to do this is to create the user and add them to the built-in "db_datareader" role. This will only allow SELECTs.
And you have to worry about more than just DELETEs, INSERTs or UPDATEs. You also have to be careful about calling any stored procedures, so to be safe you'd also want to remove execute rights, ALTER rights, GRANT rights, etc...
EDIT:
Just execute this...
CREATE LOGIN [user] WITH PASSWORD='password', DEFAULT_DATABASE=[your_db], CHECK_POLICY=OFF
GO
CREATE USER [user] FOR LOGIN [user]
EXEC sp_addrolemember N'db_datareader', N'your_db'
GO
DELETE is not the only SQL instruction that might modify your database; INSERT will definitely do so, and UPDATE might (depending on your exact query). So just analysing the Strings might be a hard way of doing this.
As long as performance is not really an issue, you could start a transaction, run your instructions one by one, check the number of affected rows for each of them, and finally rollback your transaction. Afterwards, you only run those statements that affected 0 rows.
Besides, check your database documentation: some RDBMS-es (like Oracle) don't support rollback of DDL statements like ALTER TABLE, DROP TABLE and the like...
I don't think there's a bulletproof way of preventing the alteration of records by simply checking the content of the given SQL. For example, you might have a field, which has the value "update" and some user is trying to query all rows which contain this value, yet the SQL would not be executed, since it contains a "blacklisted" string.
I guess the only safe way would be to execute the SQL's with an user, who has no rights to alter records at all.
In one of my applications I am providing the users the ability to issue direct SQL queries against a database. They type the SQL text into a text box, then I run it exactly as is using JDBC.
Obviously I trust these users very much. But I would like to limit them programatically to issuing only SELECT statements. They should never DELETE/UPDATE/INSERT. I thought maybe JDBC itself could help me here. I found the executeQuery() method in the java.sql.Statement class. But that method allows me to call DELETE (and maybe UPDATE and INSERT too). It does throw an Exception because no ResultSet is returned, but only after deleting the records.
So, I ask here, is there any way in JDBC to make sure that a SQL statement is only performed if it is a query? Or do I have to parse the statement myself and make sure it complies with my wishes?
I suggest you connect to the DBMS with a user that lacks the DELETE / UPDATE and INSERT permissions.
Often, in the network can be found code like this:
private static final String SQL = "SELECT * FROM table_name";
....
and for this SQL query is used PreparedStatement. Why?
As i know, PreparedStatement spend time to precompile SQL statement. It turns out so that the Statement is faster than a PreparedStatement. Or I'm mistaken?
Prepared statements are much faster when you have to run the same statement multiple times, with different data. Thats because SQL will validate the query only once, whereas if you just use a statement it will validate the query each time.
The other benefit of using PreparedStatements is to avoid causing a SQL injection vulnerability - though in your case your query is so simple you haven't encountered that.
For your query, the difference between running a prepared statement vs a statement is probably negligible.
EDIT: In response to your comment below, you will need to look closely at the DAO class to see what it is doing. If for example, each time the method is called it re-creates the prepared statement then you will lose any benefit of using prepared statements.
What you want to achieve, is the encapsulation of your persistence layer so that their is no specific call to MySQL or Postgres or whatever you are using, and at the same time take advantage of the performance and security benefits of things like prepared statements. To do this you need to rely on Java's own objects such as PreparedStatement,.
I personally would build my own DAO class for doing CRUD operations, using Hibernate underneath and the Java Persistence API to encapsulate it all, and that should use prepared statements for the security benefits. If you have a specific use-case for doing repeated operations, then I would be inclined to wrap that within its own object.
Hibernate can be configured to use whatever database vendor you are using via an XML file, and thus it provides really neat encapsulation of your persistence layer. However, it is quite a complicated product to get right!
Most of the time queries are not as simple as your example. If there is any variation to the query, i.e. any parameters that are not known at compile time, you must use PreparedStatement to avoid SQL injection vulnerabilities. This trumps any performance concerns.
If there is any difference between PreparedStatement and Statement, it would be highly dependent on the particular JDBC driver in question and most of the time the penalty will be negligible compare to the cost of going to the database, executing actual query and fetching results back.
As Per the My knowledge PreparedStatement is much faster then statement. Here some reason why preparedstatement is faster then statement please read for more detail.
JDBC API is provide the functionality of connectivity with database. Then we try to execute the query with the use of statement and preparedstatement.
There are four step to execute the query.
Parsing of sql query.
Compile this Query.
optimization of data acquisition path.
execute the query.
Statement interface is suitable when we will not need to execute the query multiple time.
Disadvantages of Statement Interface.
hacker can easily to hack the data. Like suppose we have one query which have the username and password is a parameters you can give the proper parameters is username='abc#example.com' and password ='abc123' actually this is current But hacker can do username='abc#example.com' or '1'=1 and password='' that means you can logged successfully. so that is happening possible in Statement.
And sql validate every time when we fetch the data from database.
So Java has the solution for this above problem that is PreparedStatement.
This interface has many advantages. the main advantages of preparedstatement is sql is not validate the query every time. so you can get the result fast. please read the below more advantages of preparedstatement.
1) We can safely provide the value of query's parameters with setter method.
2) it prevent the SQL injection because it is automatically escapes the special characters.
3) When we use statement above four steps are execute every time But when we use the PreparedStatement only last steps is execute so this is faster then statement.
Faster is not the consideration here. Parsing of the sql will generally be a tiny part of overall execution. See more at When should we use a PreparedStatement instead of a Statement?