Hibernate: org.hibernate.LazyInitializationException: Failed to lazily initialize role collection: session or session closed

I will learn to hibernate. But I am stuck at a very simple point.

When the source is next

    Controller : data collection and ready to display 
    Service : Transaction processing
    Dao : access Database 

      

And data processing in this form.


Test.java

@Entity
@Table ( name = "table_test" )
public class Test
{

    @Id
    @GeneratedValue ( strategy = GenerationType.AUTO )
    public long id;

    @OneToMany(fetch=FetchType.LAZY)
    @JoinColumn(name="test_id")
    @IndexColumn(name="orderBy")
    public List<TestItem> items;

}

      

TestItem.java

@Entity
@Table ( name = "table_item" )
public class TestItem
{

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="test_id", insertable=false, updatable=false)
    public Test parent;

    @Id
    @GeneratedValue ( strategy = GenerationType.AUTO )
    public long id;

}

      

TestDao.java

@Repository
public class TestDao
{

    @Autowired SessionFactory sessionFactory;

    protected Session getSession(){
        return sessionFactory.getCurrentSession();
    }

    public Test get(long id){
        return (Test) getSession().createCriteria( Test.class )
                    .add( Restrictions.eq( "id", id ) ).uniqueResult();
    }
}

      

TestService.java

@Service
@Transactional
public class TestService
{

    @Autowired
    TestDao testd;

    public Test get(long id){
        return testd.get( id );
    }

    public List<TestItem> getItems(Test test){
        List<TestItem> items = test.items;
        items.iterator();
        return items;
    }

}

      

TestController.java

@Controller
@RequestMapping ( "/test" )
public class TestController extends BaseController
{
    @Autowired
    TestService testService;

    @RequestMapping ( "/{id}" )
    public String seriesList ( @PathVariable long id, Model model )
    {
        Test test = testService.get( id );

        //something...

        List<TestItem> lists = testService.getItems( test );

        for(TestItem item : lists)
        {
            Model.addAttribute(item.id);
        }

        return "index";
    }
}

      

AN EXCEPTION

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.test.domain.Test.items, no session or session was closed
    org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
    org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
    org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)

      


For what reason, if I am using Lazy.

This is because it cannot be used by the Something list.

I know how to get around some.

1) The first solution is "already a list", but removes the need for lazy.

@Service
@Transactional
public class TestService
{

    @Autowired
    TestDao testd;

    public Test get(long id){
        Test test = testd.get( id );
        test.items.iterator();
        return test;
    }

    public List<TestItem> getItems(Test test){
        List<TestItem> items = test.items;
        items.iterator();
        return items;
    }

}

      

2) the second solution is "a process by an internal transaction", but this solution is used, it is always executed in a transaction

@Controller
@RequestMapping ( "/test" )
public class TestController extends BaseController
{
    @Autowired
    TestService testService;

    @RequestMapping ( "/{id}" )
    public String seriesList ( @PathVariable long id, Model model )
    {
        return testService.view( id, model );
    }
}
@Service
@Transactional
public class TestService
{

    @Autowired
    TestDao testd;

    public Test get(long id){
        Test test = testd.get( id );
        return test;
    }

    public String view(long id, Model model){
        Test test = get( id );

        List<TestItem> lists = test.items;

        for(TestItem item : lists)
        {
            model.addAttribute( item.id );
        }

        return "index";
    }

}

      


There seem to be several problems.

So, I only want to educate when necessary.

+3


source to share


1 answer


You will need to understand the concept of session and session boundaries. Hibernate works with proxies for performance reasons and does not load all associations unless needed. For session concepts you can see here



If you are in a Spring framework (which I think you are) you can check the Open Session filter. This opens a session in the context of the request so that you can access associations across all layers. You might not want to increase transaction boundaries.

+1


source







All Articles