SnappyData JDBC driver raising SQLState=XCL14 error - snappydata

SnappyData v.0-5 w/ ClientDriver JDBC driver.
I have a persistent row table in SnappyData called: sensor_data.
From the snappy> shell, this query returns thousands for rows.
snappy> select * from sensor_data where year_num = 2013 and
month_num = 1;
When run from a JDBC connection in SpringBoot, I get this error:
PreparedStatementCallback; uncategorized SQLException for SQL [select
* from sensor_data where year_num = ? and month_num = ?]; SQL state [XCL14]; error code [20000]; (SQLState=XCL14 Severity=20000) The
column position '1' is out of range. The number of columns for this
ResultSet is '0'.
Java Code is:
List<SensorData> list = jdbcTemplateBean.query("select * from sensor_data where year_num = ? and month_num = ?",
new Object[] {year, month}, new SensorDataRowMapper());
What do I need to do to fix this JDBC issue?
Trimmed Stacktrace on Spring boot:
org.springframework.jdbc.UncategorizedSQLException:
PreparedStatementCallback; uncategorized SQLException for SQL [select
* from sensor_data where year_num = ? and month_num = ?]; SQL state [XCL14]; error code [20000]; (SQLState=XCL14 Severity=20000) The
column position '1' is out of range. The number of columns for this
ResultSet is '0'.; nested exception is java.sql.SQLException:
(SQLState=XCL14 Severity=20000) The column position '1' is out of
range. The number of columns for this ResultSet is '0'. at
org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:84)
at
org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at
org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at
org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:645)
at
org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:680)
at
org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:707)
at
org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:757)
at
org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:192)
at
org.kritek.scalability.repository.SensorDataRepository.findByYearAndMonth(SensorDataRepository.java:58)
...
at
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745) Caused by:
java.sql.SQLException: (SQLState=XCL14 Severity=20000) The column
position '1' is out of range. The number of columns for this
ResultSet is '0'.
...
Caused by: ERROR XCL14: The column position '1' is out of
range. The number of columns for this ResultSet is '0'. at
com.pivotal.gemfirexd.internal.client.am.ColumnMetaData.checkForValidColumnIndex(ColumnMetaData.java:856)
at
com.pivotal.gemfirexd.internal.client.am.ColumnMetaData.getColumnType(ColumnMetaData.java:638)
... 72 more

From the stack it looks like NamedParameterJdbcTemplate is being used but '?' placeholders are being used. For NamedParameterJdbcTemplate you need to use named parameters like here.
I will recommend using the standard '?' placeholder mechanism with JdbcTemplate like:
private JdbcTemplate jdbcTemplateBean;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplateBean = new JdbcTemplate(dataSource);
}
List<SensorData> list = jdbcTemplateBean.query(
"select * from sensor_data where year_num = ? and month_num = ?",
new Object[] { year, month }, new SensorDataRowMapper());

The issue has been resolved. Here is what happened.... SnappyData routed the query to Spark because it determined it could not handle it. Spark knows nothing about JDBC PreparedStatements or bind variables and raised the error. To fix, I had to set the SnappyData JDBC property "route-query = false" in my DataSource configuration. This ensured it was not routed to Spark.

Related

How I can get the correct date of my Mysql query without the query itself subtracting one day to date

My problem is that in a table of my database with 7 columns, I have a column of date type, called "Fecnac". Through MYSQLworkbrench, I execute a simple query:
"SELECT * FROM tblAsegurados ORDER BY Name,Nss"
As a result of this query, the information of my columns or fields of the table is displayed, the table contains a column named "Fecnac" that shows the correct date, for example "2018-12-31".
MYSQLworkbrench Result image
However, I developed an application in intelliJ IDEA to execute the same query, and the query "by itself" returns the date with one day less, that is, it shows "2018-12-30". And so it does with all the dates found in the "Fecnac" column of the "tblAsegurados" table in my database.
public ArrayList<Asegurados> getAseguradosList(){
ArrayList<Asegurados> aseguradosList = new ArrayList<Asegurados>();
Connection connection = getConnection();
var query = "select * from tblAsegurados order by Nombre,Nss";
Statement st;
ResultSet rs;
try{
st = connection.createStatement();
rs = st.executeQuery(query);
Asegurados asegurado;
while(rs.next()){
asegurado = new Asegurados(
rs.getString("Nss"),
rs.getString("Nombre"),
rs.getString("Curp"),
rs.getBoolean("Esposa"),
rs.getInt("Semcot"),
rs.getInt("Hijos"),
rs.getDate("Fecnac"));
aseguradosList.add(asegurado);
System.out.println(asegurado.getFecnac());
System.out.println(rs.getDate("Fecnac"));
System.out.println(rs.getDate(7));
}
} catch (Exception e){
e.printStackTrace();
}
return aseguradosList;
}
The class "Asegurados" has an attribute of type "java.sql.date" defined, to receive "rs.getdate (Fecnac).
For i be sure of the values ​​returned by the query, in my code you can see that I made a "System.out.println" for each field date, and in all three I get the same value from the date with one day less.
Could someone help me know what happens?
Console debug IntelliJ Idea image
I already found the solution. In a part of my code, the parameter of the time zone had it defined as: serverTimezone = UTC
public static Connection getMySQLConnection() throws Exception {
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost/imss"+
"?useUnicode=true&useJDBCCompliantTimezoneShift=true"+
"&useLegacyDatetimeCode=false&serverTimezone=America/Mexico_City"+
"&verifyServerCertificate=false"+
"&useSSL=true"+
"&requireSSL=true";
String username = "root";
String password = "juan1980";
Class.forName(driver);
return DriverManager.getConnection(url, username, password);
}
I set it to: serverTimezone = america / Mexico_City, which is the zone that corresponds to me, and ready! the date is displayed correctly.

