How to execute native query and get feedback? - java

How to execute native query (create table) in java and also in return get information about is operation was successfull or not. Every method i did try always work the same. Query is working but i am getting errors about "how really bad that query was" but as i said it works.
try{
session.createNativeQuery("create table test (id number)").getResultList()
}
catch(Exception e){
// I am getting error "Could not extract result set metadata"
// Is there any way to execute getResultList() only if operation was select?
}
Summarizing, I need execute CRUD.
1. If "select" was executed i need resultList.
2. If "create" i don't want to execute getResultSet()
3. If "insert" was executed i need information about numbers of row affected.
etc... ... ...
And most important i always need information about eventual errors! If query had missing syntax or something i always need to get that information.
Guys can someone help me? I am fighting with this from several days...

A simple example using Native Query. You can determine the result of query from the affected rows value.
EntityTransaction entityTransaction;
EntityManager entityManager;
try
{
entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
// rowsUpdated - The number of "affected rows".
int rowsUpdated = entityManager.createNativeQuery("create table test (id nubmer)").executeUpdate();
entityTransaction.commit();
}
catch (HibernateException | IllegalStateException e)
{
// handle exceptions
if (entityTransaction != null && entityTransaction.isActive())
{
entityTransaction.rollback();
}
}

Related

Cassandra Java driver Performance : CQL Queries with IN Clause having high no of values

We are using Datastax Cassandra java driver (version 3.x). There is a logged batch Select statement with 'IN' clause, having a high number of values. Due to which we are facing a serious issue of low performance. Following is the format of query visible while debugging the Java application:
SELECT COL1, COL2, ... FROM XXXX WHERE PARTITIONKEY IN () AND CLUSTERINGKEY IN();
Can anyone please share how such SELECT with more than one IN clause shall be handled when there is high number of values available to pass inside it.
Does Session#executeAsync can solve this issue.
Thanks.
Don't use IN query for partition key (For a limited number of fixed data you can use if performance is not an issue). It imposes a lot of work to Coordinator node. You can use IN for clustering key but make sure your list is not too large as well.
executeAsync is the best approach here. I am adding a code snippet here.
PreparedStatement getInfo = session.prepare("SELECT COL1, COL2, ... FROM XXXX WHERE PARTITIONKEY = ?");
List<ResultSetFuture> futures = new ArrayList<>();
for (Object key : list) {
ResultSetFuture future = session.executeAsync(getInfo(key));
futures.add(future);
}
for (ResultSetFuture future : futures) {
try {
ResultSet rs = future.getUninterruptibly();
Row rw = rs.one();
if (rw != null) {
// set DB info into list or DTO
}
} catch (Exception e) {
// print log
LOGGER.error("", e);
}
}
It's a sample code. Please read this link for more details:
Cassandra Query Patterns: Not using the “in” query for multiple partitions.

SELECT FOR UPDATE in Hibernate and Oracle with multiple threads

I am having trouble getting SELECT FOR UPDATE to work in Hibernate and Oracle.
When I have two threads with one EntityManager per thread, the second thread seems to be able to read the same row as the first. I can see this by adding traces which show that the second thread reads the same row while the first is in between query.getSingleResult() and entityManager.getTransaction().commit() My expectation was that once a SELECT FOR UPDATE has been issued no one else should be able to read the same row until it is committed by the first thread. But this is not happening.
I can resort to an alternative implementation. What I want to achieve is only one process being able to read and update a row in an Oracle table so that it behaves like a queue given that the consumer processes can be in different machines.
Here is the minimum example of my code:
public MyMessage getNextMessage() {
String sql = "SELECT * FROM MESSAGE WHERE MESSAGE_STATUS = 'Pending' AND rownum=1 FOR UPDATE OF MESSAGE_STATUS";
entityManager.getTransaction().begin();
Query query = entityManager.createNativeQuery(sql, MyMessage.class);
query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
MyMessage msg = null;
try {
msg = (MyMessage) query.getSingleResult();
} catch (NoResultException nodatafound) {
// Ignore when no data found, just return null
}
if (msg != null) {
msg.setMessageStatus("In Progress");
entityManager.persist(msg);
}
entityManager.getTransaction().commit();
return msg;
}

hibernate createStoredProcedureQuery execute throws callablestatement.getmoreresults

