Hibernate, postgres CTE and native SQL query mapping ARRAY[]::BYTEA[] with addScalar - postgresql

I am trying to execute the following common table expression as a native SQL query in hibernate. Although this is a CTE starting with "WITH" clause, I have seen other examples where this was working with native SQL. I am executing this query on a table called node with the following 2 field
#Id
#Type(type = "uuid-binary")
#Column(name="ID", unique = true, nullable=false)
protected UUID id;
#Type(type = "uuid-binary")
#Column(name="PARENT_ID", nullable=true)
private UUID parentId;
This query has been taken from the official PostgreSQL wiki from here
and just modified a little bit i.e. i have removed the restriction
"WHERE parent_id IS NULL".
If I execute this query in pgAdmin4, then I get a success and I know it works as it should. i.e. I get the expected output that look like this:
Notice the type of the second column called ancestors is "bytea[]" (Not to be confused with byte[]).
It seems that I am not able to map this i.e. i thing that the problem is the mapping of the array of bytea i.e. " ARRAY[]::BYTEA[]" and the following
.addScalar("ancestors")
Session session = getSessionFactory().openSession();
session.beginTransaction();
String sql_query =
" WITH RECURSIVE tree AS ("
+ " SELECT id, ARRAY[]::BYTEA[] AS ancestors"
+ " FROM node "
+ " UNION ALL"
+ " SELECT node.id, tree.ancestors || node.parent_id"
+ " FROM node, tree"
+ " WHERE node.parent_id = tree.id"
+ " ) SELECT * FROM tree WHERE decode(:Argument1, 'hex') = ANY(tree.ancestors)"
;
Query<Object[]> query = session.createNativeQuery(sql_query)
.addScalar("id", org.hibernate.type.StandardBasicTypes.BINARY.INSTANCE)
.addScalar("ancestors")
;
String nodeIdHex = UUIDOperations.uuidToHex(node.getID() );
query.setParameter("Argument1", nodeIdHex, org.hibernate.type.StringType.INSTANCE);
List<Object[]> objectCollection = (List<Object[]>) query.list();
session.getTransaction().commit();
session.close();
return objectCollection;
When i execute this i get the following error :
Hibernate: WITH RECURSIVE tree AS ( SELECT id, ARRAY[]:BYTEA[] AS ancestors FROM node UNION ALL SELECT node.id, tree.ancestors || node.parent_id FROM node, tree WHERE node.parent_id = tree.id ) SELECT * FROM tree decode(?, 'hex') = ANY(tree.ancestors)
2018-12-11 09:11:38.200 WARN pc --- [ main] o.h.e.j.s.SqlExceptionHelper : SQL Error: 0, SQLState: 42601
2018-12-11 09:11:38.202 ERROR pc --- [ main] o.h.e.j.s.SqlExceptionHelper : ERROR: syntax error at or near ":"
Position: 45
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1514)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy238.findAllSubNodesRecursively(Unknown Source)
....
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
....
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
....
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1505)
... 58 more
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near ":"
Position: 45
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2183)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:143)
at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:106)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:60)
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.springframework.orm.hibernate5.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:230)
at org.springframework.orm.hibernate5.HibernateExceptionTranslator.convertHibernateAccessException(HibernateExceptionTranslator.java:102)
at org.springframework.orm.hibernate5.HibernateExceptionTranslator.translateExceptionIfPossible(HibernateExceptionTranslator.java:77)
....
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 49 more
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near ":"
Position: 45
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2183)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:143)
at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:106)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:60)
... 72 more
I suspect that the problem is in the " ARRAY[]::BYTEA[]" mapping but i just have no idea how to map that correctly.
I have tried to create a special user type that will help me map that but it does not seem help me in this case or i have implemented it the wrong way.
Type byteArrayType = new CustomType(new ByteaArrayUserType());
Query<Object[]> query = session.createNativeQuery(sql_query)
.addScalar("id", org.hibernate.type.StandardBasicTypes.BINARY.INSTANCE)
.addScalar("ancestors", byteArrayType)
;
here is the mapping class below:
import java.io.Serializable;
import java.sql.Array;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
public class ByteaArrayUserType implements UserType {
protected static final int[] SQL_TYPES = { Types.ARRAY };
#Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return this.deepCopy(cached);
}
#Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
#Override
public Serializable disassemble(Object value) throws HibernateException {
return (byte[][]) this.deepCopy(value);
}
#Override
public boolean equals(Object x, Object y) throws HibernateException {
if (x == null) {
return y == null;
}
return x.equals(y);
}
#Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
#Override
public boolean isMutable() {
return true;
}
#Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
#Override
public Class<byte[][]> returnedClass() {
return byte[][].class;
}
#Override
public int[] sqlTypes() {
return new int[] { Types.ARRAY };
}
#Override
public Object nullSafeGet(
ResultSet resultSet,
String[] names,
SharedSessionContractImplementor session, Object owner
)throws HibernateException, SQLException {
if (resultSet.wasNull()) {
return null;
}
if (resultSet.getArray(names[0]) == null) {
return new byte[0];
}
Array array = resultSet.getArray(names[0]);
byte[][] javaArray = (byte[][]) array.getArray();
return javaArray;
}
#Override
public void nullSafeSet(PreparedStatement statement,
Object value, int index,
SharedSessionContractImplementor session
)throws HibernateException, SQLException {
Connection connection = statement.getConnection();
if (value == null) {
statement.setNull(index, SQL_TYPES[0]);
} else {
byte[][] castObject = (byte[][]) value;
Array array = connection.createArrayOf("byte", castObject);
statement.setArray(index, array);
}
}
}
The reason i believe this has to do with the ARRAY[]::BYTEA is because if i simplify the query to something simple as :
SELECT id, ARRAY[]::BYTEA[] AS ancestors
FROM node
I still get the same error , however this time it says
[ main] o.h.e.j.s.SqlExceptionHelper : SQL Error: 0, SQLState: 42601
[ main] o.h.e.j.s.SqlExceptionHelper : ERROR: syntax error at or near ":"
Position: 20
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
so what is wrong with that ":" colon. This time only the position is different i.e. 20 instead of 45 on the previous exception

