Extract Data from a Data table to a text file in JPA - sql

I'm working on data manipulation and my order is to extract all the content of a table into a text file ! I have already implemented this but apprently, I have commited a mistake while creating the request :
public void extractDonneesFichierPlat(){
TypedQuery<NotificationCnavOP> query = entityManager.createQuery("SELECT * INTO OUTFILE 'C:\\Test.txt' FROM NotificationCnavOP", NotificationCnavOP.class);
}

You cannot use "select * into outfile..." syntax in JPQL which is a separate query language different than SQL. If you want to execute native SQL queries in JPA you must use entityManager.createNativeQuery() method.
But still it is not possible to execute such 'bulk manipulation' query using this method.
The only solution I can think of is to use JDBC instead of JPA and execute:
Object o = entityManager.getDelegate();
System.out.println(o.getClass()); //prints the object class
// in my case it is org.hibernate.internal.SessionImpl
SessionImpl s = (SessionImpl)o;
Connection c = s.connection();
try {
Statement stmt = c.createStatement();
stmt.executeQuery("SELECT * INTO OUTFILE 'C:/Test.txt' FROM NotificationCnavOP");
} catch (SQLException e) {
e.printStackTrace();
}
The actual implementation of Session depends on the provider. In the case of Hibernate it is org.hibernate.internal.SessionImpl.
For newer versions of Hibernate it is org.hibernate.Session and it doesn't have the connection() method. So, you should try:
Object o = entityManager.getDelegate();
Session s = (Session)o;
s.doWork(connection -> {
try {
Statement stmt = connection.createStatement();
stmt.executeQuery("SELECT * INTO OUTFILE 'C:/Test2.txt' FROM NotificationCnavOP");
} catch (SQLException e) {
e.printStackTrace();
}
});
Both versions work in Hibernate 4.

Related

org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "CREATE[*] SCHEMA DATABASE "; SQL statement:

Here the Main class :
public class Main {
// JDBC driver name and database URL
static final String JDBC_DRIVER = "org.h2.Driver";
static final String DB_URL = "jdbc:h2:mem:default";
// Database credentials
static final String USER = "sa";
static final String PASS = "";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// STEP 1: Register JDBC driver
Class.forName(JDBC_DRIVER);
//STEP 2: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL, USER, PASS);
//STEP 3: Execute a query
ScriptRunner sr = new ScriptRunner(conn);
//Creating a reader object
Reader reader = new BufferedReader(new FileReader("C:\\PROJECTS\\src\\main\\resources\\createDatabaseAndUser.sql"));
//Running the script
sr.runScript(reader);
// STEP 4: Clean-up environment
conn.close();
} catch (SQLException se) {
//Handle errors for JDBC
se.printStackTrace();
} catch (Exception e) {
//Handle errors for Class.forName
e.printStackTrace();
} finally {
//finally block used to close resources
try {
if (stmt != null) stmt.close();
} catch (SQLException se2) {
} // nothing we can do
try {
if (conn != null) conn.close();
} catch (SQLException se) {
se.printStackTrace();
} //end finally try
} //end try
System.out.println("Goodbye!");
}
}
createDatabaseAndUser.sql file which located in resourses folder :
CREATE SCHEMA database;
CREATE USER ADMIN PASSWORD 'abc';
I am trying to run my SQL script but receive and ERROR.
Here all output :
Connecting to database...
CREATE SCHEMA database
Error executing: CREATE SCHEMA database.Cause: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error
in SQL statement "CREATE[*] SCHEMA DATABASE"; SQL statement:
CREATE USER ADMIN PASSWORD 'abc'
CREATE SCHEMA database
[42000-199]
Goodbye!
My SQL Dialect is H2 and I use embedded H2 database in Intelij IDEA.
I just begin learning SQL and SQL scripts, so sorry in advance if question is stupid.
It looks like the output from the tool that you use is garbled somehow. There is CREATE[*] SCHEMA DATABASE command ([*] is a marker from H2), but the source SQL is listed as
CREATE USER ADMIN PASSWORD 'abc'
CREATE SCHEMA database
and it is obliviously invalid due to missing semicolon between two commands.
Both places should be the same (with exception for [*] mark) and the error message should be
Syntax error in SQL statement "CREATE USER ADMIN PASSWORD 'abc'
CREATE[*] SCHEMA DATABASE "; SQL statement:
CREATE USER ADMIN PASSWORD 'abc'
CREATE SCHEMA database [42000-199]
So you ether have a missing semicolon in your source file, or this tool removes it. Actually you don't need to use the third-party tool, you can execute the script directly in H2:
Statement st = conn.createStatement();
st.execute("RUNSCRIPT FROM 'C:\\PROJECTS\\src\\main\\resources\\createDatabaseAndUser.sql'");