Selecting multiple columns and set it to list of DTOs

I want to get multiple columns from database in a single query and set it to the corresponding DTO object fields.
Error message:
java.lang.IllegalStateException: No data type for node:
org.hibernate.hql.internal.ast.tree.IdentNode
+-[IDENT] IdentNode: 'payment' {originalText=payment}
Query:
TypedQuery<Object[]> query = entityManager.createQuery("SELECT
payment, createdOn,responseMessage FROM PaymentLog log WHERE log.id
=:personId", Object[].class);
query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<Object[]> results = query.getResultList();
for (Object[] log : results) {
paymentTransaction.setAmount(log[0].toString());
paymentTransaction.setDate(log[1].toString());
paymentTransaction.setDescription(log[2].toString());
transactionList.add(paymentTransaction);
}
P.S. I know I can use JPA constructor expression. But as I have to add the DTOs in a list of DTO(i.e. transactionList), so is there a way with JPA construction expression where I can do that by running the query only one time instead in a loop for every single DTO?
You can have the JPA provider transform the result set for you by means of a constructor expression:
http://www.objectdb.com/java/jpa/query/jpql/select#Result_Classes_Constructor_Expressions_
https://en.wikibooks.org/wiki/Java_Persistence/JPQL#Constructors
This requires that the specified class has a constructor matching the select expression. This would then look something like the below:
TypedQuery<PaymentTransaction> query = entityManager.createQuery("SELECT new PaymentTransaction (log.payment, log.createdOn, log.responseMessage ) FROM PaymentLog log WHERE log.id
=:personId", PaymentTransaction.class);
query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<PaymentTransaction> results = query.getResultList();
In JPA 2.1 you can also so like the below:
https://en.wikibooks.org/wiki/Java_Persistence/Querying#ConstructorResult_.28JPA_2.1.29
What you could do is:
TypedQuery<PaymentLog> query = entityManager.createQuery("SELECT log FROM PaymentLog log WHERE log.id =:personId", PaymentLog.class);
query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<PaymentLog> results = query.getResultList();
for (PaymentLog log : results) {
paymentTransaction.setAmount(log.getPayment());
paymentTransaction.setDate(log.getCreatedOn());
paymentTransaction.setDescription(log.getResponseMessage());
transactionList.add(paymentTransaction);
}
It is not a good idea to select everything from the database if you are not going to use it. If the selected fields were the only columns in the table then approach above works.
If you had a lot more columns in the table, the previous would still work, but this might be better:
TypedQuery<PaymentTransaction> query = entityManager.createQuery("SELECT new PaymentTransaction (log.payment, log.createdOn, log.responseMessage) FROM PaymentLog log WHERE log.id =:personId", PaymentTransaction.class);
query.setParameter("personId",new BigInteger(basicEntityDto.getId()));
List<PaymentTransaction> results = query.getResultList();
The above query will return an already created list of PaymentTransactions. You have to note that the class PaymentTransactionshould have a constructor that accept these fields in the given order. Otherwise it will cause an exception

JdbcTemplate 'IN' search not working properly

I am trying to perform IN search using JbdcTemplate in Spring. Here goes my code
#Override
public Map<String, List> dataRetriveForAsset(String type) {
List<Integer> interfaceIdList = new ArrayList<Integer>();
List<Integer> fileList = new ArrayList<Integer>();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String sql2 = "select interface_id from tbl_interface_asset where asset_id in ( :ids )";
//fileList is populated with a different query
Set<Integer> ids = new HashSet(Arrays.asList(new Integer[fileList.size()] ));
for(int i=0; i<fileList.size();i++)
{
ids.add(fileList.get(i));
}
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("ids", ids);
interfaceIdList = jdbcTemplate.query(sql2,new ListMapper1(),parameters );
and the sql2 query part executes it throws the following error.
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/iccdashboard] threw exception [Request processing failed; nested exception is org.springframework.dao.TransientDataAccessResourceException: PreparedStatementCallback; SQL [select interface_id from tbl_interface_asset where asset_id in ( :ids )]; Invalid argument value: java.io.NotSerializableException; nested exception is java.sql.SQLException: Invalid argument value: java.io.NotSerializableException] with root cause
java.io.NotSerializableException: org.springframework.jdbc.core.namedparam.MapSqlParameterSource
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at com.mysql.jdbc.PreparedStatement.setSerializableObject(PreparedStatement.java:4401)
at com.mysql.jdbc.PreparedStatement.setObject(PreparedStatement.java:4083)
at org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:351)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:216)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:144)
But if I use NamedParameterJdbcTemplate, I am getting a BadSQLGrammarError because the 'ids' value my sql query goes emplty like below.
select interface_id from tbl_interface_asset where asset_id in ( )
java.io.NotSerializableException: org.springframework.jdbc.core.namedparam.MapSqlParameterSource
I was able to fix this problem by replacing my usage of
org.springframework.jdbc.core.JdbcTemplate
with the:
org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
I was using the MapSqlParameterSource class but using the standard template which may have been the problem.
But if I use NamedParameterJdbcTemplate, I am getting a BadSQLGrammarError because the 'ids' value my sql query goes empty like below.
Can you make the SQL generation conditional on whether or not there are entries in your IN collection?
if (!ids.isEmpty()) {
parameters.addValue("ids", ids);
}

