Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: in some time ,entity can relative the other entity
PostPosted: Wed Mar 15, 2017 9:52 pm 
Newbie

Joined: Wed Mar 15, 2017 8:44 pm
Posts: 8
Hello,The hibernate developer and the hibernate User,I meet some trouble (I think it is a bug ) while I use the hibernate insert one data to database(message table)(mysql) ,in the meantime ,I select the ten latest data from message table . like this:

Code:
messageDao.save(message);//insert one data to database(I try to session.flush(); ,but not work)

List list =messageDao.getList(10);//get the ten latest data from database





the result:(User is a Object in the Message entity (relative to User ( configure the relative in the xml (many to one))))
list.get(0).getUser();//null (just inserted)
list.get(1).getUser();//not null
list.get(1).getUser();//not null
list.get(1).getUser();//not null
.....

And the result show that the latest(the ten data ,include the new one inserted just now),but the latest one is different to the others(night data), latest one can't pick out the relative data while the another can do(the night data)
it may be cache ? and how can i solve the problem?
please tell me is it a bug?



ps: my English is poor ,may be what i say is not clear;


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Thu Mar 16, 2017 2:01 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1385
You need to add the Message entity and DAO source code so it's easier to find out what you are doing.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Thu Mar 16, 2017 5:59 am 
Newbie

Joined: Wed Mar 15, 2017 8:44 pm
Posts: 8
vlad wrote:
You need to add the Message entity and DAO source code so it's easier to find out what you are doing.

Code:
messageDao

   public List<Message> getMessageByCondition(Message message,int pageNo,int  pageSize) {
      Session session= sessionFactory.getCurrentSession();
      String condition ="1=1 ";
      if(message.getMessageId()!=null){
         condition+=" And m.messageId = "+message.getMessageId();
      }
      if(message.getFromUserId()!=null){
         condition+=" And m.fromUserId = "+message.getFromUserId();
      }
      if(message.getToUserId()!=null){
         condition+=" And m.toUserId like "+message.getToUserId();
      }
      if(message.getIfRead()!=null){
         condition+=" And m.ifRead like "+message.getIfRead();
      }
      String hql = "FROM Message AS m WHERE "+condition+" order by m.messageId  desc";
      Query<?> query =session.createQuery(hql);
      return (List<Message>) query.setFirstResult((pageNo-1)*pageSize) 
        .setMaxResults(pageSize) 
        .list();
   }


   @Override
   public boolean save(Message message) {
      Session session= sessionFactory.getCurrentSession();
      try{
         session.save(message);
      }catch(Exception e){
         logger.error("增加message出错"+e);
         return false;
      }
      return true;
   }






Code:

public class Message {
   private Integer messageId;
   private String content;
   private Integer fromUserId;
   private User fromUser;
   private Integer toUserId;
   private User toUser;
   private Timestamp date;
   private Byte ifRead;
   private Byte type;
   public Integer getMessageId() {
      return messageId;
   }
   public void setMessageId(Integer messageId) {
      this.messageId = messageId;
   }
   public String getContent() {
      return content;
   }
   public void setContent(String content) {
      this.content = content;
   }
   public Integer getFromUserId() {
      return fromUserId;
   }
   public void setFromUserId(Integer fromUserId) {
      this.fromUserId = fromUserId;
   }
   public Integer getToUserId() {
      return toUserId;
   }
   public void setToUserId(Integer toUserId) {
      this.toUserId = toUserId;
   }
   public Timestamp getDate() {
      return date;
   }
   public void setDate(Timestamp date) {
      this.date = date;
   }
   public Byte getIfRead() {
      return ifRead;
   }
   public void setIfRead(Byte ifRead) {
      this.ifRead = ifRead;
   }
   public User getFromUser() {
      return fromUser;
   }
   public void setFromUser(User fromUser) {
      this.fromUser = fromUser;
   }
   public User getToUser() {
      return toUser;
   }
   public void setToUser(User toUser) {
      this.toUser = toUser;
   }
   public Byte getType() {
      return type;
   }
   public void setType(Byte type) {
      this.type = type;
   }
   
}


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Thu Mar 16, 2017 10:24 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1385
There are so many things that are wrong in your code:

1. You build the HQL query by concatenating strings so you risk SQL Injection attacks
2. You need to use Criteria API, so constructs like 1+1 are not needed at all
3. There is no reasonable explanation why Hibernate would populate a result with N entities and also append a null there. Maybe you are using an old Hibernate version?

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Thu Mar 16, 2017 9:08 pm 
Newbie

Joined: Wed Mar 15, 2017 8:44 pm
Posts: 8
vlad wrote:
There are so many things that are wrong in your code:

1. You build the HQL query by concatenating strings so you risk SQL Injection attacks
2. You need to use Criteria API, so constructs like 1+1 are not needed at all
3. There is no reasonable explanation why Hibernate would populate a result with N entities and also append a null there. Maybe you are using an old Hibernate version?

so ,how can I reduce SQL Injection attacks?
and how can I reduce 1+1

and I use the hibernate version5.2.1
this screenshot is my test
Image

the xml is
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.pouruan.web.entity">
   <class name="Message" table="`message`">
      <meta attribute="sync-DAO">false</meta>
      <cache usage="read-write"/>
      <id name="messageId" type="java.lang.Integer" column="`message_id`"> <generator class="identity"/></id>
       <property name="content" column="`content`" type="java.lang.String" not-null="true"  length="1000"/>
       <property name="fromUserId" column="`from_user`" type="java.lang.Integer" not-null="true" />
      <property name="toUserId" column="`to_user`"  type="java.lang.Integer" not-null="true" />
      <property name="date" column="`date`"  type="java.sql.Timestamp" not-null="true" />
      <property name="ifRead"  column="`if_read`"  type="java.lang.Byte" not-null="true"/>
      <property name="type"  column="`type`"  type="java.lang.Byte" not-null="true"/>
      <many-to-one name="fromUser"  column="`from_user`" insert="false" update="false" />
      <many-to-one name="toUser"  column="`to_user`" insert="false" update="false" />
   </class>
</hibernate-mapping>


the dao is
Code:
package com.pouruan.web.dao.impl;

import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.pouruan.web.dao.MessageDao;
import com.pouruan.web.entity.Message;
import com.pouruan.web.entity.User;

@Repository
public class MessageDaoImpl implements MessageDao{
   @Autowired
   private  SessionFactory sessionFactory;
   private Logger logger = LogManager.getRootLogger();
   @Override
   public List<Message> getMessageByCondition(Message message,int pageNo,int  pageSize) {
      Session session= sessionFactory.getCurrentSession();
      String condition ="1=1 ";
      if(message.getMessageId()!=null){
         condition+=" And m.messageId = "+message.getMessageId();
      }
      if(message.getFromUserId()!=null){
         condition+=" And m.fromUserId = "+message.getFromUserId();
      }
      if(message.getToUserId()!=null){
         condition+=" And m.toUserId like "+message.getToUserId();
      }
      if(message.getIfRead()!=null){
         condition+=" And m.ifRead like "+message.getIfRead();
      }
      String hql = "FROM Message AS m WHERE "+condition+" order by m.messageId  desc";
      Query<?> query =session.createQuery(hql);
      return (List<Message>) query.setFirstResult((pageNo-1)*pageSize) 
        .setMaxResults(pageSize) 
        .list();
   }

   
   
   @Override
   public int getMessageCountByCondition(Message message) {
      Session session= sessionFactory.getCurrentSession();
      String condition ="1=1 ";
      if(message.getMessageId()!=null){
         condition+=" And m.messageId = "+message.getMessageId();
      }
      if(message.getFromUserId()!=null){
         condition+=" And m.fromUserId = "+message.getFromUserId();
      }
      if(message.getToUserId()!=null){
         condition+=" And m.toUserId = "+message.getToUserId();
      }
      if(message.getIfRead()!=null){
         condition+=" And m.ifRead = "+message.getIfRead();
      }
      if(message.getType()!=null){
         condition+=" And m.type = "+message.getType();
      }
      String hql = "select count(*) FROM  Message AS m  WHERE "+condition;
      Query<?> query =session.createQuery(hql);
      return ((Number)query.uniqueResult()).intValue();
   }
   @Override
   public boolean delMessage(Message message) {
      Session session= sessionFactory.getCurrentSession();
      try{
         session.delete(message);
      }catch(Exception e){
         logger.error("删除message出错"+e);
         return false;
      }
      return true;
   }

