EntityManager.merge()
で非常に奇妙な動作が発生しています。ここで何が起こっているのですか?私は、MySQLデータベースから項目を挿入、更新、および削除するためのSpring MVC、Hibernate、およびJPAを備えたREST API設定を持っています。挿入機能と更新機能はどちらもEntityManager.merge()
を使用し、両方とも99%の時間で正常に機能します。EntityManagerのmerge()によって重複行が発生する
ただし、最初にレコードを更新するように呼び出された時点では、データベースにレコードの複製が作成され、元のレコードに戻り、必要な変更が加えられます。
私は本当になぜこれが起こっているのか迷っています。重複したレコードを作成した場合、そのレコードを編集することはできますが、更新では重複を作成して放棄し、変更を加えるために最初のレコードに戻ります。
エンティティBeanにハッシュコードと等価な設定がどのようにあるのかが原因であると考えていました。私はIDではなくユニークなキーに基づいているので、私は何か間違っているとは思えません。
私のコードは以下の通りです。何が起こっているかについてのアイデアは大きな助けになるでしょう。ここで
は、エンティティの:@Entity
@Table(name = "DAY_ITEM")
public class DayItem implements GtEntity, Serializable{
private Long id;
private String email;
private String name;
private BigDecimal amount;
private Integer modId;
private Integer fmOrder;
private String modName;
private Date daysDate;
private String daysDateString;
private Long foodId;
private Long mealId;
private FoodItem foodItem;
private MealItem mealItem;
private ArrayList<FoodItem> foodItems;
private ArrayList<MealItem> mealItems;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Basic
@Column(name = "EMAIL", nullable = false, length = 50)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Basic
@Column(name = "NAME", nullable = true, length = 100)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Basic
@Column(name = "AMOUNT", nullable = true)
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
@Basic
@Column(name = "MOD_ID", nullable = false)
public Integer getModId() {
return modId;
}
public void setModId(Integer modId) {
this.modId = modId;
}
@Basic
@Column(name = "FM_ORDER", nullable = false)
public Integer getFmOrder() {
return fmOrder;
}
public void setFmOrder(Integer fmOrder) {
this.fmOrder = fmOrder;
}
@Basic
@Column(name = "MOD_NAME", nullable = true, length = 50)
public String getModName() {
return modName;
}
public void setModName(String modName) {
this.modName = modName;
}
@Basic
@Column(name = "DAYS_DATE", nullable = false)
public Date getDaysDate() {
return daysDate;
}
public void setDaysDate(Date daysDate) {
this.daysDate = daysDate;
}
@Transient
public String getDaysDateString() {
if(daysDateString == null) {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
return formatter.format(daysDate);
}
return daysDateString;
}
public void setDaysDateString(String daysDateString) {
this.daysDateString = daysDateString;
}
@Basic
@Column(name = "FOOD_ID", nullable = true)
public Long getFoodId() {
return foodId;
}
public void setFoodId(Long foodId) {
this.foodId = foodId;
}
@Basic
@Column(name = "MEAL_ID", nullable = true)
public Long getMealId() {
return mealId;
}
public void setMealId(Long mealId) {
this.mealId = mealId;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "FOOD_ID", referencedColumnName = "ID",
updatable = false, insertable = false)
public FoodItem getFoodItem() {
return foodItem;
}
public void setFoodItem(FoodItem foodItem) {
this.foodItem = foodItem;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "MEAL_ID", referencedColumnName = "ID",
updatable = false, insertable = false)
public MealItem getMealItem() {
return mealItem;
}
public void setMealItem(MealItem mealItem) {
this.mealItem = mealItem;
}
@Transient
public ArrayList<FoodItem> getFoodItems() {
return foodItems;
}
public void setFoodItems(ArrayList<FoodItem> foodItems) {
this.foodItems = foodItems;
}
@Transient
public ArrayList<MealItem> getMealItems() {
return mealItems;
}
public void setMealItems(ArrayList<MealItem> mealItems) {
this.mealItems = mealItems;
}
public void makeDaysDate() throws ParseException{
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
this.daysDate = new Date(formatter.parse(this.daysDateString).getTime());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DayItem)) return false;
DayItem dayItem = (DayItem) o;
if (!getEmail().equals(dayItem.getEmail())) return false;
if (!getModId().equals(dayItem.getModId())) return false;
if (!getFmOrder().equals(dayItem.getFmOrder())) return false;
if (!getDaysDateString().equals(dayItem.getDaysDateString())) return false;
if (getFoodId() != null ? !getFoodId().equals(dayItem.getFoodId()) : dayItem.getFoodId() != null) return false;
return getMealId() != null ? getMealId().equals(dayItem.getMealId()) : dayItem.getMealId() == null;
}
@Override
public int hashCode() {
int result = getEmail().hashCode();
result = 31 * result + getModId().hashCode();
result = 31 * result + getFmOrder().hashCode();
result = 31 * result + getDaysDateString().hashCode();
result = 31 * result + (getFoodId() != null ? getFoodId().hashCode() : 0);
result = 31 * result + (getMealId() != null ? getMealId().hashCode() : 0);
return result;
}
}
ここでの最初のをやってコードの作成:
@Override
public List<DayItem> saveDayItem(DayItem item) throws Exception {
EntityManager manager = entityManagerFactory.createEntityManager();
EntityTransaction tx = manager.getTransaction();
List<DayItem> results = null;
try {
tx.begin();
manager.merge(item);
manager.flush();
manager.clear();
results = findUserDay(item.getDaysDate(), item.getEmail(), manager);
tx.commit();
} catch (Exception e) {
tx.rollback();
throw e;
} finally {
manager.close();
return results;
}
}
はここで更新やっコードです:あなたが実装されているので
public <T extends GtEntity> T store(T entity) throws Exception {
T managedEntity = null;
EntityManager manager = entityManagerFactory.createEntityManager();
EntityTransaction tx = manager.getTransaction();
try{
tx.begin();
managedEntity = manager.merge(entity);
tx.commit();
}catch(RuntimeException e){
tx.rollback();
throw e;
}finally {
manager.close();
return managedEntity;
}
}
エンティティは更新時にIDを持っていますか? –
@DanielJipaはい、元のレコードと同じIDです。 – Graham