hibernate update always null - java

iam new in hibernate, i have a entity class named student, it have 5 field, name, age, address, phone, and sex.
then i want to update name and age field.
student.setName("foo");
student.setAge("11");
getHibernateTemplate().update(student);
after i ran the code, the other field value become null, except the two field in the code above. i expecting my other field to stay as it is.
any suggest is deeply appreciated
btw sorry for my bad english

For updating value first of all you have to get the value by primary key and then update the object(Bean) then update method should be called.

What you have to do is retrieve your student from database before, to have a value for all the fields :
Student student = getHibernateTemplate().get(Student.class, id);
student.setName("foo");
student.setAge("11");
getHibernateTemplate().update(student);
Or, alternatively, you can do a manual update of your fields :
Session session;
boolean newSession=false;
try {
session=getHibernateTemplate().getSessionFactory().getCurrentSession();
} catch (final HibernateException e) {
session=getHibernateTemplate().getSessionFactory().openSession();
newSession=true;
}
session.createQuery(
"update Student student set " +
"student.Name = :studentName, " +
"student.Age = :studentAge " +
"where student.Id = :studentId")
.setString("studentName", "foo")
.setString("studentAge", "11")
.setString("studentId", id)
.executeUpdate();
if (newSession)
session.close();

Related

hibernate query giving an inccorect result list

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

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();

Hibernate Session return null even if table data exits

I am trying to retrieve a student object from a student table but am getting null.
public Student getStudentbyStudentName(String studentName) {
final String query = "from Student s where s.studentName = '" + studentName + "'";
return (Student)sessionFactory.getCurrentSession().createQuery(query).uniqueResult();
}
I have also tried the following to retrieve the student object of studentName. It works until my web page refreshes. When page refreshes, the following returns null. Please help.
public Student getStudentbyStudentName(String studentName) {
return (Student) sessionFactory.getCurrentSession()
.createCriteria(Student.class)
.add(Restrictions.eq("studentName", studentName))
.uniqueResult();
}
I guess that the name you pass in to that method is kind of Unicode, then you should place extra parameters in your MySQL connection url. E.g:
jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8
Second, but important. Your first code snippet is vulnerable for SQL Injection attack. Please use Criteria API (your 2nd snippet) or prepare your query:
from Student s where s.studentName = :name
in conjuntion with setParameter(...) method

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.

JPA: How to INSERT setting PK to MAX(PK) + 1

Scenario: I came across some code that is mixing JPA with JDBC within a transaction. The JDBC is doing an INSERT into a table with basically a blank row, setting the Primary Key to (SELECT MAX(PK) + 1) and the middleName to a temp timestamp. The method is then selecting from that same table for max(PK) + that temp timestamp to check if there was a collision. If successful, it then nulls out the middleName and updates. The method returns the newly created Primary Key.
Question:
Is there a better way to insert an entity into the database, setting the PK to max(pk) + 1 and gaining access to that newly created PK (preferably using JPA)?
Environment:
Using EclipseLink and need to support several versions of both Oracle and MS SqlServer databases.
Bonus Background: The reason I'm asking this question is because I run into a java.sql.BatchUpdateException when calling this method as part of a chain when running integration tests. The upper part of the chain uses JPA EntityManager to persist some objects.
Method in question
#Override
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public int generateStudentIdKey() {
final long now = System.currentTimeMillis();
int id = 0;
try {
try (final Connection connection = dataSource.getConnection()) {
if (connection.getAutoCommit()) {
connection.setAutoCommit(false);
}
try (final Statement statement = connection.createStatement()) {
// insert a row into the generator table
statement.executeUpdate(
"insert into student_demo (student_id, middle_name) " +
"select (max(student_id) + 1) as student_id, '" + now +
"' as middle_name from student_demo");
try (final ResultSet rs = statement.executeQuery(
"select max(student_id) as student_id " +
"from student_demo where middle_name = '" + now + "'")) {
if (rs.next()) {
id = rs.getInt(1);
}
}
if (id == 0) {
connection.rollback();
throw new RuntimeException("Key was not generated");
}
statement.execute("update student_demo set middle_name = null " +
"where student_id = " + id);
} catch (SQLException statementException) {
connection.rollback();
throw statementException;
}
}
} catch (SQLException exception) {
throw new RuntimeException(
"Exception thrown while trying to generate new student_ID", exception);
}
return id;
}
First off: it hurts to answer this. But I know, sometimes you have to deal with the devil :(
So technically, it's not JPA, but if you are using Hibernate as JPA-Provider, you can go with
#org.hibernate.annotations.GenericGenerator(
name = “incrementGenerator”,
strategy = “org.hibernate.id.IncrementGenerator”)
#GeneratedValue(generator="incrementGenerator")
private Long primaryKey;
The Hibernate solution is "thread-safe", but not "cluster-safe", i.e. if you run your application on several hosts, this may fail. You may catch the appropriate exception and try again.
If you stick with your solution: close the ResultSet, Statement and the Connection. Sorry, didn't catch the try-with-resources initially.
The JDBC code is pathological, makes no sense, and will not work in a multi user environment.
I would strongly recommend fixing the code to use a sequence object, or sequence table.
In JPA you can just use sequencing.
See,
http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Sequencing
If you really want to do your own sequencing, you can either assign the Id yourself, use PrePersist to assign your own id, or in EclipseLink implement your own Sequence subclass that does whatever you desire. You will need to register this Sequence object using a SessionCustomizer.
See,
http://wiki.eclipse.org/EclipseLink/Examples/JPA/CustomSequencing

Categories