Related

java.lang.NullPointerException occur upon execution

Null pointer exception occurs when you reference a null object, doesn't it? I intend to create an app that manages a store's data such as purchase (stock purchase), stock list, sales, and customer info. The data is intended to be displayed on the app table as soon as the file dynamicmenu1 is run, without clicking any button, but it only displays hard-coded data instead.
app interface
Data to be displayed from table
at view.dynamicmenu1.simpannotaActionPerformed(dynamicmenu1.java:984)
at view.dynamicmenu1.access$1000(dynamicmenu1.java:37)
at view.dynamicmenu1$11.actionPerformed(dynamicmenu1.java:404)
private void simpannotaActionPerformed(java.awt.event.ActionEvent evt) {
tabmodel.addRow(data); // line 984
try {
/** con = (Connection) Model.koneksidatabase();
java.sql.PreparedStatement prepstmnt = con.prepareStatement(sql);
*/
Statement stmnt = con.createStatement();
String sql = "Insert into tb_pembelian VALUES ('" + textid.getText()+"','"
+textnamabrg.getText()+"','"+textqty.getText()
+"','"+texthrg.getText()+"','"+texttgl.getText()+"','"+textsupplier.getText();
//cek stmnt di 'Model.java' di bagian ArrayList barang().
//Mengapa selalu Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
//at view.dynamicmenu1.simpannotaActionPerformed(dynamicmenu1.java:960)
//at view.dynamicmenu1.access$900(dynamicmenu1.java:21)
//at view.dynamicmenu1$10.actionPerformed(dynamicmenu1.java:378)??????
//NullPointerException??????
stmnt.executeUpdate(sql);
stmnt.close();
JOptionPane.showMessageDialog(null, "Data telah disimpan");
kosongkanform();
} catch ( HeadlessException| SQLException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
}
textid.setText("");
textnamabrg.setText("");
textqty.setText("");
texthrg.setText("");
texttgl.setText("");
textsupplier.setText("");
}
// line 37
public class dynamicmenu1 extends javax.swing.JFrame {
String id_barang;
String nama_barang;
String kuantitas;
String harga_satuan;
String tanggal_beli;
DefaultTableModel tabmodel;
Connection con =null;
Statement stmnt=null;
PreparedStatement prepstmnt;
ResultSet res = null;
String sql = null;
the 3rd null pointer exception error
simpannota.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
simpannotaActionPerformed(evt); // Line 404
}
});
Null pointer errors happen when there isn't anything present.
Have you checked your constructor for proper init for your variables.

