Announcement Announcement Module
Collapse
No announcement yet.
2 many-to-one relationships, stack overflow error Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    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.

    Comment


    • #3
      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

      Comment


      • #4
        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.

        Comment


        • #5
          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

          Comment

          Working...
          X