First time I've used Java to call an SP so this is probably going to be a simple issues I'm overlooking.
I've got a couple of ways i'm trying to do this and am getting errors on both.
em is an EntityManager that's declared higher up the class, i've inspected it during debugging and the database connection is correct.
The first is using a StoredProcedureQuery which throws the error;
javax.persistence.PersistenceException: org.hibernate.SQLGrammarException: Error calling CallableStatement.getMoreResults
try {
StoredProcedureQuery query = em.createStoredProcedureQuery("usp_myProc");
query.registerStoredProcedureParameter(0, Integer.class, ParameterMode.IN);
query.setParameter(0, id);
query.execute();
}
catch (Exception ex) {
log.error(ex.toString());
}
My second attempt was to try and use a native query (which sounded right when I read the documentation)
try {
Query query1 = em.createNativeQuery("EXEC usp_myProc ?");
query1.setParameter(1, id);
Integer val = (Integer) query1.getSingleResult();
}
catch (Exception ex) {
log.error(ex.toString());
}
The Procedure has been stripped down to a simple 'Select 1' to make sure that's not a problem.
PROCEDURE [usp_myProc]
-- Add the parameters for the stored procedure here
#id INT
AS
BEGIN
SELECT 1
END
I've had a google around (which is where I get the Native Query code from) but couldn't get anything to return. Even just a stored procedure call that doesn't return a value would be a god result for me now.
Thanks for any help you can give.
StoredProcedureQuery indices start at 1
query.registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN);
query.setParameter(1, id);
I was facing the same problem and I have used the method provided by the EntityManager as follows:
entityManager.createNativeQuery(
"CALL storedProcedureName(:param1, :param2, :param3)")
.setParameter("param1", parameter1)
.setParameter("param2", parameter2)
.setParameter("param3", parameter3)
.getSingleResult();
In my case, I also have casted the getSingleResult() to String because I was expecting it as INOUT StoredProcedure's parameter and it worked as it should.
I hope it helps you as well.

JPA Select Query with composite primary key leads an exception

I have tried the below code for getting the single NotificationSubType Object. But finding exception like " org.apache.openjpa.persistence.ArgumentException: Encountered "from" at character 1, but expected: ["DELETE", "SELECT", "UPDATE"]."
Please help me on given problem.
Code is given below :
...
...
try {
Query query = this.em.createQuery("from NotificationSubType conc WHERE conc.id.alertTyC = ?1 and conc.id.alertSubTyC = ?2");
query.setParameter(1, "MPPRINT");
query.setParameter(2, "REIN");
NotificationSubType trackIdResLst = (NotificationSubType)query.getSingleResult();
if (null != trackIdResLst) {
System.out.println("TRUE");
} else{
System.out.println("FALSE");
}
} catch (Exception e) {
NotificationLogger.errorWithThrowable(e);
throw new NotificationServiceException(e.getMessage());
}
...
Why not read the exception? and read the JPA spec ?
JPQL statements have to start with SELECT, UPDATE or DELETE. Anything other than those is illegal (and yours starts with FROM for some reason). Put a SELECT and the candidate alias in front of it for more chance of success
Yes Hibernate bastardises the JPQL standard with HQL (which allows you to omit SELECT plus the alias) but you are using OpenJPA so you need to use JPA compliant queries, and besides it would be good practice even when using Hibernate to obey the standard!

Couchbase bucket insert behaves asynchronously java

I am using JsonDocument inserted = bucket.insert(doc); on couchbase-server-enterprise_4.1.0-ubuntu14.04_amd64.
What exactly happening is, I trigger this insert command and on success of this I trigger the Select command on same document. This Select command doesn't returns the update entries instead returns the old ones only. When I am using debugger before Select (wait for some seconds after insert and then call Select) it works totally fine. So i think insert behaves in async manner, not sure.
Other thing i have checked is upsert instead of insert, it is also not working. However when I do bucket.replace(doc) and then call Select, it returns the updated results. I have tried explicitly using the bucket.async().insert(doc) and the using toBlocking().single() on it, this also fails.
Is the issue with insert/upsert or I am doing something wrong.
Below is some of my code snippet ::
#Override
public T save(T entity, String username) {
String id = generateId(entity);
JsonObject data = JsonObject.fromJson(getContent(entity));
data.removeKey(ID);
data.put(TYPE, klass.getSimpleName());
data.put(CREATED_AT, new Date().getTime());
data.put(CREATED_BY, username);
data.put(MODIFIED_AT, new Date().getTime());
data.put(MODIFIED_BY, username);
data.put(ACTIVE, true);
T persistedEntity = getEntity(bucket.insert(JsonDocument.create(id, data)));
return persistedEntity;
}
#Override
public List findAll() {
Statement query = selectAll().where(typeExpression()).orderBy(Sort.desc(x(CREATED_AT)));
return getEntities(query);
}
protected AsPath selectAll() {
return Select.select("meta().id, *").from(i(bucket.name()));
}
N1QL queries can run with varying degrees of consistencies, unlike key/value operations which are always consistent (you "read-your-own-writes").
So there is a slight delay between an insertion and the indexer catching up to it. If you execute a N1QL query by default it will return what's the current state of the indexer, so if it is still indexing your document you won't see the update.
Try executing the query with a ScanConsistency of REQUEST_PLUS, where you do the bucket().query(...):
N1qlQuery n1qlQuery = N1qlQuery.simple(
selectStatement, //that's the Statement query in your example
N1qlParams
.build()
.consistency(ScanConsistency.REQUEST_PLUS)
);
This will instruct N1QL to wait for the indexer to finish indexing pending mutations.

Categories