Page 1 of 2 12 LastLast
Results 1 to 10 of 19

Thread: trouble with lazy loading in hibernate

  1. #1

    Default trouble with lazy loading in hibernate

    Following is my entity bean:
    @Entity
    @Table(name = "NODES")
    @SequenceGenerator(name="nodesPKSequenceGenerator" , sequenceName="NODES_PK_SEQ", allocationSize=1)
    public class Node implements Serializable
    {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "ID", unique = true, nullable = false, precision = 22)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="nodesPKSequenceGenerator")
    private BigInteger id;

    @Column(name = "EXTERNAL_NODE_ID", unique = true, nullable = false, length = 50)
    private String externalNodeId;

    @Column(name = "LAT_DEG", precision = 2)
    private Integer latDeg;

    @Column(name = "LAT_DIRECTION", length = 1)
    private Character latDirection;

    @Column(name = "LAT_MIN", precision = 2)
    private Integer latMin;

    @Column(name = "LAT_SEC", precision = 4, scale = 2)
    private Float latSec;

    @Column(name = "LONG_DEG", precision = 3)
    private Integer longDeg;

    @Column(name = "LONG_DIRECTION", length = 1)
    private Character longDirection;

    @Column(name = "LONG_MIN", precision = 2)
    private Integer longMin;

    @Column(name = "LONG_SEC", precision = 4, scale = 2)
    private Float longSec;

    @OneToMany(mappedBy = "node1", fetch = FetchType.LAZY)
    private List<Link> links1;

    @OneToMany(mappedBy = "node2", fetch = FetchType.LAZY)
    private List<Link> links2;

    public Node()
    {
    }
    //and then getters/setters follow
    }


    And this is my spring bean file:
    <jee:jndi-lookup id="datasource" jndi-name="${jndi.jdbc}"
    resource-ref="true" />
    <bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotati on.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="datasource" />
    <property name="annotatedClasses">
    <list>
    <value>com.network.entity.Node</value>
    <value>com.network.entity.Link</value>
    </list>
    </property>
    <property name="hibernateProperties">
    <bean class="org.springframework.beans.factory.config.Pr opertiesFactoryBean">
    <property name="location" value="classpath:resources/hibernate.properties" />
    </bean>
    </property>
    </bean>
    <bean id="networkTransactionManager" class="org.springframework.orm.hibernate3.Hibernat eTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    <tx:annotation-driven transaction-manager="networkTransactionManager"/>


    Lastly the service class:
    public class NodeServiceImpl implements INodeService
    {
    private IApplicationDAO appDAO;
    @Transactional(propagation = Propagation.REQUIRED)
    private void convertToNodeVO(final Node node, final NodeVO nodeVO)
    {
    nodeVO.setId(node.getId().toString());
    nodeVO.setExternalNodeId(node.getExternalNodeId()) ;
    nodeVO.setLatDeg(node.getLatDeg().toString());
    nodeVO.setLatMin(node.getLatMin().toString());
    nodeVO.setLatSec(node.getLatSec().toString());
    nodeVO.setLatDirection(LatDirection.valueOf(node.g etLatDirection()));
    nodeVO.setLongDeg(node.getLongDeg().toString());
    nodeVO.setLongMin(node.getLongMin().toString());
    nodeVO.setLongSec(node.getLongSec().toString());
    nodeVO.setLongDirection(LongDirection.valueOf(node .getLongDirection()));
    LinkVO linkVOTemp = null;
    NodeVO nodeVOTemp = null;
    List<Link> linksTemp = node.getLinks1(); //this is where it throws exception
    List<LinkVO> linkVOs = null;
    if (!(linksTemp == null) && !(linksTemp.size() == 0))
    {
    linkVOs = new ArrayList<LinkVO>(linksTemp.size());
    for (Link linkTemp : linksTemp)
    {
    linkVOTemp = new LinkVO();
    linkVOTemp.setId(linkTemp.getId().toString());
    linkVOTemp.setExternalLinkId(linkTemp.getExternalL inkId());
    linkVOTemp.setLinkDistance(linkTemp.getLinkDistanc eKms().toString());
    linkVOTemp.setAzimuth1(linkTemp.getAzimuth1().toSt ring());
    linkVOTemp.setAzimuth2(linkTemp.getAzimuth2().toSt ring());

    nodeVOTemp = new NodeVO();
    nodeVOTemp.setId(linkTemp.getNode1().getId().toStr ing());
    nodeVOTemp.setExternalNodeId(linkTemp.getNode1().g etExternalNodeId());
    linkVOTemp.setNode1(nodeVO);

    nodeVOTemp = new NodeVO();
    nodeVOTemp.setId(linkTemp.getNode2().getId().toStr ing());
    nodeVOTemp.setExternalNodeId(linkTemp.getNode2().g etExternalNodeId());
    linkVOTemp.setNode2(nodeVO);
    linkVOs.add(linkVOTemp);
    }
    nodeVO.setLinks1(linkVOs);
    }

    linkVOTemp = null;
    nodeVOTemp = null;
    linksTemp = node.getLinks2();
    linkVOs = null;
    if (!(linksTemp == null) && !(linksTemp.size() == 0))
    {
    linkVOs = new ArrayList<LinkVO>(linksTemp.size());
    for (Link linkTemp : linksTemp)
    {
    linkVOTemp = new LinkVO();
    linkVOTemp.setId(linkTemp.getId().toString());
    linkVOTemp.setExternalLinkId(linkTemp.getExternalL inkId());
    linkVOTemp.setLinkDistance(linkTemp.getLinkDistanc eKms().toString());
    linkVOTemp.setAzimuth1(linkTemp.getAzimuth1().toSt ring());
    linkVOTemp.setAzimuth2(linkTemp.getAzimuth2().toSt ring());

    nodeVOTemp = new NodeVO();
    nodeVOTemp.setId(linkTemp.getNode1().getId().toStr ing());
    nodeVOTemp.setExternalNodeId(linkTemp.getNode1().g etExternalNodeId());
    linkVOTemp.setNode1(nodeVO);

    nodeVOTemp = new NodeVO();
    nodeVOTemp.setId(linkTemp.getNode2().getId().toStr ing());
    nodeVOTemp.setExternalNodeId(linkTemp.getNode2().g etExternalNodeId());
    linkVOTemp.setNode2(nodeVO);
    linkVOs.add(linkVOTemp);
    }
    nodeVO.setLinks2(linkVOs);
    }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public List<NodeVO> findByExample(NodeVO nodeVO)
    {
    // TODO Auto-generated method stub
    Node exampleNode = new Node();
    this.convertToNode(nodeVO, exampleNode);
    List<Node> nodes = appDAO.findByExample(exampleNode);

    NodeVO nodeVOTemp = null;
    if (nodes == null || nodes.size() == 0)
    return null;
    List<NodeVO> nodeVOs = new ArrayList<NodeVO>(nodes.size());
    for (Node nodeTemp : nodes)
    {
    nodeVOTemp = new NodeVO();
    this.convertToNodeVO(nodeTemp, nodeVOTemp);
    nodeVOs.add(nodeVOTemp);
    }

    return nodeVOs;
    }


    Although I have made service methods as Transactional with propagation=Propagation.REQUIRED but still lazy loading gives trouble by throwing following exception:
    Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.network.entity.Node.links1, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollect ion.throwLazyInitializationException(AbstractPersi stentCollection.java:383)
    at org.hibernate.collection.AbstractPersistentCollect ion.throwLazyInitializationExceptionIfNotConnected (AbstractPersistentCollection.java:375)
    at org.hibernate.collection.AbstractPersistentCollect ion.readSize(AbstractPersistentCollection.java:122 )
    at org.hibernate.collection.PersistentBag.size(Persis tentBag.java:248)
    at com.network.service.NodeServiceImpl.convertToNodeV O(NodeServiceImpl.java:143)
    at com.network.service.NodeServiceImpl.findByExample( NodeServiceImpl.java:264)


    Anyone can tell why @Transactional is not working? It seems I m missing some very fine point here.

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    Please use [ code][/code ] tags that way it remains readable!!! !!!

    You retrieve your node object in a different transaction and thus different session. THat is not going to work, regardless the @Transactional.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3

    Default

    Even with propagation REQUIRED it won't work? I think with propagation REQUIRED it either uses current transaction or creates a new one.

    Ok so what should i do then for getting above functionality?

    BTW sorry about the [code] tag didn't knew it, will take care of it in future.

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    As I stated you are retrieving it in a different transaction and thus session. Regardless of which transaction setting. This only works in the same tx and same session. Not if you use method call1 to retrieve it and method call 2 to do some processing (unless both are wrapped in the SAME transaction).

    Pass the id to the method retrieve it inside the method and do the processing.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  5. #5

    Default

    unless both are wrapped in the SAME transaction
    Can you explain this in a bit detail?

    Pass the id to the method retrieve it inside the method and do the processing
    This will work but it is dirty as it would mean 2 queries to db from application which is not good for performance. There has to be a way to do it in same transaction. I know there is a way because i have used it some time back and now i have forgotten and have no access to previous code. It was Spring2 though.

  6. #6

    Default

    @Transactional javadoc says it can be applied to TYPE as well which means does it have any difference if I put @Transactional to my service class itself.

    Let me try that.

  7. #7

    Default

    As I stated you are retrieving it in a different transaction and thus session
    So according to you this should work:

    Code:
    @Override
    	@Transactional(propagation = Propagation.REQUIRED)
        public List<NodeVO> findByExample(NodeVO nodeVO)
    	{
    		// TODO Auto-generated method stub
    		Node exampleNode = new Node();
    		this.convertToNode(nodeVO, exampleNode);
    		List<Node> nodes = appDAO.findByExample(exampleNode);
    		System.out.println(nodes.get(0).getLinks1()); //this time error here despite that it is in same transaction....
    		NodeVO nodeVOTemp = null;
    		if (nodes == null || nodes.size() == 0)
    			return null;
    		List<NodeVO> nodeVOs = new ArrayList<NodeVO>(nodes.size());
    		for (Node nodeTemp : nodes)
    		{
    			nodeVOTemp = new NodeVO();
    			this.convertToNodeVO(nodeTemp, nodeVOTemp);
    			nodeVOs.add(nodeVOTemp);
    		}
    
    		return nodeVOs;
    	}

    But it does not. Again same exception. There is some definite trouble with @Transactional or something very minor that I (we) are missing. Used to work well in Spring2. Not sure what additional is to be done with spring3 to make it work.

    And putting @Transactional on service class does not work either.

  8. #8
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    Post your stacktrace, and how are you testing/calling this?
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  9. #9

    Default

    I am calling this service from a Spring Webflow backing bean. Actually on jsf page an inputText component has validator attribute set to a method in backing bean. This backing bean calls the service method to check if user entered value is unique or not and if not unique then show error to user.
    and following is the complete stack trace:

    Following is the portion of backing bean where it is called:

    Code:
    public void validateUserId(javax.faces.context.FacesContext context, javax.faces.component.UIComponent comp, Object value)
    	{
    	    this.nodeService = NodeServiceImpl.getNodeService();
    	    if(!this.isUserIdUniqueInDB((String)value))
    	    {
                context.addMessage(comp.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR,"Invalid User ID","Node with this User ID already exists.\nPlease use a unique User ID."));
                ((RichInputText)comp).setValid(false);
    	    }
    	}
    
    private boolean isUserIdUniqueInDB(final String userId)
    	{
    	    NodeVO temp = new NodeVO();
            temp.setExternalNodeId(userId);
            List<NodeVO> exist = this.nodeService.findByExample(temp); //this is where trouble is when service is called
            if(this.operation == EEntityOperation.INSERT && exist != null && exist.size() > 0)
                return false;
            
            //in case of update need to check if any other node has this user id and since user id HAS to be unique
            //and Not-Null; so exist will at max have ONLY 1 item in it.
            //so check if that is different from current or not
            if(this.operation == EEntityOperation.UPDATE && exist != null && exist.size() == 1 && !exist.contains(this.nodeVo))
                    return false;            
            return true;
    	}
    And attached is stack trace as this editor is not allowing me to put more than 10000 characters. (stacktrace1.txt & stacktrace2.txt)
    Attached Files Attached Files

  10. #10
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    There is a proxy created but there is nothing transactional. What makes me shudder is the way you get the service... What does that static method do??? I sincerly hope it doesn't create a new applicationcontext. (I suggest you readup on spring and jsf and how to integrate those 2 technologies correctly).

    Make sure your tx:annotation-driven is in the context the services are defined in, else your tx:annotation-driven is, well, pretty much useless. Bean(Factory)PostProcessors only operate on the context they are loaded in.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •