How to execute huge sql native code using hibernate? - java

I need to create a web application that allows users to create a database using ER diagrams and then perform basic CRUD operations on it. I have already done most of the job, how it's work:
As you can see after create tables i have ready to use SQL code (right bottom corner).
And now i need to execute this code from java.
I am using Java (1.8), Oracle(11gR2), Hibernate (5.4.9.Final)
Here is my code which is used to execute native queries (i am loading sql from file):
Session session = hibernateFactory.openSession();
String query = null;
try {
query = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("test.sql").toURI())));
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
String finalQuery = query;
session.doWork(connection -> connection.prepareStatement(finalQuery).execute());
And here is the question:
Is this possible to execute this whole code at once?
I can execute this:
but when i will put another table, then i will got this error:
Its seems like hibernate don't like character: ";"
Is it possible to fix this and force this prepareStatement to execute whole code sql? Or i will need to do it in parts?

Related

Executing batch of DDL statements in one query java

I have a query which batch of sql commands in one string,
String SQLQuery =
"CREATE VOLATILE TABLE v1;
CREATE VOLATILE TABLE v2;
INSERT INTO v1;
//do stuff
INSERT INTO v2;
//do stuff
UPDATE xx;
//do stuff
DROP TABLE v1;
DROP TABLE v2;"
I tried to execute them with executeUpdate(), executeBatch() both of them fails with java jdbc client, which works in Teradata client.
Error mesg:
[TeraJDBC 15.10.00.35] [Error 3576] [SQLState 25000] Data definition not valid unless solitary.
Java code:
PreparedStatement stmt10 = null;
try {
stmt10 = conn.prepareStatement(SQLQuery);
//stmt10.executeUpdate();
stmt10.executeBatch();
//conn.commit();
} catch (Exception ex) {
throw new Exception(ex.getMessage());
} finally {
if (stmt10 != null) {
stmt10.close();
}
}
how can i do this?
In teradata you cannot execute DDL statements together. It's not a problem with the JDBC or the java code - just the way you want to use teradata. That is what that error is basically saying:
http://teradataerror.com/3576-Data-definition-not-valid-unless-solitary.html
So you need to send the separate the DDL statements in separate transactions with a separate requests. If it was multiple updates and selects it would work just fine but create table cannot be executed like that.
I believe it is due to the fact that any DDL request MUST be commited before actually happening. And if you use it like that it is not. I think it is actually OK to have DDL in a multiple commands query if it is only one and it is the last statement .

Get results as CSV from postgresql using hibernate

I execute a query which should return the results as a CSV to the STDOUT.
When I execute my query in the pgAdmin I successfully get results.
However when I execute the same query using hibernate I gets the following exception:
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not extract ResultSet
I mustn't show the tables structure but I know that the sql is fine(I've copied the entire content of "sql" then I execute it in pgAdmin); The query looks like:
String sql = "COPY (" + sqlQuery + ") TO STDOUT WITH CSV";
Then I execute it as the following:
Query query = getEntityManager().createNativeQuery(sql);
Object result = query.getSingleResult(); // I also tried the other get results method...(`getFirstresult()` has returned 0)
In any related questions I have found, I saw that the OP put the csv into a file instead of stdout.
Is it possible to return csv result using hibernate?
Thanks in advance!
AFAIK, COPY is not supported natively by PostgreSQL JDBC driver (last tested on postgresql-9.4.1208.jre7). Thus, Hibernate can not run the command.
If you really need to use COPY you should consider a CopyManager: how to copy a data from file to PostgreSQL using JDBC?
But personally, I would advocate you change your approach. Loading data with COPY looks like a kind of a hack to me.
You can have this done with univocity-parsers using two lines of code. You just need to get a resultset from your query and do this:
CsvRoutines routines = new CsvRoutines();
routines.write(resultset, new File("/path/to/output.csv"), "UTF-8");
The write() method takes care of everything. The resultset is closed by the routine automatically.

Java mysql AWS execute succeed and then select does not return the new value

I am working with AWS RDS (specifically mysql) and I am using SQL Workbench/J as a GUI tool. My server side code written in Java and here is my code:
Insert code:
try {
Statement myStatement = insertConnectionObject.createStatement();
myStatement.executeUpdate("INSERT INTO friends VALUES('buddy', '15', '123');");
myStatement.close();
} catch(Exception ex) {
// code for handling exceptions
} finally {
myStatement.close();
insertConnectionObject.close();
}
After that, I call the select code from the same table:
try {
Statement myStatement = selectConnectionObject.createStatement();
ResultSet returnedFriends = myStatement.executeQuery("SELECT * FROM friends;");
//unfortunately, the returnedFriends will not return the new inserted value 'buddy'
} catch(Exception ex) {
// code for handling exceptions
} finally {
myStatement.close();
insertConnectionObject.
unfortunately, the returnedFriends will not return the new inserted value 'buddy'.
If I will click the 'commit any pending database changes' button in the SQL Workbench/J GUI tool, and then run the select statement, the new value 'buddy' will return.
What have I tried until now?
Use the same connection object for both insert and select.
Open and close the connection after the insert command, and after every select command.
disable the auto commit and try to commit manually.
Inserting via code, and then selecting directly from the DB.
Have you tried setAutoCommit(true) on the connection, just in case it isn't?
Also, if your select is just to get a new key don't forget you can call myStatement.getGeneratedKeys() in with the update.
You should use executeQuery() to select . executeUpdate() returns nothing but int. It should give a compile time error, are you sure that the code is compiling rather than running last working version?
executeUpdate(String sql) Executes the given SQL statement, which may
be an INSERT, UPDATE, or DELETE statement or an SQL statement that
returns nothing, such as an SQL DDL statement.
So change your select code as below:
ResultSet returnedFriends = myStatement.executeQuery("SELECT * FROM friends;");
My problem was as simple and annoying as can be - apparently, I had to close the Workbench GUI when working from the code, which is kind of wired and requires probably deeper investigation from the Workbench / AWS teams.
Anyways, after closing this interface, everything just worked.
Thanks for the help!

using MySQL event scheduler with Java

I am trying to create events using Java code with hibernate. I verified my syntax for CREATE EVENT in MySQL Workbench, and I verified my Java code with a simple UPDATE query. But when I am trying to use both it just doesn't work. I am not getting any error message, just that 0 rows were affected. My code is as follows:
String sql = "CREATE EVENT IF NOT EXISTS test_event ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 20 SECOND ON COMPLETION PRESERVE ENABLE DO UPDATE my_table SET last_error_message='my test' WHERE ID=17;";
session.beginTransaction();
SQLQuery query = session.createSQLQuery(sql);
int result = query.executeUpdate();
session.getTransaction().commit();
....
session.close();
thanks a lot
How do you know if any new events were created? You can try
show events from <SCHEME_NAME>;
This will show all the events that are registered to the given schema.try printing the session\statement warning stack...
Get jdbc connection from your session: How to get jdbc connection from hibernate session?
Use JDBC to execute DDL
...
Statement stmt = null;
try {
stmt = conn.createStatement();
stmt.executeUpdate(sql);
} catch (SQLException e) {
// ...
} finally {
// close stmt
}
...
First, you need to make sure your database is prepared to execute an event. for that, you need to run the following command.
SHOW PROCESSLIST;
MySQL uses a special thread called event schedule thread to execute all scheduled events.
if you see your process list like the above picture. you need to run the below command to enable MySQL event execution.
SET GLOBAL event_scheduler = ON;
Then when you execute the "SHOW PROCESSLIST;" command you will see the below list which shows the specific thread for event execution in MySQL.
Now you can create your event using any MySQL client interface.

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