   @Override
   public boolean addMessage(Message message) {
      Session session= sessionFactory.getCurrentSession();
      try{
         session.save(message);
      }catch(Exception e){
         logger.error("增加message出错"+e);
         return false;
      }
      return true;
   }



   @Override
   public boolean editMessage(Message message) {
      Session session= sessionFactory.getCurrentSession();
      try{
         session.update(message);
      }catch(Exception e){
         logger.error("修改message出错"+e);
         return false;
      }
      return true;
   }

}



Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Fri Mar 17, 2017 2:07 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1385
Maybe you have a record where getFromUser is null. As you can see, it's not the returned entity that is null, but an attribute. Run an SQL query and validate your assumptions.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Fri Mar 17, 2017 4:45 am 
Newbie

Joined: Wed Mar 15, 2017 8:44 pm
Posts: 8
vlad wrote:
Maybe you have a record where getFromUser is null. As you can see, it's not the returned entity that is null, but an attribute. Run an SQL query and validate your assumptions.

Run an SQL query???
getFromUser return a entity ,is'nt entity attribute ?


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Fri Mar 17, 2017 5:06 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1385
The entity attribute is null, not the entity.

Run the SQL query in the DB console and see what you have there. Makes sense?

Also, you should read our User Guide, all of it. Then you'll understand what I'm talking about.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Fri Mar 17, 2017 10:32 pm 
Newbie

Joined: Wed Mar 15, 2017 8:44 pm
Posts: 8
vlad wrote:
The entity attribute is null, not the entity.

Run the SQL query in the DB console and see what you have there. Makes sense?

Also, you should read our User Guide, all of it. Then you'll understand what I'm talking about.


yes ,the entity attribute is null,but why ?why only the lastest one 's entity attribute is null ?
I look the sql log

Code:
       3117 Query   SET autocommit=1
       3117 Query   SET autocommit=0
       3117 Query   select message0_.`message_id` as message_1_9_, message0_.`content` as content2_9_, message0_.`from_user` as from_use3_9_, message0_.`to_user` as to_user4_9_, message0_.`date` as date5_9_, message0_.`if_read` as if_read6_9_, message0_.`type` as type7_9_ from `message` message0_ where 1=1 and message0_.`from_user`=3 order by message0_.`message_id` desc limit 1
       3117 Query   insert into `message` (`content`, `from_user`, `to_user`, `date`, `if_read`, `type`) values ('test', 3, 4, '2017-03-18 10:18:12', 0, 0)
       3117 Query   select last_insert_id()
       3117 Query   commit
       3117 Query   SET autocommit=1
170318 10:18:13    3117 Query   SET autocommit=0
       3117 Query   select message0_.`message_id` as message_1_9_, message0_.`content` as content2_9_, message0_.`from_user` as from_use3_9_, message0_.`to_user` as to_user4_9_, message0_.`date` as date5_9_, message0_.`if_read` as if_read6_9_, message0_.`type` as type7_9_ from `message` message0_ where 1=1 and message0_.`if_read`=0 order by message0_.`message_id` desc limit 10
       3117 Query   commit
       3117 Query   SET autocommit=1


i Run the SQL query in the DB console,this is the reslut
Image




Code:
   @RequestMapping(value = "/t.do")
   public void listMessage(HttpServletRequest request,
         HttpServletResponse response, ModelMap model){
      //insert new one
      String content="test";
      int fromUserId=3;
      int toUserId=4;
      messageService.addMessage(StringEscapeUtils.escapeHtml4(content), fromUserId, toUserId,0);
       // if i reduce last four line code , I will get right result (all getFromUser() is not null)
      //find out the ten latest
      int pageNo=1;
      int pageSize=10;
      Message m=new Message();
      m.setIfRead((byte)0);
      List<Message> list =messageService.getMessageByCondition(m, pageNo, pageSize);
      for(int i=0;i<list.size();i++){
         if(list.get(i).getFromUser()!=null){
            System.out.println("fromUser not null");
         }else{
            System.out.println("null");
         }
      }
   }


may be I misunderstand your answer....


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Fri Mar 17, 2017 10:35 pm 
Newbie