How to use the Postgres any-clause with JPA/Hibernate native queries (array parameters)

So we've got a whole lot of Postgres SQL queries stored in files and used from PHP. The task is to replace PHP with Java. We want to reuse as much of the queries "as is" to keep the migration path short. I can't get the Array parameters to work.
Here's a query example:
update user_devices
set some_date = now()
where some_id in (
select distinct some_id from user_devices
where user_id = any(:userIDs) and device_id = any(:deviceIDs)
and exists (select 1 from users where user_id = any(:userIDs) and customer_id = :customerID)
);
Note the "any" clauses, which cause the problem, because they expect an array type.
This is how we used them from PHP:
$this->allValues['userIDs'] = '{' . implode ( ",", $userIdNodes ) . '}';
$this->allValues['deviceIDs'] = '{' . implode ( ",", $deviceIdNodes ) . '}';
$this->allValues['customerID'] = customerID;
$this->db->runQuery ( $this->getQuery ( 'my_query' ), $this->allValues );
So as parameters the array types look like "{111,222}".
This is what I tried in Java:
Integer customerID = 1;
int[] userIDs = new int[]{111,222};
int[] deviceIDs= new int[]{333,444};
//List<Integer> userIDs = Arrays.asList(111,222);
//List<Integer> deviceIDs= Arrays.asList(333,444);
//java.sql.Array userIDs = toArray("integer", new int[]{111,222}));
//java.sql.Array deviceIDs= toArray("integer", new int[]{333,444}));
//java.sql.Array userIDs = toArray("integer", Arrays.asList(111,222)));
//java.sql.Array deviceIDs= toArray("integer", Arrays.asList(333,444)));
//String userIDs = "{111,222}";
//String deviceIDs= "{333,444}";
//String userIDs = "ARRAY[111,222]";
//String deviceIDs= "ARRAY[333,444]";
Query nativeQuery = em.createNativeQuery(queryString);
nativeQuery.setParameter("userIDs", userIDs);
nativeQuery.setParameter("deviceIDs", deviceIDs);
nativeQuery.setParameter("customerID", customerID);
//nativeQuery.setParameter(createParameter("userIDs",java.sql.Array.class), userIDs);
//nativeQuery.setParameter(createParameter("userIDs",java.sql.Array.class), deviceIDs);
//nativeQuery.setParameter(createParameter("customerID", Integer.class), customerID);
query.executeUpdate();
//[...]
private Array toArray(String typeName, Object... elements) {
Session session = em.unwrap(Session.class); // ATTENTION! This is Hibernate-specific!
final AtomicReference<Array> aRef = new AtomicReference<>();
session.doWork((c) -> {
aRef.set(c.createArrayOf(typeName, elements));
});
return aRef.get();
}
private <T> Parameter<T> createParameter(final String name, final Class<?> clazz) {
return new Parameter<T>() {
#Override
public String getName() {
return name;
}
#Override
public Integer getPosition() {
return null; // not used
}
#Override
public Class<T> getParameterType() {
return (Class<T>) clazz;
}
};
}
None of these will work I will get one of these exceptions:
When using the "toArray" method:
Caused by: org.hibernate.HibernateException: Could not determine a type for class: org.postgresql.jdbc4.Jdbc4Array
at org.hibernate.internal.AbstractQueryImpl.guessType(AbstractQueryImpl.java:550)
at org.hibernate.internal.AbstractQueryImpl.guessType(AbstractQueryImpl.java:534)
at org.hibernate.internal.AbstractQueryImpl.determineType(AbstractQueryImpl.java:519)
at org.hibernate.internal.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:487)
at org.hibernate.jpa.internal.QueryImpl$ParameterRegistrationImpl.bindValue(QueryImpl.java:247)
at org.hibernate.
Or when using int[] or Strings, I'll get:
Caused by: org.postgresql.util.PSQLException: ERROR: op ANY/ALL (array) requires array on right side
Position: 137
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:570)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:420)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:366)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection$StatementHandler.invoke(AbstractJdbc23PooledConnection.java:453)
at com.sun.proxy.$Proxy274.executeUpdate(Unknown Source)
at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:125)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
jpa.spi.BaseQueryImpl.setParameter(BaseQueryImpl.java:582)
Using Wireshark I found this when both APIs are talking to the database:
Image: Comparison of database calls with Wireshark
select oid, typname from pg_type where oid in (0, 23, 1043) order by oid;
oid |typname
------+-------
23 |int4
1043 |varchar
Has anyone managed to use array-parameters with native queries using Hibernate as backend for the JPA EntityManager? If so: How?
Change your query from where user_id = any(:userIDs) to where user_id IN (:userIDs), and change the userIDs array to a collection e.g. List<Long>. You will have to additionally protect it empty lists, but it will work.
I was able to work around this problem by unwrapping the Hibernate session from the EntityManager and use a JDBC PreparedStatement, which eats the java.sql.Array parameters without any complaint.
The NamedParameterStatement used in the example below is described here (I've modified it to my needs). It delegates to a PreparedStatement.
The rest of the code goes a little something like this:
public int executeUpdate(...){
//....
Integer customerID = 1;
java.sql.Array userIDs = toArray("integer", new int[]{111,222}));
java.sql.Array deviceIDs= toArray("integer", new int[]{333,444}));
final AtomicInteger rowsModifiedRef = new AtomicInteger();
final Session session = em.unwrap(Session.class); // ATTENTION! This is Hibernate-specific!
session.doWork((c) -> {
try (final NamedParameterStatement statement = new NamedParameterStatement(c, queryString)) {
statement.setObject("deviceIDs", userIDs);
statement.setObject("userIDs", userIDs);
statement.setObject("customerID", userIDs);
rowsModifiedRef.set(statement.executeUpdate());
}
});
return rowsModifiedRef.get();
}
private Array toArray(String typeName, Object... elements) {
Session session = em.unwrap(Session.class); // ATTENTION! This is Hibernate-specific!
final AtomicReference<Array> aRef = new AtomicReference<>();
session.doWork((c) -> {
aRef.set(c.createArrayOf(typeName, elements));
});
return aRef.get();
}

