0

I'm just starting to use Hibernate and I was wondering how to insert a new element into a oneToMany relation without loading the container first.

Consider the following example:

@Entity
@Table(name="orders")
class Order {
    @Id @GeneratedId
    public Long id;
    @OneToMany(mappedBy="order")
    public List<Item> items = new ArrayList<Item>();
}

@Entity
@Table(name="items")
class Item {
    @Id @GeneratedId
    public Long id;
    @ManyToOne
    public Order order;
}

I want to insert a new Item into an Order (I know the order's id and that it is valid), but I do not want to load the order first. Clearly, this should be possible, as the SQL only needs the id for the insert and not the entire Order object.

Konstantin Weitz
  • 6,180
  • 8
  • 26
  • 43

4 Answers4

2

You should be able to do this easily all within Hibernate.

Item item - new Item();
Order order = new Order();
order.setId(order_id);
item.setOrder(order);
em.persist(item);

Make sure you have your cascade property set correctly on your order property in your Item entity. If you don't you may end up changing the values in Order inadvertently.

@ManyToOne(cascade=CascadeType.PERSIST) 

should be OK. It will only allow changes to orders from the item side if the order does not exist already.

As an aside you may want to think about this relationship as a ManyToMany since it makes sense to have Items on multiple Orders.

James DW
  • 1,815
  • 16
  • 21
  • If I am understanding it correctly, this method is not really something you should do. In Hibernate, we only expect only one instance of entity with same identifier exists in session. Though you are tricking Hibernate and it works this time, it is not something guaranteed to work in other version as it is against Hibernate's design. Who knows when will Hibernate add extra checking on entity validness in similar scenario? – Adrian Shum Jun 19 '12 at 01:44
1

I don't think you can, Hibernate will need to have the Order in session/context before you can add an item to it. i.e. Hibernate will need to 'know' the items order.

enkor
  • 7,527
  • 3
  • 31
  • 55
1

"Luckily" you are not having any cascade policy, and the dependency is set on Item side.

You can use session.load() to load the user with the ID you want. load() method will return a proxy in case it is not found in session. That is useful when you want to set the dependency without going to db to fetch the entity.

it looks something like:

Order order = session.load(Order.class, orderId);  // no DB call
Item item = new Item(); 
item.setOrder(order);
// set other attributes of item
session.save(item);

For difference of load() and get(), please refer to Hibernate: Difference between session.get and session.load

Community
  • 1
  • 1
Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
0

You can do that by creating a new Item without an Order, persist it and then update the order_id value from the new Item using a native query.

tibtof
  • 7,857
  • 1
  • 32
  • 49