Results 1 to 5 of 5

Thread: 2 many-to-one relationships, stack overflow error

  1. #1
    Join Date
    Feb 2005
    Posts
    3

    Default 2 many-to-one relationships, stack overflow error

    Hi all,
    I am new to hibernate and spring and I've tried to model my code after the petclinic example and the hibernate book.
    I have a class Prof that has one-to-many relationship with class Pattern. I have another class Type that also has one-to-many relationship with class Pattern. Pattern has 2 many-to-one relationships with Type and Prof. I am getting a stack overflow exception when I try to save a pattern. Inside the Prof and Type POJOs, I declared Set patterns. Before I save the Pattern, I try to add the pattern to the set in Prof and the set in Type. The exception occurs when I try to add the pattern to the second set. It doesn't matter which one I add first, I switched the order and it always occurs on the second time I try to add. Does anyone have any idea what I am doing wrong? Any help is appreciated!
    Here is the table structure:
    Table Prof
    pro_id PK

    Table Type
    type_id PK

    Table Pattern
    pat_id PK
    pro_id FK
    type_id FK

    Below is the mapping file, pojo's and code. I followed the petclinic example and the hibernate book to get this code.

    Hibernate Mapping
    Code:
    <hibernate-mapping>
    <class name="Prof" table="prof" >
            <id name="pro_id" column="pro_id" type="java.lang.Integer">
                <generator class="increment">
                </generator>
            </id>
    
            <set name="patterns" inverse="true" >
                  <key column="pro_id"></key>
                  <one-to-many class="Pattern"/>
            </set> 
    </class>
    
    <class name="Pattern" table="pattern" >
            <id name="pat_id" column="pat_id" type="java.lang.Integer">
                <generator class="increment"></generator>
            </id>
            <many-to-one name="prof" class="Prof" column="pro_id" />
            <many-to-one name="type" class="Type" column="type_id" />
    </class>
    
    <class name="Type" table="type" >
            <id name="type_id" column="type_id" type="java.lang.Integer">
                <generator class="increment"></generator>
            </id>
            <set name="patterns" inverse="true" >
                  <key column="type_id"></key>
                  <one-to-many class="Pattern"/>
            </set>
    </class>
    </hibernate-mapping>
    snippet of test case:
    Code:
    ...get prof from db...
    ...get typ from db...
    
    pattern = new Pattern&#40;&#41;
    ...set pattern properties...        
    typ.addPattern&#40;pattern&#41;;
    prof.addPattern&#40;pattern&#41;; <--second time add pattern to a set, stack overflow&#40;see Prof POJO&#41;
    dao.savePattern&#40;pattern&#41;;
    POJO's
    Code:
    public class Prof extends BaseObject&#123;
      private Integer pro_id;
      private Set patterns;
    ...
      public Set getPatterns&#40;&#41; &#123;
    		if &#40;this.patterns == null&#41;&#123;
    			this.patterns = new HashSet&#40;&#41;;			
    		&#125;
    		return this.patterns;
    	&#125;
    	
    	public void setPatterns&#40;Set patterns&#41; &#123;
    		this.patterns = patterns;
    	&#125;
    	public void addPattern&#40;Pattern ptn&#41;&#123;
    		getPatterns&#40;&#41;.add&#40;ptn&#41;; <--this line causes stack overflow
    		ptn.setProf&#40;this&#41;;
    	&#125;
        &#125;
    
    public class Pattern extends BaseObject &#123;
        private Integer pat_id;
        private Prof prof;
        private Type typ;
    ...
       public Prof getProf&#40;&#41; &#123;
    		return prof;
    	&#125;
    	
    	public void setProf&#40;Prof prof&#41; &#123;
    		this.prof = prof;
    	&#125;
    	public Type getType&#40;&#41; &#123;
    		return typ;
    	&#125;
    	
    	public void setType&#40;Type typ&#41; &#123;
    		this.typ = typ;
    	&#125;	
    &#125;
    
    public class Type extends BaseObject&#123;
       private Integer type_id;
       private Set patterns;
    ...                
       public Set getPatterns&#40;&#41; &#123;
    		
    		if &#40;this.patterns == null&#41;&#123;
    			this.patterns = new HashSet&#40;&#41;;			
    		&#125;
    		return this.patterns;
    	&#125;
    	
    	public void setPatterns&#40;Set patterns&#41; &#123;
    		this.patterns = patterns;
    	&#125;
    	public void addPattern&#40;Pattern ptn&#41;&#123;
    		getPatterns&#40;&#41;.add&#40;ptn&#41;;
    		ptn.setType&#40;this&#41;;
    	&#125;
    &#125;
    thanks in advance.
    pat

  2. #2
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    You are going into a infinite loop(that's what StackOverFlow usually stand for). Can you post also the code for BaseObject - what usually happens in this case is having objects A and B with A trying to set automatically the relation with B and B doing the same thing with A.
    In short:

    1 add B to A will make
    2. B add automatically a relation to A (through some logic inside the setter)
    which tries to do 1.

    Put some logging inside your code or use a debugger if you cannot spot the loop.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  3. #3
    Join Date
    Feb 2005
    Posts
    3

    Default

    Costin
    Thanks for your reply. The BaseObject I am using is the one that came with equinox when I did the Spring Quick Start Tutorial. I will post that code below. Do you know how I should model these relationships?
    Code:
    public class BaseObject implements Serializable &#123;
        public String toString&#40;&#41; &#123;
            return ToStringBuilder.reflectionToString&#40;this,
                    ToStringStyle.MULTI_LINE_STYLE&#41;;
        &#125;
    
        public boolean equals&#40;Object o&#41; &#123;
            return EqualsBuilder.reflectionEquals&#40;this, o&#41;;
        &#125;
    
        public int hashCode&#40;&#41; &#123;
            return HashCodeBuilder.reflectionHashCode&#40;this&#41;;
        &#125;
    &#125;
    thanks
    pat

  4. #4
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    Sorry for the delay - I was traveling.
    EqualsBuilder and HashCodeBuilders when used with reflection methods are dangerous - remove them and implement your own hashcode and equals builder.
    Your code goes into an infinite loop because when you add the BaseObject to a set, the Set implementation checks for duplicates (meaning equals). However EqualsBuilder will try to compute one based on the object properties - so if A has a member B the EqualsBuilder for A will call equals for B which is actually EqualsBuilder again which calss equals for A and so on.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  5. #5
    Join Date
    Feb 2005
    Posts
    3

    Default

    I changed my java classes to implement Serializable instead of extending the BaseObject. Everything is working now. Thank you so much for your help.
    pat

Similar Threads

  1. ERROR: Context initialization failed
    By makhlo in forum Architecture
    Replies: 8
    Last Post: Jul 11th, 2008, 01:41 AM
  2. Context initialization failed
    By kanonmicke in forum Container
    Replies: 7
    Last Post: Sep 29th, 2005, 12:35 AM
  3. could not satisfy dependencies
    By springuser in forum Container
    Replies: 4
    Last Post: Apr 26th, 2005, 01:15 PM
  4. Replies: 1
    Last Post: Apr 25th, 2005, 07:37 PM
  5. Replies: 4
    Last Post: Nov 5th, 2004, 03:59 AM

Posting Permissions

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