Error in SQLite db creation and Inserting data

When trying to create a database with a single table I encountered the following error. Not able to point the issue causing the error. Although have created the table column, still responding with no such column
Logcat data:
03-16 12:08:35.954 1249-1249/com.example.bharathduraiswamy.comboedittext E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo
{com.example.bharathduraiswamy.comboedittext/com.example.bharathduraiswamy.comboedittext.AddSupplier}: android.database.sqlite.SQLiteException: no such
column: _id (code 1): , while compiling: SELECT _id, supplier_name, supplier_contact_number, supplier_address FROM SUPPLIER
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2313)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2365)
at android.app.ActivityThread.access$600(ActivityThread.java:156)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5336)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.sqlite.SQLiteException: no such column: _id (code 1): , while compiling: SELECT _id, supplier_name, supplier_contact_number,
supplier_address FROM SUPPLIER
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:886)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:497)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1314)
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1161)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1032)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1200)
at com.example.bharathduraiswamy.comboedittext.VivzDatabaseAdapter.getAllRows(VivzDatabaseAdapter.java:78)
at com.example.bharathduraiswamy.comboedittext.AddSupplier.populateListView(AddSupplier.java:271)
at com.example.bharathduraiswamy.comboedittext.AddSupplier.onCreate(AddSupplier.java:71)
at android.app.Activity.performCreate(Activity.java:5122)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2277)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2365)
            at android.app.ActivityThread.access$600(ActivityThread.java:156)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:153)
            at android.app.ActivityThread.main(ActivityThread.java:5336)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
            at dalvik.system.NativeStart.main(Native Method)
MainActivity.java data:
DBAdapter myDb;
AutoCompleteTextView customerName;
EditText customerNumber, customerAddress;
customerName = (AutoCompleteTextView) findViewById(R.id.addCustomerName);
customerNumber = (EditText) findViewById(R.id.addCustomerNumber);
customerAddress = (EditText) findViewById(R.id.addCustomerAddress);
openDB();
private void openDB() {
myDb = new DBAdapter(this);
myDb.open();
}
public void addCustomer(MenuItem item) {
if (!TextUtils.isEmpty(customerName.getText().toString()) &&
!TextUtils.isEmpty(customerNumber.getText().toString())) {
myDb.insertCustomer(
customerName.getText().toString(),
customerNumber.getText().toString(),
customerAddress.getText().toString());}
}
DbHelper data: (Edited)
package com.example.bharathduraiswamy.comboedittext;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBAdapter {
private static final String TAG = "DBAdapter"; //used for logging database version changes
/////////////////
//START : CUSTOMER DATA
/////////////////
// Field Names:
public static final String CUSTOMER_ROWID = "customer_id";
public static final String CUSTOMER_NAME = "customer_name";
public static final String CUSTOMER_CONTACT_NUMBER = "customer_contact_number";
public static final String CUSTOMER_CONTACT_ADDRESS = "customer_contact_address";
public static final String[] CUSTOMER_KEYS = new String[] {CUSTOMER_ROWID, CUSTOMER_NAME, CUSTOMER_CONTACT_NUMBER, CUSTOMER_CONTACT_ADDRESS};
// Column Numbers for each Field Name:
public static final int COL_CUSTOMER_ROWID = 0;
public static final int COL_CUSTOMER_NAME = 1;
public static final int COL_CUSTOMER_CONTACT_NUMBER = 2;
public static final int COL_CUSTOMER_CONTACT_ADDRESS = 3;
// DataBase info:
public static final String DATABASE_NAME = "dbLeder";
public static final String CUSTOMER_TABLE = "CUSTOMERLIST";
public static final int DATABASE_VERSION = 3; // The version number must be incremented each time a change to DB structure occurs.
//SQL statement to create database
private static final String DATABASE_CREATE_SQL =
"CREATE TABLE " + CUSTOMER_TABLE
+ " ("
+ CUSTOMER_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ CUSTOMER_NAME + " VARCHAR(255), "
+ CUSTOMER_CONTACT_NUMBER + " VARCHAR(255), "
+ CUSTOMER_CONTACT_ADDRESS + " VARCHAR(255));";
public final Context context;
public DatabaseHelper myDBHelper;
public SQLiteDatabase db;
/////////////////
//END : CUSTOMER DATA
/////////////////
public DBAdapter(Context ctx) {
this.context = ctx;
myDBHelper = new DatabaseHelper(context);
}
// Open the database connection.
public DBAdapter open() {
db = myDBHelper.getWritableDatabase();
return this;
}
// Close the database connection.
public void close() {
myDBHelper.close();
}
//onClick Method for Check - addCustomer
public long insertCustomer(String custName, String custContactNumber, String custContactAddress) {
ContentValues initialValues = new ContentValues();
initialValues.put(CUSTOMER_NAME, custName);
initialValues.put(CUSTOMER_CONTACT_NUMBER, custContactNumber);
initialValues.put(CUSTOMER_CONTACT_ADDRESS, custContactAddress);
// Insert the data into the database.
return db.insert(CUSTOMER_TABLE, null, initialValues);
}
// Delete a row from the database, by rowId (primary key)
public boolean deleteRow(long rowId) {
String where = CUSTOMER_ROWID + "=" + rowId;
return db.delete(CUSTOMER_TABLE, where, null) != 0;
}
public void deleteAll() {
Cursor c = getAllRows();
long rowId = c.getColumnIndexOrThrow(CUSTOMER_ROWID);
if (c.moveToFirst()) {
do {
deleteRow(c.getLong((int) rowId));
} while (c.moveToNext());
}
c.close();
}
// Return all data in the database.
public Cursor getAllRows() {
String where = null;
Cursor c = db.query(true, CUSTOMER_TABLE, CUSTOMER_KEYS, where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Get a specific row (by rowId)
public Cursor getRow(long rowId) {
String where = CUSTOMER_ROWID + "=" + rowId;
Cursor c = db.query(true, CUSTOMER_TABLE, CUSTOMER_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Change an existing row to be equal to new data.
public boolean updateRow(long rowId, String custName, String custContactNumber, String custContactAddress) {
String where = CUSTOMER_ROWID + "=" + rowId;
ContentValues newValues = new ContentValues();
newValues.put(CUSTOMER_NAME, custName);
newValues.put(CUSTOMER_CONTACT_NUMBER, custContactNumber);
newValues.put(CUSTOMER_CONTACT_ADDRESS, custContactAddress);
// Insert it into the database.
return db.update(CUSTOMER_TABLE, newValues, where, null) != 0;
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase _db) {
_db.execSQL(DATABASE_CREATE_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading application's database from version " + oldVersion
+ " to " + newVersion + ", which will destroy all old data!");
// Destroy old database:
_db.execSQL("DROP TABLE IF EXISTS" + CUSTOMER_TABLE);
onCreate(_db); // Recreates the onCreate()
}
}
}
Nothing strikes me as wrong in your code.
Did you increment the DATABASE_VERSION field to make sure your onUpgradee() method is called ?
If you did that already, maybe try to uninstall the app from your device. That will erase the existing database. If this work, that would probably mean that your onUpgrade() method does not work.
Good luck.
EDIT : Check your onUpgrade() method. You don't have a space after "EXISTS". You need one otherwise the query won't work.
The new Logcat shows that you are having a different error. I think what it tells you is that you should have at least one column called "_id" in your table.
This is sort of a must have when working in SQLite on Android because some of the convenience methods look for this column name.
If you search StackOverflow, you will find some answers tell you that you can Alias this row and don't have to change the design of your table, but I'd say go ahead and change your design.

play.exceptions.JavaExecutionException: Cannot get the object #Id for an object in WAS8

this is my code in controller and here i save my object
public static void newNdsf(Integer cprNumber,String fstCode,Date startDate,
Double amount, Date endDate, String isActive, String userCreated, String msg){
Beneficiary beneficiary = new Beneficiary();
beneficiary.beneficiaryPK = (new BeneficiaryPK(cprNumber, fstCode, startDate));
beneficiary.dateCreated = (new Date());
beneficiary.userCreated = userCreated;
beneficiary.amount = new BigDecimal(amount);
beneficiary.dateLastUpdate = (new Date());
beneficiary.userLastUpdate = userCreated;
beneficiary.endDate = endDate;
if(isActive.charAt(0) == Constants.IN_ACTIVE || isActive.charAt(0) == Constants.ACTIVE)
beneficiary.isActive = isActive.charAt(0);
else
System.out.println("in valid is Active value entered in service");
beneficiary.save();
int count = new CRSServices().savePersonDetails(cprNumber);
System.out.println("Person Data saved from Service : " + count);
msg = msg.concat("Entered Successfully");
renderText(msg);
}
in Models iam overriding the save method to catch some exception
#Override
public <T extends JPABase> T save()
{
long startTs = System.currentTimeMillis();
if (endDate != null && beneficiaryPK != null && beneficiaryPK.startDate != null && endDate.before(beneficiaryPK.startDate)){
throw new RuntimeException("startdate_after_end_date");
}
Object result = super.save();
logger.debug("Save Took: {} " , System.currentTimeMillis() - startTs);
return (T) result;
}
this code is working on WAS6
but when i use it in WAS8
it gives me this exception
#6d2l11n03
Internal Server Error (500)
Execution exception (In /app/models/Beneficiary.java around line 221)
ValidationException occured : error during validation of
play.exceptions.JavaExecutionException: error during validation of <unknown>
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:290)
at play.server.ServletWrapper$ServletInvocation.execute(ServletWrapper.java:476)
at play.Invoker$Invocation.run(Invoker.java:187)
at play.server.ServletWrapper$ServletInvocation.run(ServletWrapper.java:467)
at play.Invoker.invokeInThread(Invoker.java:61)
at play.server.ServletWrapper.service(ServletWrapper.java:117)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1214)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:774)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:456)
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1027)
at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:87)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:895)
at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1662)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:195)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:452)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:511)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:305)
at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1659)
Caused by: javax.validation.ValidationException: error during validation of <unknown>
at org.apache.bval.jsr303.ClassValidator.unrecoverableValidationError(ClassValidator.java:633)
at org.apache.bval.jsr303.ClassValidator.validate(ClassValidator.java:161)
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:113)
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:71)
at org.hibernate.action.EntityInsertAction.preInsert(EntityInsertAction.java:177)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:72)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:267)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:259)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:178)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:345)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:791)
at play.db.jpa.JPABase._save(JPABase.java:47)
at play.db.jpa.GenericModel.save(GenericModel.java:187)
at models.Beneficiary.save(Beneficiary.java:221)
at controllers.NdsfService.newNdsf(NdsfService.java:189)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:413)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:408)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:182)
... 27 more
Caused by: play.exceptions.UnexpectedException: Unexpected Error
at play.db.jpa.JPAPlugin$JPAModelLoader.keyValue(JPAPlugin.java:491)
at play.db.jpa.JPABase._key(JPABase.java:96)
at play.db.jpa.JPABase.hashCode(JPABase.java:226)
at org.apache.bval.jsr303.GraphBeanIdentity.hashCode(GraphBeanIdentity.java:123)
at java.util.HashMap.getEntry(HashMap.java:510)
at java.util.HashMap.get(HashMap.java:498)
at org.apache.bval.jsr303.GroupValidationContextImpl.collectValidated(GroupValidationContextImpl.java:133)
at org.apache.bval.jsr303.ClassValidator.validateBeanNet(ClassValidator.java:421)
at org.apache.bval.jsr303.ClassValidator.validate(ClassValidator.java:141)
... 45 more
Caused by: play.exceptions.UnexpectedException: Cannot get the object #Id for an object of type class models.Beneficiary
at play.db.jpa.JPAPlugin$JPAModelLoader.keyField(JPAPlugin.java:511)
at play.db.jpa.JPAPlugin$JPAModelLoader.keyValue(JPAPlugin.java:489)
... 53 more
if anyone can help!!!
Figured this out
in my object
before i have only
#EmbeddedId
public BeneficiaryPK beneficiaryPK;
and this works in WAS 6 but not in WAS 8
so now i added #Id and both annotations are working in WAS 8
#EmbeddedId
#Id
public BeneficiaryPK beneficiaryPK;
hope this is helpfull

