-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 
Author Message
 Post subject: Really struggling with inverse - have read docs!!
PostPosted: Wed Jul 21, 2004 7:54 am 
Regular
Regular

Joined: Fri Jul 16, 2004 3:04 pm
Posts: 52
Location: Wiltshire UK
Hi, I am really struggling to understand how the inverse property in the mapping affects many-to-many (or even one-to-many relationships). I don't really understand the bit about changes will only be persisted if they are made to the primary end of the relationship. I have written a test case to try & work this out, but it doesn't seem to uphold what I thought I understood. I have spent the last couple of weeks looking at the documentation & reading the forum, but just can't seem to get my head around it. Please could someone have a look at my code here & try to explain the inverse attribute & it's effects to me? There is a comment in the JUnit test where I change the parent name to MUM & I thought it wouldn't propogate to the child, but it does!! I'm thoroughly confused by this concept & could do with some simple example of what changes will & won't be propogated from each end of the relationship.

Many thanks
Paul :-)

code follows:
Parent mapping
Code:
<class name="Parent">
        <id name="id" type="int">
            <generator class="native"/>
        </id>

        <property name="name" unique="true" type="string"/>

        <set name="children" table="parent_child" inverse="true" cascade="all-delete-orphan">
            <key column="child_id"/>
            <many-to-many column="parent_id" class="Child"/>
        </set>
    </class>


Parent class
Code:
// default package

import java.io.Serializable;
import java.util.Set;
import org.apache.commons.lang.builder.ToStringBuilder;


/** @author Hibernate CodeGenerator */
public class Parent implements Serializable {

    /** identifier field */
    private Integer id;

    /** nullable persistent field */
    private String name;

    /** persistent field */
    private Set children;

    /** full constructor */
    public Parent(String name, Set children) {
        this.name = name;
        this.children = children;
    }

    /** default constructor */
    public Parent() {
    }

    /** minimal constructor */
    public Parent(Set children) {
        this.children = children;
    }

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set getChildren() {
        return this.children;
    }

    public void setChildren(Set children) {
        this.children = children;
    }

    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Parent)) return false;

        final Parent parent = (Parent) o;

        if (!name.equals(parent.name)) return false;

        return true;
    }

    public int hashCode() {
        return name.hashCode();
    }

    public String toString() {
        final StringBuffer buf = new StringBuffer();
        buf.append("Parent");
        buf.append("{id=").append(id);
        buf.append(",name=").append(name);
        buf.append('}');
        return buf.toString();
    }


}


Child mapping
Code:
<class name="Child">
        <id name="id" type="int">
            <generator class="native"/>
        </id>

        <property name="name" unique="true" type="string"/>

        <set name="parents" table="parent_child" cascade="save-update">
            <key column="parent_id"/>
            <many-to-many column="child_id" class="Parent"/>
        </set>

        <set name="grandchildren" table="child_grandchild" inverse="true" cascade="all-delete-orphan">
            <key column="grandchild_id"/>
            <many-to-many column="child_id" class="Grandchild"/>
        </set>

    </class>


Child class
Code:
// default package

import java.io.Serializable;
import java.util.Set;
import org.apache.commons.lang.builder.ToStringBuilder;


/** @author Hibernate CodeGenerator */
public class Child implements Serializable {

    /** identifier field */
    private Integer id;

    /** nullable persistent field */
    private String name;

    /** persistent field */
    private Set parents;

    /** persistent field */
    private Set grandchildren;

    /** full constructor */
    public Child(String name, Set parents, Set grandchildren) {
        this.name = name;
        this.parents = parents;
        this.grandchildren = grandchildren;
    }

    /** default constructor */
    public Child() {
    }

    /** minimal constructor */
    public Child(Set parents, Set grandchildren) {
        this.parents = parents;
        this.grandchildren = grandchildren;
    }

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set getParents() {
        return this.parents;
    }

    public void setParents(Set parents) {
        this.parents = parents;
    }

    public Set getGrandchildren() {
        return this.grandchildren;
    }

    public void setGrandchildren(Set grandchildren) {
        this.grandchildren = grandchildren;
    }

    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Child)) return false;

        final Child child = (Child) o;

        if (!name.equals(child.name)) return false;

        return true;
    }

    public int hashCode() {
        return name.hashCode();
    }

    public String toString() {
        final StringBuffer buf = new StringBuffer();
        buf.append("Child");
        buf.append("{name=").append(name);
        buf.append(",id=").append(id);
        buf.append('}');
        return buf.toString();
    }


}


