Retriving a single column result using Hibernate HQL - java

using Hibernate I have a HQL query that looks like this:
String myQuery = " SELECT code,((max(mid)/min(mid))-1)*100
FROM ExchangeRate
WHERE effectivedate >= '2017-09-01'and effectivedate <= '2017-10-22'
group by name, code order by 2 desc "
With this query i want to recive the code of ExchangeRate with biggest diffrence in given time (from 2017-09-01 to 2017-10-22). Since i only want one rate I put a limit on the query and download the result using uniqueResult() method.
Session session = CRUDSessionFactory.getSessionFactory().openSession();
Query q = session.createQuery(myQuery);
q.setMaxResults(1);
Object code = q.uniqueResult();
The problem is to receive the first column value 'code' as a string which is a varchar in my Postgress database but i can't seem to find a decent solution to do it, since there's also the second column with BigDecimal as a data type. While using debug and variables window the variable code get's the proper values which looks like this:
Variable window in debugg mode
Reffering to the object code like an array by using:
String myCode = code[0];
This obviously does not work since the variable is not an array.
EDIT:
The thing that worked for me was casting the Object type from uniqueResult() to an Object array and then using first value of that array:
Object[] code = (Object[]) q.uniqueResult();
String myCode = (String) code[0];

Related

UPDATE AND REPLACE part or a string/record with parameter

