Announcement Announcement Module
Collapse
No announcement yet.
Issues with XXXToOne lazy load - org.hibernate.LazyInitializationException Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Issues with XXXToOne lazy load - org.hibernate.LazyInitializationException

    Hi there,

    I have the following setup in my development environment:
    1. Spring 3
    2. Spring Data JPA - using repositories
    3. JPA-Hibernate

    I am trying out the XXXToOne lazy initialization workaround located at http://justonjava.blogspot.com/2010/...e-to-many.html. Here is an example of one of my entities:

    Code:
    @Entity
    @Table(name = "PLAYER_SPOUSE")
    public class PlayerSpouse extends BaseEntity implements FieldHandled {
    
    	private static final long serialVersionUID = 1L;
    
    	private FieldHandler fieldHandler;
    
    	@Column(name = "NAME")
    	private String name;
    
    	@OneToOne(fetch = FetchType.LAZY, optional = true, mappedBy = "playerSpouse")
    	@LazyToOne(LazyToOneOption.NO_PROXY)
    	private Player player;
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public Player getPlayer() {
    		if (fieldHandler != null) {
    			return (Player) fieldHandler.readObject(this, "player", player);
    		}
    		return player;
    	}
    
    	public void setPlayer(Player player) {
    		if (fieldHandler != null) {
    			this.player = (Player) fieldHandler.writeObject(this, "player",
    					this.player, player);
    			return;
    		}
    
    		this.player = player;
    	}
    
    	@Override
    	public void setFieldHandler(FieldHandler handler) {
    		fieldHandler = handler;
    	}
    
    	@Override
    	public FieldHandler getFieldHandler() {
    		return fieldHandler;
    	}
    
    }
    However, I cannot get it to work in my environment using Spring Data JPA repositories as I am encountering an error in "org.hibernate.LazyInitializationException: session is not connected" when I attempt to get a Player from a PlayerSpouse object.

    Here is my offending code:
    Code:
    PlayerSpouse findByName = playerSpouseRepository.findByName("Toni");
    		
    		findByName.getPlayer(); // error
    Here is my stack trace:
    Code:
    SEVERE: org.hibernate.LazyInitializationException: session is not connected
    	at org.hibernate.bytecode.instrumentation.spi.AbstractFieldInterceptor.intercept(AbstractFieldInterceptor.java:89)
    	at org.hibernate.bytecode.instrumentation.internal.javassist.FieldInterceptorImpl.readObject(FieldInterceptorImpl.java:98)
    When I tried it out with plain Hibernate however, it works perfectly:
    Code:
    		SessionFactory sf = sessionFactory;
    
    		Session openSession = sf.openSession();
    
    		Object ps = openSession.get(PlayerSpouse.class, 6L);
    
    		if (ps instanceof PlayerSpouse) {
    			PlayerSpouse ps1 = (PlayerSpouse) ps;
    			ps1.getPlayer(); // works
    		}
    
    		openSession.close();
    Can anybody help me with this? Thanks!

  • #2
    The plain hibernate code isn't the same as the spring code. I suggest you read up on how spring manages transactions and that you correctly specify transactions (the service layer should be transactional NOT the dao layer). If you want to render something in the the view you are probably going to need the OpenEntityManagerInViewFilter to keep the entitymanager open until after the view rendering.

    Comment


    • #3
      Hi, I just had an almost identical issue right now - and after a couple of hours this is where I got to. I'll post my findings - maybe we can get to the bottom of it

      My issue was that I switched a url structure in my Spring-MVC application from using an actual id to using an internal id. So something like:

      Code:
      http://example.com/app/edit/12
      (where 12 is the real id in the database) changed to
      Code:
      http://example.com/app/edit/XU99L
      (where XU99L is an internal id of the object.

      This means that inside my controller I changed the code for the GET method. Instead of using
      Code:
      superheroRepository.findOne(Long id)
      it now uses
      Code:
      superHeroRepository.findByInternalId(String internalId)
      So - the get method works, and the superhero gets loaded, however - if I then POST - I get the LIE - and hibernate suggests that the session is no longer there.

      From what I can see, the automagic finders on the repository use Hibernate's Session.load() - which means that they actually return a proxy. The findOne() seems to use Session.get() - which doesn't return a proxy. When I save, I need to do things with some of the @OneToMany fields, and that's when the proxy throws up on me.

      Hope this helps.

      Comment


      • #4
        So - the get method works, and the superhero gets loaded, however - if I then POST - I get the LIE - and hibernate suggests that the session is no longer there.
        When doing a POST you shouldn't reuse the object you got with the GET but first retrieve the object, modify the properties and store again.

        From what I can see, the automagic finders on the repository use Hibernate's Session.load()
        No they don't... The use a query/criteria to load the objects not load or get (also there is no session there is an entitymanager and those are different).

        Comment


        • #5
          I have tried the OpenEntityManagerInViewFilter and it works fine. Thanks!

          Comment

          Working...
          X