RuntimeException Retrieving data from SQLite Database

I've imported a Database into SQLite (testing.sqllite) which was created in SQLliteManager in Firefox Plugin. I placed it in data/data//databases/.
When I try to retrieve data from the DB, I'm getting runtime exception. Here is my code...
DataBaseHelper.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseHelper extends SQLiteOpenHelper{
public static final String KEY_ROWID = "keyno";
public static final String DESTINATION = "Destination";
public static final String CITY = "City";
public static final String COUNTRY = "Country";
public static final String IMG1 = "Img1";
//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/com.world.destinations/databases/";
private static String DB_NAME = "testing";
private static String DATABASE_TABLE = "Master";
private DataBaseHelper ourHelper;
private SQLiteDatabase myDataBase;
private final Context myContext;
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access to the application assets and resources.
* #param context
*/
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
/**
* Creates a empty database on the system and rewrites it with your own database.
* */
public void createDataBase() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist){
//do nothing - database already exist
}else{
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exist to avoid re-copying the file each time you open the application.
* #return true if it exists, false if it doesn't
*/
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//database does't exist yet.
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
public DataBaseHelper open() throws SQLiteException {
ourHelper = new DataBaseHelper(myContext);
myDataBase = ourHelper.getWritableDatabase();
return this;
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transfering bytestream.
* */
private void copyDataBase() throws IOException{
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException{
//Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
#Override
public synchronized void close() {
if(myDataBase != null)
myDataBase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public String getData() {
// TODO Auto-generated method stub
String[] columns = new String[]{KEY_ROWID, DESTINATION, CITY, COUNTRY, PERIOD, TYPE, CURRENCY, ELEVATION, BRIEF, HIGHLIGHTS, IMG_MAIN};
Cursor c = myDataBase.query(DATABASE_TABLE, columns, null, null, null, null, null);
String result = "";
int iRow = c.getColumnIndex(KEY_ROWID);
int iName = c.getColumnIndex(DESTINATION);
int iCity = c.getColumnIndex(CITY);
int iCountry = c.getColumnIndex(COUNTRY);
int iImgmain = c.getColumnIndex(IMG1);
for(c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
result = result + c.getString(iRow) + " " + c.getString(iName) + " " + c.getString(iCity) + " " + c.getString(iCountry) + " " + c.getString(iImgmain) + "\n";
}
return result;
}
}
and here is my ShowData.java
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class ShowData extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.setContentView(R.layout.showdata);
TextView tv = (TextView)findViewById(R.id.textView1);
DataBaseHelper info = new DataBaseHelper(this);
info.open();
String data = info.getData();
info.close();
tv.setText(data);
}
}
and here is the exception...
11-14 20:19:29.099: E/AndroidRuntime(933): FATAL EXCEPTION: main
11-14 20:19:29.099: E/AndroidRuntime(933): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.world.destinations/com.world.destinations.ShowData}: android.database.sqlite.SQLiteException: no such table: Master (code 1): , while compiling: SELECT keyno, Destination, City, Country, Img_Main FROM Master
11-14 20:19:29.099: E/AndroidRuntime(933): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
11-14 20:19:29.099: E/AndroidRuntime(933): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
11-14 20:19:29.099: E/AndroidRuntime(933): at android.app.ActivityThread.access$600(ActivityThread.java:130)
11-14 20:19:29.099: E/AndroidRuntime(933): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
11-14 20:19:29.099: E/AndroidRuntime(933): at android.os.Handler.dispatchMessage(Handler.java:99)
11-14 20:19:29.099: E/AndroidRuntime(933): at android.os.Looper.loop(Looper.java:137)
11-14 20:19:29.099: E/AndroidRuntime(933): at android.app.ActivityThread.main(ActivityThread.java:4745)
11-14 20:19:29.099: E/AndroidRuntime(933): at java.lang.reflect.Method.invokeNative(Native Method)
11-14 20:19:29.099: E/AndroidRuntime(933): at java.lang.reflect.Method.invoke(Method.java:511)
11-14 20:19:29.099: E/AndroidRuntime(933): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
Can someone please help me where I'm going wrong. Much appreciated. Thanks.
You are trying to query an empty database.
From stack trace:
SQLiteException: no such table: Master (code 1): , while compiling: SELECT keyno, Destination, City, Country, Img_Main FROM Master
My guess is that you have placed the file in the wrong directory on the sd card and SQLite created a empty database somewhere else.