spring data hibernate lazy loading
<p>I'm in the middle of learning Spring Data/Hibernate stuff and faced with known issue of lazy loading in Hibernate. I tried different approaches described in stackoverflow and other resources, but it looks like they don't work. I'm using hibernate in coupe with spring data annotation configuration. My approaches were:</p>

<ol>
<li>Plain loading of @OneToMany dependency with <em>fetch = FetchType.LAZY</em>. As expected I receive <em>LazyInitializationException</em> with message about </li>
</ol>

<blockquote>
  <p>could not initialize proxy - no Session</p>
</blockquote>

<ol start="2">
<li>Using transactional repository. Same result as for the first point;</li>
<li>Using Spring transaction template. Same result;</li>
<li>Using @NamedEntityGraph of JPA 2.1. Here situation is more interesting. My test pass, however in SQL debug I can see data are not loaded lazy, but at the first time I querying repository. Another words child table joined to parent table first time I'm querying repository.</li>
</ol>

<p>I pushed my test project to github, so it's possible to review it there 
<a href="https://github.com/megamaxskx/hibernate_lazy_fetch" rel="nofollow">https://github.com/megamaxskx/hibernate_lazy_fetch</a></p>

<p><strong>UPDATED</strong></p>

<p><strong>Spring transaction template approach:</strong>
Repository:</p>

<pre><code>@Repository
public interface PlainParentRepository extends CrudRepository&lt;PlainParent, Long&gt; {

}
</code></pre>

<p>Configuration:</p>

<pre><code>@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = REPOSITORY_LOCATION)
public class DBConfig {

    public static final String REPOSITORY_LOCATION = "com.lazyloadingtest";
    private static final String ENTITIES_LOCATION = "com.lazyloadingtest";

    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setDatabase(Database.H2);
        jpaVendorAdapter.setGenerateDdl(true);
        jpaVendorAdapter.setShowSql(true);
        return jpaVendorAdapter;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean lemfb = new LocalContainerEntityManagerFactoryBean();
        lemfb.setDataSource(dataSource());
        lemfb.setJpaVendorAdapter(jpaVendorAdapter());
        lemfb.setPackagesToScan(ENTITIES_LOCATION);
        lemfb.setJpaProperties(hibernateProperties());
        return lemfb;
    }

    protected Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.format_sql", true);
        return properties;
    }

}
</code></pre>

<p>Child class:</p>

<pre><code>@Entity
public class EntityGraphChild implements Serializable {

    public static long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private long id;

    private String name;

    @ManyToOne
    private PlainParent parent;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public PlainParent getParent() {
        return parent;
    }

    public void setParent(PlainParent parent) {
        this.parent = parent;
    }
}
</code></pre>

<p>Parent class:</p>

<pre><code>@Entity
public class PlainParent implements Serializable {

    public static long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private long id;

    private String name;

    @OneToMany(targetEntity = PlainChild.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Set&lt;PlainChild&gt; children;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set&lt;PlainChild&gt; getChildren() {
        return children;
    }

    public void setChildren(Set&lt;PlainChild&gt; children) {
        this.children = children;
    }
}
</code></pre>

<p>Spring transaction template test:</p>

<pre><code>@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
        DBConfig.class,
})
public class SpringTransactionTemplateTest {

    @Autowired
    private PlainParentRepository repository;

    @Autowired
    private JpaTransactionManager transactionManager;

    @Test
    public void testRepository() {
        PlainChild child1 = new PlainChild();
        child1.setName("first child");

        PlainChild child2 = new PlainChild();
        child2.setName("second child");

        PlainParent parent = new PlainParent();
        parent.setId(1l);
        HashSet&lt;PlainChild&gt; children = new HashSet&lt;PlainChild&gt;(Arrays.asList(child1, child2));
        parent.setChildren(children);
        repository.save(parent);

        TransactionTemplate txTemplate = new TransactionTemplate();
        txTemplate.setTransactionManager(transactionManager);

        Set&lt;PlainChild&gt; fromDB = txTemplate.execute(new TransactionCallback&lt;Set&lt;PlainChild&gt;&gt;() {
            public Set&lt;PlainChild&gt; doInTransaction(TransactionStatus transactionStatus) {
                PlainParent fromDB = repository.findOne(1L);
                return fromDB.getChildren();
            }
        });

        assertEquals(2, fromDB.size());
    }

 }
</code></pre>

<p><strong>NamedEntityGraph approach:</strong></p>

<p>Child:</p>

<pre><code>@Entity
public class EntityGraphChild implements Serializable {

    public static long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private long id;

    private String name;

    @ManyToOne
    private EntityGraphParent parent;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public EntityGraphParent getParent() {
        return parent;
    }

    public void setParent(EntityGraphParent parent) {
        this.parent = parent;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        EntityGraphChild child = (EntityGraphChild) o;

        if (id != child.id) return false;
        return name != null ? name.equals(child.name) : child.name == null;

    }
}
</code></pre>

<p>Parent:</p>

<pre><code>@Entity
@NamedEntityGraph(
        name = "graph.Parent.children",
        attributeNodes = @NamedAttributeNode(value = "children")
)
public class EntityGraphParent implements Serializable {

    public static long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private long id;

    private String name;

    @OneToMany(targetEntity = EntityGraphChild.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Set&lt;EntityGraphChild&gt; children;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set&lt;EntityGraphChild&gt; getChildren() {
        return children;
    }

    public void setChildren(Set&lt;EntityGraphChild&gt; children) {
        this.children = children;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        EntityGraphParent parent = (EntityGraphParent) o;

        if (id != parent.id) return false;
        if (name != null ? !name.equals(parent.name) : parent.name != null) return false;
        return children != null ? children.equals(parent.children) : parent.children == null;

    }

    @Override
    public int hashCode() {
        int result = (int) (id ^ (id &gt;&gt;&gt; 32));
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (children != null ? children.hashCode() : 0);
        return result;
    }
}
</code></pre>

<p>Test:</p>

<pre><code>@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
        DBConfig.class,
})
public class EntityGraphParentRepositoryTest {

    @Autowired
    private EntityGraphParentRepository repository;

    @Test
    public void testRepository() {
        EntityGraphChild child1 = new EntityGraphChild();
        child1.setName("first child");

        EntityGraphChild child2 = new EntityGraphChild();
        child2.setName("second child");

        EntityGraphParent parent = new EntityGraphParent();
        parent.setId(1l);
        parent.setName("ParentGraph");
        HashSet&lt;EntityGraphChild&gt; children = new HashSet&lt;EntityGraphChild&gt;(Arrays.asList(child1, child2));
        parent.setChildren(children);

        repository.save(parent);

        System.out.println("--- Before querying repo");
        EntityGraphParent fromDB = repository.findByName("ParentGraph");
        System.out.println("--- After querying repo");
        assertEquals(2, fromDB.getChildren().size());
        System.out.println("--- Test finished");
    }

}
</code></pre>

<p>Repository:</p>

<pre><code>@Repository
public interface EntityGraphParentRepository extends CrudRepository&lt;EntityGraphParent, Long&gt; {

    @EntityGraph(value = "graph.Parent.children", type = EntityGraph.EntityGraphType.LOAD)
    public EntityGraphParent findByName(String name);
}
</code></pre>