Java ResultSet Iteration for SQL Select JSON_OBJ - java

I want to execute the JSON Query using the the following query
string sql = "SELECT JSON_OBJECT ('customerid' VALUE customerID, 'customerutility' VALUE customerutility) FROM customerTABLE";
I need to run this from Java application and store the results in a file.
statement = connection.createStatement();
ResultSet rs = statement.executeQuery(sql);
I am guessing the executeQuery returns a JSON OBJECT. I am not quite sure how to get this object to serialize to a file.
any help in this is greatly appreciated

Honestly I never worked with SQLServer, but I will take the liberty of answering because nobody has done so far..
If I were in your place I would try one of the following options:
I would try to read the JSON as if it were a string: rs.getString("json") where "json" is used as alias
If the first approach doesn't work, I would try with an explicit string cast on the sql side
Both the previous solutions derive from the assumption that, if the json will be written on a file, no typing is necessary, but a string representation of the json is enough.
Otherwise my approach would be to read in the classic way the fields of the table and then turn each row into a json java side, and this operation is very simple:
Json.createObjectBuilder()
.add("customerid", 1)
.add("customerUtility", "something")
.build();

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

Java prepared statement does not allow large strings in the where clause of the query

I am trying to retrieve data from DB2 using Java prepared statement
String select_statement = "SELECT * FROM schema_name.table_name where NME='xxx002' and LINE =7200 and FILE_NME='720001042021XYZ002' with ur";
try (Connection connection = DataBaseConnection.getGeoCarDBConnection_TESTDATA();
PreparedStatement ps = connection.prepareStatement(select_statement);) {
ResultSet rs = null;
rs = ps.executeQuery();
}
The problem I am facing is that I include the FILE_NME in the where clause of the query, as shown above, 0 rows are returned. But any other string fields can be passed and I get the desired number of rows.
Any integer fields in the where clause works too.
But only the string fields that are large(In this case, FILE_NME field) are not working. In the DB2 table, where I am pulling the data from, the FILE_NME field is of varchar(30).
Things that did not work for me was
String select_statement = "SELECT * FROM schema_name.table_name where NME='xxx002' and LINE =7200 and FILE_NME = ? with ur";
then I set the String value using,
ps.setString(1, "'720001042021XYZ002'")
ps.setString(1, "720001042021XYZ002")
Both did not work.
None of the google links were helpful. Have spent more than a day on it.
This code used to work flawlessly before, Even the java version hasn't changed(as per my knowledge)
I am running it in windows 10.
Java version : 1.8 ((build 1.8.0_221-b11))
I run the same query in the database client and it works.
Someone please help me or point me in the right direction. I don't know what I am missing
Thank in advance
The problem was that there was indeed no data, I was checking the same query in the database client in a different environment. I am closing this.

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.

How can I Insert JSON object into Postgres using Java preparedStatement?