SQL WHERE LIKE clause in JSF managed bean

Hi i have this managed bean where it makes MySQL queries, the problem here is the SQL statement makes a '=' condition instead of 'LIKE'
Here is the code in my managed bean.
Connection con = ds.getConnection();
try{
if (con == null) {
throw new SQLException("Can't get database connection");
}
}
finally {
PreparedStatement ps = con.prepareStatement(
"SELECT * FROM Clients WHERE Machine LIKE '53'");
//get customer data from database
ResultSet result = ps.executeQuery();
con.close();
List list;
list = new ArrayList();
while (result.next()) {
Customer cust = new Customer();
cust.setMachine(result.getLong("Machine"));
cust.setCompany(result.getString("Company"));
cust.setContact(result.getString("Contact"));
cust.setPhone(result.getLong("Phone"));
cust.setEmail(result.getString("Email"));
//store all data into a List
list.add(cust);
}
return list;
Here the SELECT command does not pull all the numbers in 'Machine' column which is like 53, but if i enter a whole value, such as the complete number (53544) in place of 53 then the result is pulled up. I am confused !!
Also if i replace the above select statement with SELECT * FROM Clients the entire database is stored in list. Any ideas ?
Use wildcards:
Like '%53%'
...means everything that contains '53'.
Like '%53' - it ends with 53
LIKE '53%' - it starts with 53
You can also use _ if You want to replace a single character.
You can find a descriptipn HERE
You sql query should be
"SELECT * FROM Clients WHERE Machine LIKE '%53%'

JPA native query for LONGTEXT field in a MySQL view results in error

I have the following JPA SqlResultSetMapping:
#SqlResultSetMappings({
#SqlResultSetMapping(name="GroupParticipantDTO",
columns={
#ColumnResult(name="gpId"),
#ColumnResult(name="gpRole"),
// #ColumnResult(name="gpRemarks")
}
)
Which is used like this:
StringBuilder sbQuery = new StringBuilder("Select ");
sbQuery.append(" gpId, ");
sbQuery.append(" gpRole, ");
// sbQuery.append(" gpRemarks ");
sbQuery.append(" FROM v_group_participants_with_details ");
Query query = em.createNativeQuery(sbQuery.toString(), "GroupParticipantDTO");
The view is like this:
DROP VIEW IF EXISTS `v_group_participants_with_details`;
CREATE VIEW `v_group_participants_with_details`
AS
SELECT
gp.id AS gpId,
gp.role AS gpRole,
gp.remarks AS gpRemarks
FROM GroupParticipation gp
;
The GroupParticipation table has the remarks column defined as LONGTEXT (I'm using Mysql 5.x)
Now for the problem:
When the remarks field is commented out from the query everything works perfectly, but if I try to include the remarks field in the query, I get the following error:
javax.persistence.PersistenceException: org.hibernate.MappingException:
No Dialect mapping for JDBC type: -1
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException
(AbstractEntityManagerImpl.java:614)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:76)
What gives? How can I get a LONGTEXT column from a native query?
This problem is reported in HHH-1483 and HHH-3892. In short, Hibernate does not know, how to map a LONGVARCHAR column returned by a native query.
This problem is fixed in Hibernate 3.5.0+. For previous versions, a workaround would be to extend the MysqlDialect to register the correct Hibernate Type for a LONGVARCHAR:
import java.sql.Types;
import org.hibernate.Hibernate;
public class MyMySQL5Dialect extends org.hibernate.dialect.MySQL5Dialect {
public MyMySQL5Dialect() {
super();
// register additional hibernate types for default use in scalar sqlquery type auto detection
registerHibernateType(Types.LONGVARCHAR, Hibernate.TEXT.getName());
}
}