Junit Test
Code:
import junit.framework.TestCase;
import net.sf.hibernate.Session;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Transaction;

import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;

/**
* Date: 21-Jul-2004
*/
public class HibernateTest extends TestCase {

    public void testParentChild(){
        try {
            Session session = null;
            Transaction tx = null;
            try {
                //create parent
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                Parent parent = new Parent("DAD",new HashSet());
                session.save(parent);
                tx.commit();
                session.close();

                // add child
                Child child = new Child("KATHERINE",new HashSet(),new HashSet());
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                child.getParents().add(parent);
                parent.getChildren().add(child);
                session.save(child);
                tx.commit();
                session.close();

                // check child is there
                Set children = parent.getChildren();
                assertTrue(children.size() == 1);
                Iterator iterator = children.iterator();
                Child childFromParent = null;
                if (iterator.hasNext()) {
                    childFromParent = (Child) iterator.next();
                }
                assertEquals(child,childFromParent);

                // change parent name
                parent.setName("MUM");
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                session.update(parent);
                tx.commit();
                session.close();

                Parent parentFromChild = null;
                Set parents = child.getParents();
                iterator = parents.iterator();
                if (iterator.hasNext()) {
                    parentFromChild = (Parent) iterator.next();
                }
                assertFalse(parentFromChild.getName().equals("MUM")); // this should fail as I updated it from the inverse end


                // remove child
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                Integer parentId = parent.getId();
                Integer childId = child.getId();
                assertTrue(child.getParents().remove(parent));
                assertTrue(parent.getChildren().remove(child));
                session.update(parent); // save parent here even though it is inverse member of relationship as this
                                       //   will cause cascade-delete-orphan to work
                tx.commit();
                session.close();

                // check child has been removed
                children = parent.getChildren();
                assertTrue(children.size() == 0);
                session = HibernateSessionFactory.getSession();
                try {
                    session.load(Child.class, childId);
                    fail("This object should no longer exist");
                }
                catch (HibernateException e) {
                    assertTrue(true);
                }
                session.close();

                // add new child
                child = new Child("GRACE",new HashSet(),new HashSet());
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                child.getParents().add(parent);
                parent.getChildren().add(child);
                session.save(child);
                tx.commit();
                session.close();

                // check child is there
                children = parent.getChildren();
                assertTrue(children.size() == 1);
                iterator = children.iterator();
                if (iterator.hasNext()) {
                    childFromParent = (Child) iterator.next();
                }
                childId = childFromParent.getId();
                assertEquals(child, childFromParent);

                // delete parent
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                session.delete(parent);
                tx.commit();
                session.close();

                // ensure parent & child have been deleted
                session = HibernateSessionFactory.getSession();
                try {
                    session.load(Parent.class, parentId);
                    fail("This object should no longer exist");
                }
                catch (HibernateException e) {
                    assertTrue(true);
                }
                try {
                    session.load(Child.class, childId);
                    fail("This object should no longer exist");
                }
                catch (HibernateException e) {
                    assertTrue(true);
                }
                session.close();


            }
            catch(HibernateException e){
                tx.rollback();
                throw e;
            }
            finally {
                if(session != null){
                    session.close();
                }
            }
        }
        catch (HibernateException e) {
            fail(e.getMessage());
        }
    }
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 21, 2004 8:09 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Did you give a chance to this one http://www.hibernate.org/155.html

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 21, 2004 8:25 am 
Regular
Regular

Joined: Fri Jul 16, 2004 3:04 pm
Posts: 52
Location: Wiltshire UK
Hi Emmanuel, thanks for the quick reply. Yes I did read that one!
Sorry ,but I just don't get it! (& people say CMP is complicated - LOL).
I have found now, that having added the code to change the Parent name (changing assertFalse(parentFromChild.getName().equals("MUM")); to assertTrue(parentFromChild.getName().equals("MUM")); so it doesn't fail there ) the code now fails on this line, assertTrue(child.getParents().remove(parent));. It worked fine before I added the section to change the Parent name. I have since tried several different ways to change the Parent name, getting it from the Child collection, saving the Child, saving the Parent & I just can't make it work. It may just be me being dumb :-( but the examples seem to show adding related Objects to collections, but nothing shows how to correctly mutate values. I've spent a great many frustrating hours struggling with this & am on the verge of giving up & going back to CMP ;-)

A simple example would be greatly appreciated :-)

Many Thanks
Paul


Top
 Profile  
 
 Post subject: Surely this breaks Collections contract??
PostPosted: Wed Jul 21, 2004 9:19 am 
Regular
Regular

Joined: Fri Jul 16, 2004 3:04 pm
Posts: 52
Location: Wiltshire UK
Hi, I also do not understand in the above code why the line child.getParents().remove(parent) returns false, when if I insert the line assertEquals(parent,parentFromChild); above it this returns true!!

Also if I insert the following
Code:
Set tempParents = child.getParents();
                Iterator tmpIt = tempParents.iterator();
                while (tmpIt.hasNext()) {
                    Parent tmpParent = (Parent) tmpIt.next();
                    System.out.println(tmpParent);
                    System.out.println(parent);
                }


The child's parent collection shows that it contains the parent object & that their id's and names are identical. My equals & hashCode methods both use name, so as far as I can see the child.getParents().remove(parent) should return true, otherwise it would seem to be breaking the contract for the Collection Interface!

Thanks
Paul


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 27, 2004 5:10 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Post 10 lines of code showing your pb, and I'll check it.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 27, 2004 5:23 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
And Hibernate delegate the collection.remove(Object) result to a JDK collection. So unless your JDK is buggy...

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 27, 2004 5:37 am 
Regular
Regular

Joined: Tue Oct 28, 2003 8:25 am
Posts: 72
Location: Belgium
This is a problem with equals/hashcode and collections mis-use.

Look at this:

Code:
parent.getChildren().add(child);
...
parent.setName("MUM");
...
assertTrue(child.getParents().remove(parent));


getChildren() returns a HashSet. This means that the hashcode value of the parent object is used to get it back, meaning that remove() needs the hashcode value of the parent object.

Between add() and remove, you've changed the hashcode value because of the setName() -> the set cannot find it back and returns false without removing it.

assertEquals(parent,parentFromChild) returns true simply because these are two references on the same object.

Very tricky but quite common mis-use of the collections framework.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 28, 2004 5:10 pm 
Regular
Regular

Joined: Fri Jul 16, 2004 3:04 pm
Posts: 52
Location: Wiltshire UK
Thanks both of you. I was using the id initially in my equals()/hashCode(), but then changed it to name after reading the article on equals()/hashCode() but continued to change the name as part of my test! D'uh!

I have now figured that part out. I just have to experiment a bit to see how inverse="true" & the cascade attribute works.

Thanks once again for your help. :-)

It does seem like a lot of new users struggle with the collections support. It would be good to have a really good simple example, with a JUnit test, available somewhere on the site, with Parent/Child/Grandchild relationships & showing what changes will & won't be persisted. Maybe I'll be able to provide one if I ever work it out myself :-)