I’m struggling to insert a JSON object into my postgres v9.4 DB. I have defined the column called "evtjson" as type json (not jsonb).
I am trying to use a prepared statement in Java (jdk1.8) to insert a Json object (built using JEE javax.json libraries) into the column, but I keep running into SQLException errors.
I create the JSON object using:
JsonObject mbrLogRec = Json.createObjectBuilder().build();
…
mbrLogRec = Json.createObjectBuilder()
.add("New MbrID", newId)
.build();
Then I pass this object as a parameter to another method to write it to the DB using a prepared statement. (along with several other fields) As:
pStmt.setObject(11, dtlRec);
Using this method, I receive the following error:
org.postgresql.util.PSQLException: No hstore extension installed.
at org.postgresql.jdbc.PgPreparedStatement.setMap(PgPreparedStatement.java:553)
at org.postgresql.jdbc.PgPreparedStatement.setObject(PgPreparedStatement.java:1036)
I have also tried:
pStmt.setString(11, dtlRec.toString());
pStmt.setObject(11, dtlRec.toString());
Which produce a different error:
Event JSON: {"New MbrID":29}
SQLException: ERROR: column "evtjson" is of type json but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
But, at least this tells me that the DB is recognizing the column as type JSON.
I did try installing the hstore extension, but it then told me that it was not an hstore object.
OracleDocs shows a number of various methods to set the parameter value in the preparedStatement, but I'd rather not try them all if someone knows the answer. (http://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html) These also reference an additional parameter, SQLType, but I can't find any reference to these.
Should I try setAsciiStream? CharacterStream? CLOB?
This behaviour is quite annoying since JSON strings are accepted without problems when used as literal strings in SQL commands.
There is a already an issue for this in the postgres driver Github repository (even if the problem seems the be the serverside processing).
Besides using a cast (see answer of
#a_horse_with_no_name) in the sql string, the issue author offers two additional solutions:
Use a parameter stringtype=unspecified in the JDBC connection URL/options.
This tells PostgreSQL that all text or varchar parameters are actually
of unknown type, letting it infer their types more freely.
Wrap the parameter in a org.postgresql.util.PGobject:
PGobject jsonObject = new PGobject();
jsonObject.setType("json");
jsonObject.setValue(yourJsonString);
pstmt.setObject(11, jsonObject);
You can do it like this and you just need the json string:
Change the query to:
String query = "INSERT INTO table (json_field) VALUES (to_json(?::json))"
And set the parameter as a String.
pStmt.setString(1, json);
You have two options:
Use statement.setString(jsonStr) and then handle the conversion in the sql statement:
PreparedStatement statement = con.prepareStatement(
"insert into table (jsonColumn) values (?::json)");
statement.setString(1, jsonStr);
Another option is to use PGobject to create a custom value wrapper.
PGobject jsonObject = new PGobject();
PreparedStatement statement = con.prepareStatement(
"insert into table (jsonColumn) values (?)");
jsonObject.setType("json");
jsonObject.setValue(jsonStr);
statement.setObject(1, jsonObject);
I personally prefer the latter as the query is cleaner
Passing the JSON as a String is the right approach, but as the error message tells you, you need to cast the parameter in the INSERT statement to a JSON value:
insert into the_table
(.., evtjson, ..)
values
(.., cast(? as json), ..)
Then you can use pStmt.setString(11, dtlRec.toString()) to pass the value
Most answers here defines ways of inserting into postgres json field with jdbc in a non-standard way, ie. it is db implementation specific. If you need to insert a java string into a postgres json field with pure jdbc and pure sql use:
preparedStatement.setObject(1, "{}", java.sql.Types.OTHER)
This will make the postgres jdbc driver (tested with org.postgresql:postgresql:42.2.19) convert the java string to the json type. It will also validate the string as being a valid json representation, something that various answers using implicit string casts does not do - resulting in the possibility of corrupt persisted json data.
As others have mentioned, your SQL string needs to explicitly cast the bind value to the PostgreSQL json or jsonb type:
insert into t (id, j) values (?, ?::json)
Now you can bind the string value. Alternatively, you can use a library that can do it, for example jOOQ (works out of the box) or Hibernate (using a third party UserType registration). The benefits of this is that you don't have to think about this every time you bind such a variable (or read it). A jOOQ example:
ctx.insertInto(T)
.columns(T.ID, T.J)
.values(1, JSON.valueOf("[1, 2, 3]"))
.execute();
Behind the scenes, the same cast as above is always generated, whenever you work with this JSON (or JSONB) data type.
(Disclaimer: I work for the company behind jOOQ)
if using spring boot: adding the following line to application.properties helped:
spring.datasource.hikari.data-source-properties.stringtype=unspecified
as Wero wrote:
This tells PostgreSQL that all text or varchar parameters are actually
of unknown type
Instead of passing json object pass its string value and cast it to json in the query.
Example:
JSONObject someJsonObject=..........
String yourJsonString = someJsonObject.toString();
String query = "INSERT INTO table (json_field) VALUES (to_json(yourJsonString::json))";
this worked for me.

Any way to return a ResultSet in Java?

I found out that Java doesn't let ResultSet to be return as a data type. And would like to ask whether is there any better solution to return results after executing query?
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/shopping mall?zeroDateTimeBehavior=convertToNull", "root", "" );
java.sql.Statement stmt = con.createStatement() ;
String query = "SELECT * FROM shops WHERE SHOPNAME LIKE \'%" + shopName + "%\' ORDER BY shopname ASC"; // Select and sort using user input
ResultSet rs = stmt.executeQuery(query) ;
// How to return the result after executing the query?
}
catch ( SQLException err ) {
return null;
}
Don't mind the return null; part. Was testing something. Basically this is my current code for now. How can I return the result after executing query?
You need to provide better context for the error. Is this, for example, a JAX-WS web service endpoint? Anyway, as stated in the trace, your error is a web service error--not a JDBC error. This error can happen for many reasons--usually related to something wrong with the way you are defining the API to your service.
You are certainly allowed to return a ResultSet from a method even if that is a very bad idea, especially from a web service endpoint. A ResultSet can't be serialized into a SOAP message. More generally, to return a ResultSet betrays implementation details to the callers of the method. Why should they know you are using JDBC? Or even that you are talking to a relational (or any) database at all?
The better approach is to populate a model object relevant to your domain with the data in the ResultSet, and that object will be serialized to SOAP via JAXB or whatever you use. Or maybe you just return some text from the database, in which case JAX-WS knows what to do.
Also, make sure you do something with SQLException so you can trace the cause of your actual JDBC errors.
You write a method to retrieve info from a database, where should the data be processed and put into a model class? If you want code that is loosely coupled, then 98% of the time you would process the result set within the same method.
What happens if the query needs to change? You want the changes to be localized into a small of a subset of code as possible.
Take a look at Spring-JDBC JdbcTemplate. This method
List<Map<String, Object>> queryForList(String sql)
returns a List that contains a Map per row. You can use it or make something similar

Categories

Resources