title: Hibernate: Lazy initialization vs broken hashcode/equals conundrum
body: <p>I'm quite new to JPA and Hibernate (I'm studying hard though!) and I am struggling with a problem that I can't seem to find a trivial solution for, so here it is.</p>
  
  <p>I have an entity that looks kinda like the following:</p>
  
  <pre><code>@Entity
  @Table(name = "mytable1")
  public class EntityOne {
    // surrogate key, database generated
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
  
    // business key
    @Column(name = "identifier", nullable = false, unique = true)
    private String identifier;
  
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
    @JoinColumn(name = "twoId", nullable = false)
    private EntityTwo two;
  
    @OneToMany(mappedBy = "entityOne", fetch = FetchType.EAGER, 
      cascade = {CascadeType.ALL}, orphanRemoval = true)
    private Set&lt;EntityThree&gt; resources = new HashSet&lt;&gt;();
  
    // getters/setters omitted
  
    @Override
    public int hashCode() {
      // the business key should always be defined (through constructor/query)
      // if this is null the class violates the general hashcode contract 
      // that the integer value returned must always be the same
      Assert.notNull(identifier);
      // a dirty alternative would be:
      // if(identifier==null) return 0;
      return identifier.hashCode();
    }
  
    @Override
    public boolean equals(Object o) {
      return o instanceof ResourceGroup 
        &amp;&amp; ((ResourceGroup) o).identifier.equals(identifier);
    }
  }
  </code></pre>
  
  <p>My project is set up with Spring JPA, so I have my <code>CrudRepository&lt;EntityOne,Long&gt;</code> injected in a Service class that has a few <code>@Transactional</code> methods and I scan my domain/service packages for JPA and transactions respectively.</p>
  
  <p>One of the service methods calls the repository's <code>findAll()</code> method and returns a list of <code>EntityOne</code>s. Everything works fine unless I try to access the getter for <code>two</code>, which obviously throws:</p>
  
  <pre><code>org.hibernate.LazyInitializationException: could not initialize proxy - no Session
  </code></pre>
  
  <p>I thought it might be useful to have this object initialized, so I switched the fetching type from lazy to eager. However, if I do that I get the following:</p>
  
  <pre><code>java.lang.IllegalArgumentException: [Assertion failed] - this argument is required; it must not be null
      at org.springframework.util.Assert.notNull(Assert.java:112)
      at org.springframework.util.Assert.notNull(Assert.java:123)
      at my.pkg.domain.EntityOne.hashCode(ResourceGroup.java:74)
      at java.util.HashMap.hash(HashMap.java:351)
      at java.util.HashMap.put(HashMap.java:471)
      at java.util.HashSet.add(HashSet.java:217)
      at java.util.AbstractCollection.addAll(AbstractCollection.java:334)
      at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:346)
      at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:243)
      at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:233)
      at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:209)
      at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:1149)
  //...
  </code></pre>
  
  <p>I briefly looked at Hibernate's source code and it looks like it's trying to put my <code>EntityOne</code> objects in a set <strong>before</strong> their business key is initialized. Is my interpretation correct? Is there a way around this? Am I doing something incredibly dumb?</p>
  
  <p>I appreciate your help</p>
  
  <p><strong>EDIT</strong>: I just want to clarify that what I'm trying to understand here is what the best practices are specifically <strong>with respect to JPA and Hibernate</strong>. If this was a plain POJO I could make the identifier field final (I would actually make the whole class immutable) and be safe. I can't do this because I'm using JPA. So the questions: do you violate the hashCode contract and in which way? How does Hibernate deal with this violation? What's the JPA recommended way of doing this in general? Should I get rid of hash based collections altogether and use lists instead?</p>
  
  <p>Giovanni</p>