Error org.hibernate.Lazyinitializationexception how to resolve?

Asked

Viewed 478 times

2

I know this error is derived from trying to fetch some data from the database when I have no session open.

But the biggest problem for me is that this error is appearing to me completely random, as I am developing a server that processes data and then sends to clients, every 3 minutes the server repeats the same operations, but the error either appears right on the server run or may appear after 3 or 4 hours of running the server.

The error always points to the class Produto more precisely for the method toString, I commented the method and now gives error in hashCode.

Structure in the database:

|| Lot || ----Contains ---> || Product || ----Contains ---> || qualityGates ||

Code -> Product.java

public class Produto  implements java.io.Serializable {


     private Integer idProduto;
     private Qualitygate qualitygateByIdQualityGate3;
     private Qualitygate qualitygateByIdQualityGate2;
     private Qualitygate qualitygateByIdQualityGate1;
     private Familiaproduto familiaproduto;
     private String noproduto;
     private Integer vt;
     private String tipo;
     private Set loteestados = new HashSet(0);

    public Produto() {
    }

//++ GET'S & SET'S

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 59 * hash + Objects.hashCode(this.idProduto);
        hash = 59 * hash + Objects.hashCode(this.qualitygateByIdQualityGate3); // <-----erro
        hash = 59 * hash + Objects.hashCode(this.qualitygateByIdQualityGate2);
        hash = 59 * hash + Objects.hashCode(this.qualitygateByIdQualityGate1);
        hash = 59 * hash + Objects.hashCode(this.familiaproduto);
        hash = 59 * hash + Objects.hashCode(this.noproduto);
        hash = 59 * hash + Objects.hashCode(this.vt);
        hash = 59 * hash + Objects.hashCode(this.tipo);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Produto other = (Produto) obj;
        if (!Objects.equals(this.idProduto, other.idProduto)) {
            return false;
        }
        if (!Objects.equals(this.qualitygateByIdQualityGate3, other.qualitygateByIdQualityGate3)) {
            return false;
        }
        if (!Objects.equals(this.qualitygateByIdQualityGate2, other.qualitygateByIdQualityGate2)) {
            return false;
        }
        if (!Objects.equals(this.qualitygateByIdQualityGate1, other.qualitygateByIdQualityGate1)) {
            return false;
        }
        if (!Objects.equals(this.familiaproduto, other.familiaproduto)) {
            return false;
        }
        if (!Objects.equals(this.noproduto, other.noproduto)) {
            return false;
        }
        if (!Objects.equals(this.vt, other.vt)) {
            return false;
        }
        if (!Objects.equals(this.tipo, other.tipo)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return " noproduto=" + noproduto;
    }
//    @Override
//    public String toString() {
//        return "Produto{" + "idProduto=" + idProduto + ", qualitygateByIdQualityGate3=" + qualitygateByIdQualityGate3 + ", qualitygateByIdQualityGate2=" + qualitygateByIdQualityGate2 + ", qualitygateByIdQualityGate1=" + qualitygateByIdQualityGate1 + ", familiaproduto=" + familiaproduto + ", noproduto=" + noproduto + ", vt=" + vt + ", tipo=" + tipo + ", loteestados=" + loteestados + '}';
//    }

  }

Code -> Product.hbm.xml

<hibernate-mapping>
  <class catalog="mydb" name="Models.Produto" table="produto">
    <id name="idProduto" type="java.lang.Integer">
      <column name="idProduto"/>
      <generator class="identity"/>
    </id>
    <many-to-one class="Models.Qualitygate" fetch="select" name="qualitygateByIdQualityGate3">
      <column name="idQualityGate3"/>
    </many-to-one>
    <many-to-one class="Models.Qualitygate" fetch="select" name="qualitygateByIdQualityGate2">
      <column name="idQualityGate2"/>
    </many-to-one>
    <many-to-one class="Models.Qualitygate" fetch="select" name="qualitygateByIdQualityGate1">
      <column name="idQualityGate1"/>
    </many-to-one>
    <many-to-one class="Models.Familiaproduto" fetch="select" name="familiaproduto">
      <column name="idNomeProduto"/>
    </many-to-one>
    <property name="noproduto" type="string">
      <column length="45" name="noproduto" not-null="true" unique="true"/>
    </property>
    <property name="vt" type="java.lang.Integer">
      <column name="vt"/>
    </property>
    <property name="tipo" type="string">
      <column length="10" name="tipo"/>
    </property>
    <set fetch="select" inverse="true" lazy="true" name="loteestados" table="loteestado">
      <key>
        <column name="ProdutoidProduto" not-null="true"/>
      </key>
      <one-to-many class="Models.Loteestado"/>
    </set>
  </class>
