私は次のビジネスモデルを持っています:
食事-名前と価格が含まれています
メニュー-名前と食事のセット、およびその金額と代替価格(通常はデフォルト価格よりも低い)が含まれています。
過去に、私はを使用して同様の問題を解決しHashMap<Entity, Value>
ました。この場合、価格と金額の2つの値があります。JavaとJPAはマルチマップをサポートしていないため、同じキーを含む2つのHashMapを使用することにしました。
@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>();
}
生成されたテーブルは正常に見えます:MENU_ID、MEAL_ID、AMOUNT、PRICE。
このように(エンティティ内のメソッドで)新しい食事をメニューに追加し、それを切り離した状態で追加します(食事をすぐにDBに保存したくない-GUIプレビューが最初に来ます):
menu.prices.add(meal, price);
menu.amounts.add(meal, amount);
切り離されたメニューに十分な食事を追加し、「OK」ボタンをクリックすると、私のメニューがマージされます。
操作はem.merge(menu)
次のSQLにマップされます。
insert into MENU_MEAL (MENU_ID, MEAL_ID, PRICE) values (?, ?, ?)
insert into MENU_MEAL (MENU_ID, MEAL_ID, AMOUNT) values (?, ?, ?)
そしてここに問題があります。主キー制約違反の例外が発生します。2番目の呼び出しでは、(MENU_ID、MEAL_ID)エントリを更新する必要があります。代わりに、同じ外部キーを使用して新しいエントリを挿入しようとします。
「update-if-exists-insert-otherwise」を強制する方法について何か提案はありますか?
各HashMapを異なるテーブルにマッピングすることで、問題を一時的に修正しました。しかし、私はその解決策が好きではありません。
編集:このように動作するには、マージが必要です:
insert into MENU_MEAL (MENU_ID, MEAL_ID, PRICE) values(?, ?, ?) on duplicate key update PRICE=values(price)
それを達成する方法はありますか?