Joined: Wed Mar 15, 2017 8:44 pm
Posts: 8
vlad wrote:
Maybe you have a record where getFromUser is null. As you can see, it's not the returned entity that is null, but an attribute. Run an SQL query and validate your assumptions.

how can i record where getFromUser?
this is the message class

Code:
package com.pouruan.web.entity.parent;

import java.sql.Timestamp;

import org.apache.commons.lang3.StringEscapeUtils;

import com.pouruan.web.entity.User;

public class Message {
   private Integer messageId;
   private String content;
   private Integer fromUserId;
   private User fromUser;
   private Integer toUserId;
   private User toUser;
   private Timestamp date;
   private Byte ifRead;
   private Byte type;
   public Integer getMessageId() {
      return messageId;
   }
   public void setMessageId(Integer messageId) {
      this.messageId = messageId;
   }
   public String getContent() {
      return content;
   }
   public void setContent(String content) {
      this.content = content;
   }
   public Integer getFromUserId() {
      return fromUserId;
   }
   public void setFromUserId(Integer fromUserId) {
      this.fromUserId = fromUserId;
   }
   public Integer getToUserId() {
      return toUserId;
   }
   public void setToUserId(Integer toUserId) {
      this.toUserId = toUserId;
   }
   public Timestamp getDate() {
      return date;
   }
   public void setDate(Timestamp date) {
      this.date = date;
   }
   public Byte getIfRead() {
      return ifRead;
   }
   public void setIfRead(Byte ifRead) {
      this.ifRead = ifRead;
   }
   public User getFromUser() {
      return fromUser;
   }
   public void setFromUser(User fromUser) {
      this.fromUser = fromUser;
   }
   public User getToUser() {
      return toUser;
   }
   public void setToUser(User toUser) {
      this.toUser = toUser;
   }
   public Byte getType() {
      return type;
   }
   public void setType(Byte type) {
      this.type = type;
   }
   
}



Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Sat Mar 18, 2017 2:25 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1385
It's very simple. You have two things mapping to the same Fk:

Code:
public Integer getFromUserId() {
      return fromUserId;
}

public User getFromUser() {
      return fromUser;
}


So, that looks like you are duplicating the mapping on the very same DB column. You don't really need the getFromUserId attribute.

If you were using annotations, your mapping would have been:

Code:
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="user_id")
private User user;


Now, you are persisting the user_id column, but the User attribute is not associated back. most likely because you forgot to set the reference with a proxy prior to saving it:

Code:
message.setUser(entityManager.getReference(User.class, userId));


You really have to read the Hibernate User Guide. Otherwise, you'll struggle more with this kind of issues.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Sat Mar 18, 2017 8:00 am 
Newbie

Joined: Wed Mar 15, 2017 8:44 pm
Posts: 8
vlad wrote:
It's very simple. You have two things mapping to the same Fk:

Code:
public Integer getFromUserId() {
      return fromUserId;
}

public User getFromUser() {
      return fromUser;
}


So, that looks like you are duplicating the mapping on the very same DB column. You don't really need the getFromUserId attribute.

If you were using annotations, your mapping would have been:

Code:
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="user_id")
private User user;


Now, you are persisting the user_id column, but the User attribute is not associated back. most likely because you forgot to set the reference with a proxy prior to saving it:

Code:
message.setUser(entityManager.getReference(User.class, userId));


You really have to read the Hibernate User Guide. Otherwise, you'll struggle more with this kind of issues.


oh thank you ,
but I still don't konw why nine others 's getFromUser is not null

ps:my English is poor so l read the Hibernate User Guide is not clear....


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Sat Mar 18, 2017 8:17 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1385
The other 9 are not null because they were fetched from the DB while the one with null was just persisted. If you call:

Code:
session.refresh(theEntityWithNull);


you'll see that the User association is not null anymore.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: in some time ,entity can relative the other entity
PostPosted: Sun Mar 19, 2017 5:17 am 
Newbie

Joined: Wed Mar 15, 2017 8:44 pm
Posts: 8
vlad wrote:
The other 9 are not null because they were fetched from the DB while the one with null was just persisted. If you call:

Code:
session.refresh(theEntityWithNull);


you'll see that the User association is not null anymore.



oh ,thank you very much


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.