Paul


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 28, 2004 5:11 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Try http://caveatemptor.hibernate.org/, the 'eg' package in Hibernate, or the unit tests in Hibernate.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 29, 2004 4:11 am 
Regular
Regular

Joined: Fri Jul 16, 2004 3:04 pm
Posts: 52
Location: Wiltshire UK
Thanks Christian, I'll look at those, but they still seem a lot to go through to learn what should be a simple concept. The fact that so many people have problems understanding this relationship, seems to me to be indicating that perhaps the documentation isn't quite clear enough.

This is what I don't understand. I thought that if I marked one side of the relationship as inverse, that I then only needed to add to the primary side of the relationship & Hibernate automatically added to the inverse side, the only issue being that changes made to the inverse side would not be persisted.

So I don't understand why in the following code the last assert returns false. Surely the Parent should have been added to the Child as the Child is marked as the inverse side of the relationship.

Code:
<set name="children" table="parent_child" cascade="all-delete-orphan">
        <key column="child_id"/>
         <many-to-many column="parent_id" class="Child"/>
</set>


Code:
<set name="parents" table="parent_child" inverse="true" cascade="save-update">
          <key column="parent_id"/>
          <many-to-many column="child_id" class="Parent"/>
</set>


Code:
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                Parent parent = new Parent("DAD","DAD2",new HashSet());
                session.save(parent);
                tx.commit();
                session.close();

                // add child
                Child child = new Child("KATHERINE", "CHILD3",new HashSet(),new HashSet());
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                parent.getChildren().add(child);
                session.saveOrUpdate(parent);
                tx.commit();
                session.close();

                //set ids for later
                Integer parentId = parent.getId();
                Integer childId = child.getId();

                // check child is there
                Set children = parent.getChildren();
                assertTrue(children.size() == 1);
                assertTrue(children.contains(child));
                Iterator iterator = children.iterator();
                Child childFromParent = null;
                if (iterator.hasNext()) {
                    childFromParent = (Child) iterator.next();
                }
                assertEquals(child,childFromParent);

                // check Parent exists in Child's collection
                Parent parentFromChild = null;
                Set parentsFromChild = child.getParents();
                iterator = parentsFromChild.iterator();
                if (iterator.hasNext()) {
                    parentFromChild = (Parent) iterator.next();
                }
                assertNotNull(parentFromChild);


