I have the following business model:
Meal - contains name and price
Menu - contains name and a set of Meals with their amounts and alternate prices (usually lower than default prices).
In the past I have solved similar problems using HashMap<Entity, Value>
. In this case, I have two values: price and amount. Since Java and JPA don't support multimaps, I decided to go with two HashMaps containing same keys.
@Entity
public class Menu {
@Column
private String name;
@ElementCollection
@CollectionTable(name = "MENU_MEALS", joinColumns = @JoinColumn(name = "MENU_ID"))
@MapKeyJoinColumn(name = "MEAL_ID", referencedColumnName = "ID")
@Column(name="AMOUNT")
private Map<Meal, BigDecimal> amounts = new LinkedHashMap<Meal, BigDecimal>();
@ElementCollection
@CollectionTable(name = "MENU_MEALS", joinColumns = @JoinColumn(name = "MENU_ID"))
@MapKeyJoinColumn(name = "MEAL_ID", referencedColumnName = "ID")
@Column(name="PRICE")
private Map<Meal, BigDecimal> prices = new LinkedHashMap<Meal, BigDecimal>();
}
The generated tables look fine: MENU_ID, MEAL_ID, AMOUNT, PRICE.
I add new Meals to Menus like this (in a method inside my entity), and I do it while it's detached (don't want to store Meals to DB right away - GUI preview comes first):
menu.prices.add(meal, price);
menu.amounts.add(meal, amount);
After adding enough Meals to the detached Menu and clicking an 'OK' button, my Menu is merged.
The em.merge(menu)
operation maps into following SQL:
insert into MENU_MEAL (MENU_ID, MEAL_ID, PRICE) values (?, ?, ?)
insert into MENU_MEAL (MENU_ID, MEAL_ID, AMOUNT) values (?, ?, ?)
And here lies the problem. I get a primary key constraint violation exception. The second call should update (MENU_ID, MEAL_ID) entry, instead trying to insert a new one with same foreign keys.
Any suggestions how to force it to do "update-if-exists-insert-otherwise"?
I have temporarily fixed the problem by mapping each HashMap to a different table. But I don't like that solution.
EDIT: I need my merge to behave like this:
insert into MENU_MEAL (MENU_ID, MEAL_ID, PRICE) values(?, ?, ?) on duplicate key update PRICE=values(price)
Any ideas how to achieve that?