Reputation: 103477
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;
}
}
Upvotes: 1
Views: 1076
Reputation: 72840
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).
Upvotes: 1