ALL>
I have here a named query to update and replace records.
#NamedQuery(name = POST.UPDATE_POST_MESSAGE, query = "UPDATE Post p SET p.message = REPLACE(p.message, :value, 'ANONYMOUS')"
I wanted the "old string" to be parameterized but it shows an error of
Caused by: java.lang.IllegalArgumentException: You have attempted to set a parameter value using a name of value that does not exist in the query string UPDATE Post p SET p.message = REPLACE(p.message, :value, 'ANONYMOUS').
here's the code in my dao layer:
private static final String VALUE = "value";
public void updateMessage(String value) {
EntityManager entityManager = createEntityManager();
entityManager.createNamedQuery(POST.UPDATE_POST_MESSAGE)
.setParameter(VALUE, value)
.executeUpdate();
}
I am not sure if we can use a parameter inside the replace function, been searching everywhere and i cant find an answer.
If not possible, can someone help/recommend a way to replace records using a parameter.
Here you assigned parameter value to VALUE variable but using value((lower case ).

Can I return custom object from UPDATE query instead of integer?

Executing UPDATE query it always returns INT number of rows affected.
Maybe there is some way to return for example list of all objects which where updated or first one updated?
I have #Entity SecurityPolicy and want this object back after update.
So here is my code:
#Modifying
#Query(value = "UPDATE security_policy s set max_fail_sign_in =:maxFailSignIn," +
" min_password_length =:minPasswordLength," +
" capital_in_password =:capitalInPassword," +
" digit_in_password =:digitInPassword," +
nativeQuery = true)
SecurityPolicy updateSecurityPolicy(#Param("maxFailSignIn") Integer maxFailSignIn,
#Param("minPasswordLength") Integer minPasswordLength,
#Param("capitalInPassword") Boolean capitalInPassword,
#Param("digitInPassword") Boolean digitInPassword);
When using #Modifying it tells me that result should be Int, and without it - could not extract ResultSet.
I know with spring data you can easily save or update some entity and get it as a result, so I want achieve something similar.
No you cannot as the integer response is not generated by framework but by RDBMS itself (SQL spec). That integer says how many rows were modified by query.
Since you don't want to use JPA to do this, you will have to SELECT that row after update, like you would do with plain SQL.

Unable to delete object using datastore, query (with `id`) on dao and ds return zero result

I'm trying to delete an object from datastore but it's not deleting it. Code is given below:
MoIADocument moIADoc = new MoIADocument();
// update fields in moIADoc object
ds.save(moIADoc);
printDBDocs();
// create a query to retrieve objects
QueryResults<MoIADocument> foundResults = dao.find(query);
List<MoIADocument> list = foundResults.asList();
for (MoIADocument obj : list) {
ds.delete(obj);
MoDBIATopic topicBO = obj.getData().get(EnumChannelType.FACEBOOK).getData().get(GraphConstants.Topic_Default);
topicBO.setInfluence(topicBO.getInfluence() * 25);
ds.save(obj);
}
printDBDocs();
###########################
the result of first print (in JSON format) is:
###########################
obj in for loop is:
###########################
and after for loop the print statement gives two objects as:
Why is it not deleting old object by mongoConstants.ds.delete(obj);? And I have annotated id field ad #Id but still two objects are saved with same id. How is this possible? How can we force to overwrite an object if id is same?
#Id
#Indexed
private String id;
Note: id is the top level id as indicated in JSON.
And I tried using query as:
Query<MoIADocument> query1 = ds.createQuery(MoIADocument.class).disableValidation();
query1.field("id").equal(obj.getId());
ds.delete(query1);
This too not working as expected.
EDIT:
Problem looks like in query result. Using above query1, it returned zero results.
I tried multiple approaches but nothing worked as expected.. tried following ways:
Approach# 1:
Query<MoDBIADocument> query1 = dao.createQuery(MoDBIADocument.class).disableValidation();
query1.field("id").equal(moDoc.getId());
QueryResults<MoDBIADocument> foundResults1 = dao.find(query1);
printDBDocs(foundResults1);
Approach# 2: (using _id instead of id)
Query<MoDBIADocument> query1 = dao.createQuery(MoDBIADocument.class).disableValidation();
query1.field("_id").equal(moDoc.getId());
QueryResults<MoDBIADocument> foundResults1 = dao.find(query1);
printDBDocs(foundResults1);
Approach# 3:
using `ds` instead of `dao` in `Approach# 1` and `Approach# 2`
Approach# 4:
DBObject dbObj = new BasicDBObject("id", moDoc.getId());
DBCursor cursor = COLLECTION.find(dbObj);
None of above approaches worked.. I think problem is with using top level id field (somehow?)..
Using internal id (of FACEBOOK) worked as expected
query1.field("data.FACEBOOK.id").equal(str);
Problem was using a String id as #Id field. Actually it should be ObjectId id. WIth this change class become as below:
#Entity("Collection_IAGlobals")
public class MoDBIADocument {
#Id
#Indexed
private ObjectId id;
// some more fields
}
and updating as:
QueryResults<MoIADocument> foundResults = dao.find(query);
List<MoIADocument> list = foundResults.asList();
for (MoIADocument obj : list) {
//do modifications in obj
dao.save(obj);
}
this way there is no need to delete old object. It replaces old object with new one (since they are having same id).
Works fine using both ds and dao.
But now, new problem with setting id field. If I set using some string as:
moIADoc.setId(new ObjectId("123456"));
it is resulting into following error:
Exception in thread "main" java.lang.IllegalArgumentException: invalid ObjectId [123456]
at org.bson.types.ObjectId.<init>(ObjectId.java:128)
at org.bson.types.ObjectId.<init>(ObjectId.java:122)
It works fine any of other methods, like:
// don't set id field
//OR
//set using default constructor of ObjectId
moIADoc.setId(new ObjectId());
//OR use other constructors e.g.
moIADoc.setId(new ObjectId(new Date(), 123456));
So, the question is why ObjectId is not taking String argument?

Get return value (scalar), not result table, from stored procedure using Java and Hibernate

I'm having a hard time getting the return value (integer) from a stored procedure using Hibernate and Java.
My stored procedure is as follows:
create proc dbo.CheckEquipmentAuthorization
#ReplicaId int
as
declare #IDAuthType int
select #IDAuthType = AuthorizationType.IDAuthorizationType from AuthorizationType
inner join ReplicaAuthorization on ReplicaAuthorization.RefIDAuthorizationType = AuthorizationType.IDAuthorizationType
inner join Replica_ReplicaAuthorization on Replica_ReplicaAuthorization.RefIDAuthorization = ReplicaAuthorization.IDAuthorization
inner join Replica on Replica.IDReplica = Replica_ReplicaAuthorization.RefIDReplica
where Replica.IDReplica = #ReplicaId
and GETDATE() between ReplicaAuthorization.AuthBegin and ReplicaAuthorization.AuthEnd
declare #AuthIntValue int
set #AuthIntValue = 10
if (#IDAuthType is not null)
begin
select #AuthIntValue = AuthorizationType.IntValue from AuthorizationType
where AuthorizationType.IDAuthorizationType = #IDAuthType
end
print #AuthIntValue
return #AuthIntValue
I'm trying to get the return value using:
query = session.createSQLQuery(
"exec CheckEquipmentAuthorization(:replicaId)")
.setParameter("replicaId", replicaId);
But it seems I can only get a result table using this, and since no result table is generate from my procedure, nor do I want one to be, it fails.
Is there a way to get that returned value using that createSQLQuery() method?
I'm using Hibernate, Java and SQL Server. The stored procedure is working correctly (I have tested it with a sql client).
Thank you.
This seems to be a duplicate of this. Have you mapped a scalar return type of your stored procedure? And are you translating into that return type?
In the stored procedure, I replaced
return #AuthIntValue
with
select #AuthIntValue as RetVat
The way I call the stored procedure and transform the result into an object I created.
StoredProcResult o = (StoredProcResult)session.createSQLQuery("exec CheckEquipmentAuthorization :replicaId")
.addScalar("retVal", Hibernate.INTEGER)
.setParameter("replicaId", replicaId)
.setResultTransformer(Transformers.aliasToBean(StoredProcResult.class))
.setCacheMode(CacheMode.GET)
.uniqueResult();
int xpto = o.getRetVal();
The StoredProcResult object:
public class StoredProcResult {
public int retVal;
public int getRetVal() {
return retVal;
}
public void setRetVal(int retVal) {
this.retVal = retVal;
}
}
I know this is very old, but I just found myself faced with the same problem and found a simple solution when working with MS SQL Server. Modify your original query as follows:
query = session.createSQLQuery(
"declare #result int; exec #result = CheckEquipmentAuthorization(:replicaId); select #result")
.setParameter("replicaId", replicaId);
Now you get the return code as the query.uniqueResult() without the need to modify the original stored procedure. This can be handy when you aren't able (or don't want) to modify the oriignal stored procedure.

Java LinkedHashMap: what's the difference in these two?

EDIT: The entire code and database creation script can be found from http://gitorious.org/scheator . The database script is in Schema/.
I have the following Java code:
A LinkedHashMap defined in an abstract class as
LinkedHashMap<Object, Data> list;
A descendant class that initializes this list like this:
list = new LinkedHashMap<Integer, Data>();
I add items like this:
String id = rs.getString(FIELDS[0]);
String name = rs.getString(FIELDS[1]);
Data team = new Data(Integer.parseInt(id.trim()), name);
list.put(id, team);
Now when I do this:
System.err.println("delete() count: " + list.size());
System.err.println("delete() key value " + key);
Data obj;
obj = (Data)list.remove(key);
deletedList.put(key, obj);
System.err.println("delete() count: " + list.size());
Nothing is removed from the list, i.e. the first and last prints print the same size(). The key is also correct (I have verified there is an item by that id).
However, and this is my question, if I add the values like this:
Integer id = rs.getInt(FIELDS[0]);
String name = rs.getString(FIELDS[1]);
Data team = new Data(id, name);
list.put(id, team);
The code works! Shouldn't parseInt() produce a similar key to getInt()? Why does the second version work but the first doesn't? I spent a good hour debugging this until I found the reason and I still can't figure out the reason.
First example:
String id = rs.getString(FIELDS[0]);
Second example:
Integer id = rs.getInt(FIELDS[0]);
I can't say for sure since I can't see the rest of the code, but if the key variable is an Integer in this call:
obj = (Data)list.remove(key);
then the remove will only work if the object was put into the map using an Integer and that is why it is only working when the id is integer when you call the put method. The String "123" does not equal the integer 123.
Also I am assuming that you just missed a line in your first example but there was no call to list.put(id, team) but that could also be the source of your problems
There should be no difference, but there are a number of things that are not clear from your example:
deletedList does not refer to the list object
the records in your database that are being used are the same in both cases (perhaps in the first a different int is being used that is already in the Map)
Autoboxing may also be complicating the issue. Replace Integer id in the second sample with int id to pass the same arguments to your Data constructor.
Maybe you could post up the complete code such that we can reproduce the scenario accurately?
Update
You are using String values as keys in your original code. You then have an Object key in your remove(key) method, so I expect you are passing an Integer to the method at this point. A String will not match an Integer as a key, which explains why your remove was not working.
If you use generics to specify your HashMap (LinkedHashMap<Integer, Team> instead of <Object, Team>) this kind of error can't happen - the compiler will say something like
The method put(Integer, Object) in the type HashMap<Integer,Object> is not applicable for the arguments (String, String)
Yanamon is right. It's pretty clear when you look at the diff:
while (rs.next()) {
- String id = rs.getString(FIELDS[0]);
+ Integer id = rs.getInt(FIELDS[0]);
String name = rs.getString(FIELDS[1]);
- Data team = new Data(Integer.parseInt(id.trim()), name);
+ Data team = new Data(id, name);
list.put(id, team);
Note that in the original version, an int (auto-boxed to Integer) is being passed into the Data constructor. But id, which is being putted, is still a String.
My guess is that int the second case you cast it explicitly into an Integer
Integer id = rs.getInt(FIELDS[0]);
while on the first case it remains an int
Integer.parseInt(id.trim())
from the javadoc of parseInt
static int parseInt(String s)
Parses the string argument as a signed decimal integer.
If I were you I would inspect the contents of the LinkedHashMap using a debugger, before and after your put and before and after your remove. Step into the remove() method (the source code is part of the JDK) and see what it is doing. Odds are your code is not adding or removing the object correctly. It's hard to see here because the code sample is incomplete.
As for rs.getInt() and Integer.parseInt(), the first is database-vendor specific (I assume rs is a ResultSet), and thus they may not have the same behaviour. However, once the Integer key is created (you can verify this with your debugger) it should be equivalent for HashMap or LinkedHashMap purposes. But your code sample complicates things further; you are using rs.getString() and then Integer.parseInt(). While I would be surprised if this happened, it's possible that the database driver is formatting the id column into a string that confuses parseInt(). To me it's far more readable to just do rs.getInt().

Categories

Resources