How do I create a BigQuery view with standard SQL using the Java API?

I can create views using the Java API, but the query needs to be legacy sql:
public void createView(String dataSet, String viewName, String query) throws Exception {
Table content = new Table();
TableReference tableReference = new TableReference();
tableReference.setTableId(viewName);
tableReference.setDatasetId(dataSet);
tableReference.setProjectId(projectId);
content.setTableReference(tableReference);
ViewDefinition view = new ViewDefinition();
view.setQuery(query);
content.setView(view);
LOG.debug("View to create: " + content);
try {
if (tableExists(dataSet, viewName)) {
bigquery.tables().delete(projectId, dataSet, viewName).execute();
}
} catch (Exception e) {
LOG.error("Could not delete table", e);
}
bigquery.tables().insert(projectId, dataSet, content).setProjectId(projectId).execute();
}
Is there a way to create a BQ view with standard sql using the API?
You need to set setUseLegacySQL(false) on the ViewDefinition object.
[..]
ViewDefinition view = new ViewDefinition();
view.setQuery(query);
view.setUseLegacySql(false); //<-- you're missing this
content.setView(view);
[..]
See the API docs here.
With the new API, you can use the "#standardSQL" notation to avoid the default LegacySQL setting (the setUseLegacySql() method no longer exists in the new API).
Here is an example:
ViewDefinition tableDefinition = ViewDefinition.newBuilder("#standardSQL\n WITH A AS (select 1 as foo) SELECT * from A").build();

Apache DBUtils - Why need resultsethandler for Insert?

I run an insert statement using Apache DBUtils. However, I am not sure why I have to include ResultSetHandler for this case:
String theQuery = QueryGenerator.insertintoStats();
ResultSetHandler<Object> dummyHandler = new ResultSetHandler<Object>() {
#Override
public Object handle(ResultSet rs) throws SQLException
{
return null;
}
};
try
{
queryRunner.insert(connection, theQuery, dummyHandler, Constants.UUIDSTR.toString(), name, prevbackupTime,
curbackupTime, updStartTime, delStartTime, bkupType.toString(), rowCount);
}
catch (SQLException e)
{
LOGGER.info(theQuery.toString());
LOGGER.error("Caught exception!", e);
}
Similar's the case for insertbatch which does use ResultSetHandler. I have resorted to use batch call for batch queries. Can anyone explain why we would be needing resultset handler for insert?
From documentation https://commons.apache.org/proper/commons-dbutils/apidocs/:
public <T> T insert(String sql,
ResultSetHandler<T> rsh,
Object... params)
throws SQLException
rsh - The handler used to create the result object from the ResultSet
of auto-generated keys.
If you insert values in a table which generate id upon insertion, you can retrieve it back, for example see this answer how to do this manually : https://stackoverflow.com/a/1915197/947111
You need ResultSetHandler<T> rsh to iterate over ResultSet which returned with id's which has been created.

jdbc and processing output using Jakarta Commons Math

