views:

937

answers:

3

I have a products objects which belongs to certain categories i.e. classical many to one relationship.

@Entity
public class Product{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;

    String name;
    Double price;
    @ManyToOne(fetch = FetchType.LAZY)
    Category category;
...
}

@Entity
public class Category implements Identifiable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
...
}

I want to insert and update products without preselecting categories. Like this:

Product product = dao.get(productId);
Category category = dao.get(categoryId);
product.setCategory(category);
dao.update(product);

or

Product product = new Product(somename);
Category category = dao.get(categoryId);
product.setCategory(category);
dao.insert(product);

Is it possible to update and insert without category selecting? I don't want to use HQL or direct queries for that.

+2  A: 

Hibernate needs a safe way to determine the state of your object. That's why it's going a long way to make sure you can't mix objects from different sessions (so you can't load the categories at startup and then just use them later).

The solution is to load the categories at startup, set up a caching provider like ehcache for this class and then use this code:

Product product = new Product(somename);
product.setCategory(session.merge(category));

That won't cause any DB round trips if you configure the cache that category instances can't change.

Aaron Digulla
+3  A: 

session.load() exists specifically for cases like this. The following:

Category category = session.load(categoryId);
product.setCategory(category);

will not hit the database. It will, however, throw an exception at a later stage (during flush, more or less) if there is no category available with given id.

Using load() is faster than merge() and has no side-effects (cascading, etc...)

ChssPly76
A: 

I've just tried following:

Category category = new Category(categoryId);
product.setCategory(category);

And it worked, i mean product record in db got correct link to category and category with id

categoryId

haven't changed.

Vladimir
The problem with this approach is you're creating a new instance of persistent entity with the same identifier. It may have worked for you this time because `Category` in question was not associated with **current** session; if it were, Hibernate would throw an exception. It's also dangerous in terms of data integrity; if you were to specify cascading for your many-to-one on `category`, the above code would overwrite your original category with all blank values (or fail with constraint violation error)
ChssPly76
Hm, I had a sense that I'm doing something nasty here. Thanks for clarification.
Vladimir