Top
 Profile  
 
 Post subject: I think I may have it :-)
PostPosted: Thu Jul 29, 2004 4:35 am 
Regular
Regular

Joined: Fri Jul 16, 2004 3:04 pm
Posts: 52
Location: Wiltshire UK
I think the problem may be this section of the Hibernate Developers Notebook (O'Reilly) by James Elliott.

Quote:
"... we made this association bidirectional - the Artist class has a collection of Track associations too. We didn't bother to store anything in there. The great news is that we don't have to. Because of the fact that we marked this as an inverse mapping in the Artist mapping document, Hibernate understands that when we add an Artist association to a Track, we're implicitly adding that Track as an association to the Artist at the same time."


I don't think that this is correct, someone please correct me if I'm wrong!

I think that the developers notebook is incorrect here & that you do have to add to the collection on both sides. I think that 'inverse="true", has nothing to do with the pure Java relationships, but only affects the way that the mappings between the related Objects takes place & so if you change the relationship & do a save(or update) on the inverse side, the relationship will not be updated, however, if you save (or update) on the primary side the relationship change will be persisted. I think this section from the Hibernate documentation explains it.

http://www.hibernate.org/155.html
Inverse defines which side is responsible of the association maintenance. The side having inverse="false" (default value) has this responsibility (and will create the appropriate SQL query - insert, update or delete). Changes made to the association on the side of the inverse="true" are not persisted in DB.

Inverse attribute is not related in any way to the navigation through relationship. It is related to the way hibernate generate SQL queries to update association data.

Is my understanding correct here?

Many Thanks
Paul

p.s. Just wanted to say that the support & responses in this forum are excellent! Many thanks to all of the people who give their time to help us struggling Hibernate newbies :-)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 29, 2004 6:06 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
DON'T READ THE O'REILLY BOOK WITHOUT DOUBLE CHECKING EVERYTHING THE AUTHOR SAYS WITH THE HIBERNATE REFERENCE DOCUMENTATION!

Sorry for shouting, but it will be a nightmare to correct all the mistakes the author made in this forum. This is not exactly how we should spend your time.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 29, 2004 7:45 am 
Regular
Regular

Joined: Fri Jul 16, 2004 3:04 pm
Posts: 52
Location: Wiltshire UK
Hi Christian, no problem with the shouting :-) The trouble with being a newbie to Hibernate & double checking the stuff from the book against the documentation, is that the relationship stuff in Hibernate is quite complex when you start using inverse="true", cascades & extended transactions using multiple sessions (which I need to do as it is a web application I am porting). The thinking has to be quite different from EJB2 CMP moving to Hibernate.

I have put a page on our wiki at work containing the following information, which has helped us to understand more clearly. I wonder if it might be useful to have on the HIbernate site, or I can host it & provide a URL. I wonder if someone would be kind enough to check it for me & let me know if you thought it would be useful :-)

Thanks
Paul

many-to-many Hibernate relationship
Explanation of 'inverse="true"' from http://www.hibernate.org/155.html
Quote:
'Inverse defines which side is responsible of the association maintenance. The side having inverse="false" (default value) has this responsibility (and will create the appropriate SQL query - insert, update or delete). Changes made to the association on the side of the inverse="true" are not persisted in DB.
Inverse attribute is not related in any way to the navigation through relationship. It is related to the way hibernate generate SQL queries to update association data.'


