views:

163

answers:

1

A many-to-many relationship.

The tables:

Product (productId, ...)
Category (categoryId, ...)
Product_Category(productId, categoryId)

I setup the relationship so all updates will be done via the Product entity.

Product Entity:

 private Set<Category> categories = new HashSet<Category>();





public void AddCategory(Category category)
    {
        if(!this.categories.contains(category))
            this.categories.add(category);

        if(!category.getProducts().contains(this))
            category.getProducts().add(this);        
    }

    public void RemoveCategory(AMCategory category)
    {

        if(categories.contains(category))
            categories.remove(category);

        if(category.getProducts().contains(this))
            category.getProducts().remove(this);       
    }

Product.hbm.xml

  <set name="categories" table="product_category" cascade="save-update" lazy="true">
    <key column="productId"/>
    <many-to-many column="categoryId" class="Category"/>
</set>

The Category entity:

private Set<Product> products = new HashSet<Product>();

 /**
     * @return the products
     */
    public Set<Product> getProducts() {
        return products;
    }

Category.hbm.xml:

<set name="Products" table="product_category" cascade="none" inverse="true" lazy="true">
        <key column="categoryId"/>
        <many-to-many column="productId" class="Product"/>
    </set>  

Now I have a loop where I am creating and saving Product entities, and also associating a single category to each.

The product_category table is empty, so I guess I have an issue with my mappings.

forloop
{
Product p = new Product();

// set all properties

Category c = DAO.GetCategory(someId);

p.AddCategory(c);


session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(p);
session.getTransaction().commit();

}

I also tried first saving the new product, then loading the newly inserted product, and then adding the category and then saving, but same result, the table product_category is empty.

The product table has inserted the new products.

What have I done wrong? There should be rows in both the product_category and product tables, but the product_category is empty.

Update

My HibernateUtil class:

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            Configuration configuration = new Configuration().configure();



            return configuration.buildSessionFactory();
        }
        catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }


}
+1  A: 

You must specify the inverse direction when mapping both sides of a relationship using the inverse attribute - cascade is something quite different. Hibernate needs to know which side of the relationship to use to persist the record in the link table (or the foreign key field in the case of a one-many/many-one mapped both ways).

David M
Does my helper method AddCategory look ok in the Product entity?
mrblah
Yes, absolutely. If you map both ways, you need to make sure you set this both ways as you are doing.
David M
ok now I am getting an error: SEVERE: failed to lazily initialize a collection of role: blah.Model.Product.categories, no session or session was closed
mrblah
i am wrapping everything in getcurrentsession, begintrasaction and then a commit, not sure why it can't find the session?
mrblah
You have already disposed your session, when you are still working with the objects. You need to keep the session alive for the duration of your unit of work, then close it and stop using the objects. If you close the session before a lazy-loaded object or collection is loaded, how does it know where to load from?
David M
Or, you are using multiple sessions when you should be using one - does getCurrentSession definitely return the session used by your DAO to retrieve categories?
David M
well I have: <property name="current_session_context_class">thread</property> not sure if that does it?
mrblah
I updated my question with the HibernateUtil class I am using.
mrblah