</hibernate-mapping>

Code -> Genericodao Session creation (At first there was the HibernateUtil to create me the sessions but due to the problem of creating many sessions and giving full memory error I changed to this approach)

public class GenericDao<T extends Serializable> {

    private static Session session;
    public Class<T> persistentClass;

    public GenericDao(){
        //this.session = HibernateUtil.getSession();
        this.persistentClass = (Class<T>) ((ParameterizedType) 
            getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public Session createSession(){
            Configuration cfg= new Configuration().configure();
        SessionFactory sessionfactory=cfg.buildSessionFactory();
        session=sessionfactory.openSession();

        return this.session;
    }
    public Session getSession() {
        if(this.session == null || !this.session.isOpen()){  
           return createSession();
        } else return session;
    }

    protected void save(T entity) {

         try {

            Session session = getSession();
            session.beginTransaction();
            session.save(entity);
            session.getTransaction().commit();
        } catch (Exception e) {
            session.getTransaction().rollback();

        } finally {
            session.close();
        }

   }

// ----------------------- +outros métodos 

    public T findById(Integer id) {
        return (T) getSession().createCriteria(persistentClass)
                .add(Restrictions.eq("id", id)).uniqueResult();
    }


    private void close() {
        if (getSession() != null && getSession().isOpen()) {
            getSession().close();
        }
    }
}

Any solution to this problem?

1 answer

1


First of all, if you always use accesses all object attributes, you should use the mode ager and not Lazy.

However, the problem may have its cause in the fact that, in certain circumstances, Hibernate creates proxies in entities Lazy, which means it doesn’t load the data until it intercepts a call to a method getter.

I myself have had problems accessing attributes in these types of objects. Solution? Try call the method getter instead of accessing the attributes directly.

For example, where do you do this:

hash = 59 * hash + Objects.hashCode(this.idProduto);

You can switch to that:

hash = 59 * hash + Objects.hashCode(this.getIdProduto());
  • 1

    Could you post a line of code with the examples you gave? just to make sure I got it right... for example when you talk about calling getter methods is this: this.objeto.getNome instead of this.objeto ? and by the way thanks for the help

  • @jsantos1991 I updated the answer

  • Thanks for editing, as the error is random let’s see if it solves, if that’s the case I come to mark as the right.

  • It gave the error again, after 4 h working it decided to appear, did not interrupt the program but still wanted to try to solve this problem, you know how I can change my mapping to eager? or some example of a good implementation of the session?

  • @jsantos1991 Your Session must be closing in some situation. How do you manage your Daos instances? Is it not a competition problem? You store Session in a class attribute, so if two users access the system at the same time and share the same Session, one will close the session of the other, understand? I think you’d better define a SessionFactory global and recover a new local Session in each method. Also, try to change fetch="select" for fetch="join".

  • thanks again for the help, I’ve had this sessionFactory but I could not implement it right, the program burst(full memory), I will make these changes, then I say something.

  • Ah as for the resorts, I have at the beginning of the program something like this ProdutoDao prodDao=new ProdutoDAO(); and then use throughout the program when needed prodDao.save(obejto) it’s wrong to do so?

  • is a desktop system, I will implement this SessionFactory see if I can get it to work properly

  • @jsantos1991 The problem of using the same Session is related to the competition. If there is more than one process running at the same time they will use the same session and one can close the other session. If the system is not web but local, then you could keep the same Sesssion open all the time. Only if a processing takes longer than 3 minutes, then the next "pipeline" could give problem. Try to remove the session.close() of the method save and switch to fetch="join" in relationships.

  • the fetch ="join" I have changed, but since the error is random I do not know if I can solve the problem, however and to finish this subject, when you talk about removing session.close() you mean all the close-ups and so always work with the same session right?

  • @jsantos1991 That’s right, the idea would be to work leaving the session open and working with it. If you need to open and close a session, create a new session in a local method variable, never in a shared variable.

  • thanks again for all the help/explanation, I will mark the answer as sure since after you manage to implement the problem should disappear...

Show 7 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.