Using jdbc I am querying my database of ambulance response times. My goal is to take the output and process it into statistics using Jakarta Commons Math library. So far I am successful in querying my database and outputting the response times to the console. My next step is to process this output statistically, such as mean, medians, mode, etc. This is where I am stuck. Shown below is my code.
package javaDatabase;
import java.sql.*;
import org.apache.commons.math3.stat.StatUtils;
public class javaConnect3
{
public static void main(String[] args)
{
Connection conn = null;
Statement stmt = null;
try
{
conn = DriverManager
.getConnection("jdbc:sqlserver://myServerAddress;database=myDatabase;integratedsecurity=false;user=myUser;password=myPassword");
stmt = conn.createStatement();
String strSelect = "SELECT M_SecondsAtStatus FROM MManpower WHERE M_tTime > 'august 25, 2014' AND M_Code = 'USAR'";
ResultSet rset = stmt.executeQuery(strSelect);
while (rset.next())
{
int values = rset.getInt("M_SecondsAtStatus");
System.out.println(values);
}
// I am hoping to derive useful statistics from my database, such as the following.
// this uses Jakarta Commons Math
// System.out.println("min: " + StatUtils.min(values));
// System.out.println("max: " + StatUtils.max(values));
// System.out.println("mean: " + StatUtils.mean(values));
// System.out.println("product: " + StatUtils.product(values));
// System.out.println("sum: " + StatUtils.sum(values));
// System.out.println("variance: " + StatUtils.variance(values));
} catch (SQLException ex)
{
ex.printStackTrace();
} finally
{
try
{
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
} catch (SQLException ex)
{
ex.printStackTrace();
}
}
}
}
An error message pops up in Eclipse and the variable "values" is red underlined; "values cannot be resolved to a variable".
I am not sure how to get this to work. I don't understand how to output my ambulance response times from the database into something Apache Commons math will understand.
How can I get Apache Commons math to take the output from my database and generate a statistical result?
You need something like this:
List<Double> values = new ArrayList<Double>();
while (rset.next()) {
values.add(rset.getInt("M_SecondsAtStatus"));
}
double mean = StatsUtils.mean(values.toArray(new Double [](values.size()));
It's likely that you could query the database for statistics. The name of the method depends on your database:
SELECT avg(M_SecondsAtStatus)
FROM MManpower
WHERE M_tTime > 'august 25, 2014'
AND M_Code = 'USAR'
I'd say the second one is more efficient, because you don't have to transfer all those values to the Java JVM to do the same calculation that the database can do for you.
Another alternative is to use a DescriptiveStatistics object to collect all the data and then use it to compute the summary statistics you need. Using it alleviates the need for doing all explicit type casting and conversion:
DescriptiveStatistics ds = new DescriptiveStatistics();
while(rset.next()) {
int observation = rset.getInt("M_SecondsAtStatus");
ds.addValue(observation);
}
System.out.println("min: " + ds.getMin());
System.out.println("max: " + ds.getMax());
...

HQL :Hibernate update query

i use struts2 and hibernate jpa for my app and i have an error when traying using update query with hibernate
here is my code :
in my class dao
#Override
public void UpdateNoteEvaluation() {
try {
String hql="update Evaluation e " +
"SET e.Eval_NoteGlobal =: ( SELECT SUM( sv.SousEval_Note ) AS sum FROM sousevaluation sv )" +
"ORDER BY EVAL_ID DESC LIMIT 1 ";
Query q= session.createQuery(hql);
q.executeUpdate();
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
}
}
in my class Action :
public String saveOrUpdate(){
sousevaldao.UpdateNoteEvaluation();
System.out.println("update note ok ok");
return SUCCESS;
}
so here i can't make the update i get this error :
java.lang.IllegalArgumentException: node to traverse cannot be null!
at org.hibernate.hql.ast.util.NodeTraverser.traverseDepthFirst(NodeTraverser.java:55)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:277)
knowing i have test the update query im phpmyadmin it's work fine
If query has been tested to be working one via phpMyAdmin, it is quite clear that query is SQL query - not a HQL query. Also syntax of query seems to contain MySQL SQL dialect specific LIMIT clause.
Query for native SQL queries can be created via Session.createSQLQuery(String queryString) method:
String sql = ...
Query q = session.createSQLQuery(sql);