hibernate query giving an inccorect result list - java

this is the method Dao layer List,
public List<PortfolioMemberView> getPortfolioMemberViewByPid(Integer pid){
//check the portfolioId value in console
System.out.print(pid);
try {
Session session = sessionFactory.getCurrentSession();
String sql = "from PortfolioMemberView pv where pv.portfolioId = ?0";
Query query = session.createQuery(sql).setParameter(0, pid);
List<PortfolioMemberView> pmvl = query.list();
//check the result list by assetCode in console
for(PortfolioMemberView pv: pmvl){
System.out.print(pv.getAssetCode());
}
return pmvl;
}catch(Exception e){
logger.info("操作失败:" + e.getMessage() + ", " +e.getCause());
throw new RuntimeException();
}
I have a view(That I create) PortfolioMemberView in my database
and it has the following data
inmage
when I involke the method, the console print following result.
2
Hibernate: select portfoliom0_.portfolioId as portfoli1_8_,
portfoliom0_.assetId as assetId2_8_, portfoliom0_.accountType as accountT3_8_, portfoliom0_.assetCode as assetCod4_8_, portfoliom0_.assetLabel as assetLab5_8_, portfoliom0_.value_ as value_6_8_, portfoliom0_.annualReturn as annualRe7_8_, portfoliom0_.returnRate as returnRa8_8_ from PortfolioMemberView portfoliom0_ where portfoliom0_.portfolioId=?
CMPROP0121CMPROP0121CMPROP0121CMPROP0121CMPROP0121
The expected result should be CMPROP0121kckbGYck, because when portfolioId = 2, the assetCode of three object in the resulting list shoud be CMPROP0121,kckb,GYck.
I also copy the query hibenate generated and run it at mysql database, and the result is correct.
Hibernate: select portfoliom0_.portfolioId as portfoli1_8_,
portfoliom0_.assetId as assetId2_8_, portfoliom0_.accountType as accountT3_8_, portfoliom0_.assetCode as assetCod4_8_, portfoliom0_.assetLabel as assetLab5_8_, portfoliom0_.value_ as value_6_8_, portfoliom0_.annualReturn as annualRe7_8_, portfoliom0_.returnRate as returnRa8_8_ from PortfolioMemberView portfoliom0_ where portfoliom0_.portfolioId=?
not sure what's wrong, pls help!!!

I mapped portfolioId as primary Id, and primary Id cannot be duplicated. but obviously the primary key portfolioId is duplicated. I make aother primary key portfolioMemberId, and the problem solved

Related

java DAO update query failure

I am trying to write DAO method to update value in postgres table "accounts" with just two columns:
"id" string
"balance" int
public Account setAccountBalance(String id, Integer balance) {
Handle h = dbi.open();
try{
return h.createQuery("UPDATE accounts SET balance=" + balance.intValue() +
" WHERE id=\'" + id +"\';")
.mapTo(Account.class)
.first();
} finally {
h.close();
}
}
But on execute I see the following exception:
org.skife.jdbi.v2.exceptions.NoResultsException: Query did not have a result set, perhaps you meant update? [statement:"UPDATE accounts SET balance=20 WHERE id='1';", located:"UPDATE accounts SET balance=20 WHERE id='1';", rewritten:"UPDATE accounts SET balance=20 WHERE id='1';", arguments:{ positional:{}, named:{id:'1'}, finder:[]}]
Any idea if the problem is in query syntax, or use of DAO?
Looks like you are using JDBI. According to the documentation, SQL UPDATEs can be performed through Handle.execute(), as follows:
h.execute("UPDATE accounts SET balance=? WHERE id=?", balance.intValue(), id);
But the execute method doesn't return a result set and therefore cannot be used for creating an Account object. You would need to issue a separate query for doing that, maybe something like
return h.createQuery("SELECT id, balance FROM accounts WHERE id = :id")
.bind("id", id)
.mapTo(Account.class)
.first();

Database Query working on DBMS directly but not in Java

I am trying to do things before processing Ingest to KIT DataManager (Code on GitHub, it runs on tomcat7) with a "Staging Processor" …
adding a custom Staging Processor
package edu.kit.dama.mdm.content.mets;
…
public class TryQuota extends AbstractStagingProcessor {
…
#Override
public final void performPreTransferProcessing(TransferTaskContainer pContainer) throws StagingProcessorException {
…
trying to get user data
… this works
UserData userResult = null;
try {
userResult = mdm.findSingleResult(
"Select u FROM UserData u WHERE u.email=?1",
new Object[]{"dama#kit.edu"},
standard email of admin user with userid 1
UserData.class
);
} catch (UnauthorizedAccessAttemptException e2) {
System.out.println("exception on extracting userid");
e2.printStackTrace();
}
try {
System.out.println("KIT DM ID: " + userResult.getUserId());
}catch(Exception e4) {
System.out.println("exception on output for userid");
e4.printStackTrace();
}
trying to get quota from UserQuota
and on the other hand, the corresponding implementation doesn't do the job here (that I want to get working)
Number UserQuota = null;
try {
UserQuota = mdm.findSingleResult(
//SQL would be: "SELECT quota FROM userquota WHERE uid=?;"
//JPQL is …
"Select q.quota FROM UserQuota q WHERE q.uid=?1",
new Object[]{1},
Number.class
);
} catch (UnauthorizedAccessAttemptException e2) {
System.out.println("exception on userquota");
e2.printStackTrace();
}
System.out.println("quota is: " + UserQuota );
UserQuota is still null here
DB is PostgreSQL, Table is:
CREATE SEQUENCE userquota_seq
START WITH 1
INCREMENT BY 1
NO MAXVALUE
NO MINVALUE;
CREATE TABLE userquota
(
id INTEGER NOT NULL DEFAULT nextval('userquota_seq'),
uid INTEGER NOT NULL DEFAULT 0,
quota DECIMAL NOT NULL DEFAULT 0,
CONSTRAINT uid_key UNIQUE (uid),
CONSTRAINT fk_uid FOREIGN KEY (uid) REFERENCES users(id)
);
This quota I want to get from db in the processor
INSERT INTO userquota (id, uid,quota) VALUES ( 0, 1, 1048576 );
So mainly I want to get the entry for the ingesting user (here 1) from db: 1048576 as a Long.
Any hints welcome on how to proceed on these things.
As stated in above comment, the following statement is invalid SQL syntax:
SELECT u FROM UserData u WHERE u.email=?1
Instead, according to above comment the correct syntax would be:
SELECT u.* FROM UserData u WHERE u.email='dama#kit.edu'
I found a solution by creating a class UserQuota1 so JPQL can work here.
As I did not find a way around, I first copied class UserData, dropped everything I had no use of and changed the members according to my database table userquota. This also means when extending the db table this class needs to be altered as well.
A very important part I had no clue about is that this new class also needs to be registered for tomcat7 in persistence.xml, also here copied over from the entry for UserData.

null pointer exception on retrieving records from the database hibernate hql

I have a record that exists in my database which I crossed several times and the record is correct. I have also ensured that toString is overriden in my class to get a meaningful representation of the data I am retrieving.
This is the hql I am using to fetch records from the database
public List <Admin> getByAdminRole(int id) {
Query query = _sessionFactory.getCurrentSession()
.createQuery("select a.id from Admin a WHERE a.id = :id");
query.setParameter("role", id);
return query.list();
}
In my controller class I am calling the hql method this way
SupportDao _supportDao = new SupportDao();
List <Admin> add = _supportDao.getByAdminRole(1); //this line of code throws null pointer exception
System.out.println(">>>>>>>>>>> the value of add>>>>>>> " + add);
After research on solving nullpointer exception, I have ensured that toString is overriden in my model class Admin.java
#Override
public String toString(){
return this.id + this.name + this.getEmail() + this.getPassword() + this.role;
}
Please what could be wrong with my code?
change
query.setParameter("role", id);
to
query.setParameter("id", id);
if want to return List<Admin> also modify ,
.createQuery("select a.id from Admin a WHERE a.id = :id");
to
.createQuery("from Admin a WHERE a.id = :id");
it will return Admin list with only one Admin if single id is present
if you want single Admin then
return query.uniqueResult(); and change return type as per requirement
Since you're instantiating SupportDAO yourself are you absolutely, 101% sure that _sessionFactory in SupportDAO is also instantiated?
Looking to your above code where you passing the "id" as parameter but in setParameter method your are passing with "role" .
I guess you need to pass it with "id" only.

select scope_identity() using createSQLQuery in Hibernate

I am forced to use createSQLQuery to insert values into tables with an Identity column (the first column and the primary key) using hibernate. Using hibernate classes are not an option since the tables are created on the fly for each customer that is added to the system. I have run the query and it successfully inserts into the table. I then execute a "select scope_identity()" and it always returns null. "select ##Identity" works but that is not guaranteed to be the correct one. I have also tried to append "select scope_identity()" to the insert query. Then I tried query.list() and query.uniqueResult() both of which throw the hibernate exception of "No Results ..."
Session session = DatabaseEngine.getSessionFactory().openSession();
String queryString = "insert into table1 (dataid) values (1)"
SQLQuery query = session.createSQLQuery(insertQueryString);
query.executeUpdate();
query = session.createSQLQuery("select scope_identity()");
BigDecimal entryID = (BigDecimal)query.uniqueResult();
The simple example table is defined as follows:
"CREATE TABLE table1 (EntryID int identity(1,1) NOT NULL," +
"DataID int default 0 NOT NULL, " +
"PRIMARY KEY (EntryID))";
Is there a way I am missing to use scope_identity() with createSQLQuery?
Actually the SQLServerDialect class used by Hibernate uses the same "scope_identity()" too.
The reason why it's not working is because you need to execute those in the same statement or stored procedure.
If you execute the scope_identity() call in a separate statement, SQL Server will not be able to give you last inserted identity value.
You cannot do it with the SQLQuery, even Hibernate uses JDBC to accomplish this task. I wrote a test on GitHub to emulate this and it works like this:
Session session = entityManager.unwrap(Session.class);
final AtomicLong resultHolder = new AtomicLong();
session.doWork(connection -> {
try(PreparedStatement statement = connection.prepareStatement("INSERT INTO post VALUES (?) select scope_identity() ") ) {
statement.setString(1, "abc");
if ( !statement.execute() ) {
while ( !statement.getMoreResults() && statement.getUpdateCount() != -1 ) {
// do nothing until we hit the resultset
}
}
try (ResultSet rs = statement.getResultSet()) {
if(rs.next()) {
resultHolder.set(rs.getLong(1));
}
}
}
});
assertNotNull(resultHolder.get());
The code uses Java 8 lambdas instead of anonymous classes, but you can easily port it to Java 1.7 too.

DAO method retrieve single entry

How can I write DAO method which will return as a result only first entry from the database. For instance lets say I'm looking at Users table and I want to retrieve only the first entry, I'd declare method like:
public User getFirstUser(){
//method logic
}
EDIT:
User has primary key id if that matters at all.
I apologize if this question is too simple/stupid/whatever I'm beginner with Java so I'm trying new things. thank you
My attempt :
public User getFirstUser(){
try {
final String getQuery = "SELECT * FROM Users WHERE Id = (SELECT MIN(Id) FROM Users)";
final Query query = getSession().createQuery(getQuery);
final int rowCount = query.executeUpdate(); // check that the rowCount is 1
log.debug("get successful");
// return what??
} catch (RuntimeException re) {
log.error("get not successful", re);
throw re;
}
}
You can
use:
Query query = session.createQuery("from User");
query.setMaxResults(1);
User result = (User) query.uniqueResult();
use User user = session.get(User.class, id); if you know the ID upfront.
Get all users ordered by id and limit the results to 1 (but don't use LIMIT, use setMaxResults() to remain portable):
Query q = session.createQuery("from User u order by u.id");
q.setMaxResults(1);
User u = (User) q.uniqueResult();
SELECT * FROM Users WHERE Id = (SELECT MIN(Id) FROM Users)
:)
Don't remember exactly but i think there is a method getSingleResult in JPA and also in Hibernate so...
But this method perhaps throw exception when multiple results are returned... can't remember...
Actually there is also getResultList returning a List of entities, and you could do list.get(0) no?
Or create a query with LIMIT 1?
In MS SQL Server we do it like,
First user, min ID,
SELECT TOP 1 * FROM Users ORDER BY Id
Latest user, max ID,
SELECT TOP 1 * FROM Users ORDER BY Id DESC
thanks.

Categories