Because we have cascade="save-update" on the Child's relationship to the Parent, save will be called on the Parent, even when we only save the Child, therefore the primary (inverse="false") side of the relationship is saved & so all relationships are updated. Thus we can safely update either side of the relationship, as save will always be called on the primary relationship. (If we did not have the cascade="save-update" on the Child's relationship to the Parent we would have to ensure that we always saved on the Parent side of the relationship or the relationship table would not get updated.)
This can be tested by adding the following code to the test case

Code:
Child child2 = new Child("GRACE","CHILD2", new HashSet(), new HashSet());
                child2.getParents().add(parent);
                parent.getChildren().add(child2);
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                session.saveOrUpdate(child2);// this should end up not being persisted
                tx.commit();
                session.close();
                // check to see Child relationship to Parent wasn't persisted
                session = HibernateSessionFactory.getSession();
                loadedParent = (Parent) session.load(Parent.class,parentId);
                session.close();
                parentsFromChild = loadedParent.getChildren();
                assertTrue(parentsFromChild.size() == 1);
                assertFalse(parentsFromChild.contains(child2));
and modifying the Child mapping file by removing the cascade="save-update" attribute.

Note that Hibernate Developer's Notebook end of page 71 - start of page 72 is incorrect, you do need to add to both sides of the relationship. The inverse="true" attribute has nothing to do with the pure Java releationships, it only relates to how the sql is generated to update the relationship tables

It is also important to understand how to correctly implement equals() & hashCode() for use with Hibernate persistent classes. See http://www.hibernate.org/109.html


relationship mapping sections from Parent & Child classes

from Parent mapping file
Code:
<set name="children" table="parent_child" cascade="all-delete-orphan">
      <key column="child_id"/>
      <many-to-many column="parent_id" class="Child"/>
</set>

from Child mapping file
Code:
<set name="parents" table="parent_child" inverse="true" cascade="save-update">
       <key column="parent_id"/>
       <many-to-many column="child_id" class="Parent"/>
</set>


JUnit test method
Code:
public void testParentChild(){
        try {
            Session session = null;
            Transaction tx = null;
            try {
                //create parent
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                Parent parent = new Parent("DAD","PARENT1",new HashSet());
                session.save(parent);
                tx.commit();
                session.close();

                // add child
                Child child = new Child("KATHERINE", "CHILD1",new HashSet(),new HashSet());
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                child.getParents().add(parent);
                parent.getChildren().add(child);
                session.saveOrUpdate(parent);
                tx.commit();
                session.close();

                //set ids for later
                Integer parentId = parent.getId();
                Integer childId = child.getId();

                // check child is there
                Set children = parent.getChildren();
                assertTrue(children.size() == 1);
                assertTrue(children.contains(child));
                Iterator iterator = children.iterator();
                Child childFromParent = null;
                if (iterator.hasNext()) {
                    childFromParent = (Child) iterator.next();
                }
                assertEquals(child,childFromParent);

                // now try changing Parent from Child side
                Parent parentFromChild = null;
                Set parentsFromChild = child.getParents();
                iterator = parentsFromChild.iterator();
                if (iterator.hasNext()) {
                    parentFromChild = (Parent) iterator.next();
                }
                assertNotNull(parentFromChild);
                parentFromChild.setName("MUM");
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                session.saveOrUpdate(parentFromChild);
                tx.commit();
                session.close();

                // check name changed & persisted OK
                session = HibernateSessionFactory.getSession();
                Parent loadedParent = (Parent) session.load(Parent.class,parentId);
                session.close();
                assertEquals("MUM",loadedParent.getName());

                // delete parent
                session = HibernateSessionFactory.getSession();
                tx = session.beginTransaction();
                session.delete(parent);
                tx.commit();
                session.close();

                // ensure parent & child have been deleted
                session = HibernateSessionFactory.getSession();
                try {
                    session.load(Parent.class, parentId);
                    fail("This object should no longer exist");
                }
                catch (HibernateException e) {
                    assertTrue(true);
                }
                try {
                    session.load(Child.class, childId);
                    fail("This object should no longer exist");
                }
                catch (HibernateException e) {
                    assertTrue(true);
                }
                session.close();
            }
            catch(HibernateException e){
                tx.rollback();
                throw e;
            }
            finally {
                if(session != null){
                    session.close();
                }
            }
        }
        catch (HibernateException e) {
            fail(e.getMessage());
        }
    }


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.