gpt4 book ai didi

mysql - EntityManager merge() 导致重复行

转载 作者:行者123 更新时间:2023-11-29 20:49:38 28 4
gpt4 key购买 nike

我在使用 EntityManager.merge() 时遇到了一些非常奇怪的行为。这就是正在发生的事情。我有一个使用 Spring MVC、Hibernate 和 JPA 的 REST API 设置,用于从 MySQL 数据库插入、更新和删除项目。插入和更新函数都使用 EntityManager.merge(),并且它们在 99% 的情况下都能正常工作。

但是,在某个时刻,这似乎是第一次调用更新记录,它会在数据库中创建该记录的副本,然后返回到原始记录并按应有的方式对其进行更改。

我真的不知道为什么会发生这种情况。您可能会认为,如果它创建了重复记录,它会编辑该记录,但不,在更新时,它会创建重复记录,放弃它,然后返回到第一条记录进行更改。

我认为这是因为我在实体 bean 中设置了 hashcode 和 equals,这可能是这样。尽管我没有发现它们有什么问题,因为我是基于唯一键而不是 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;
}
}

最佳答案

由于您实现了 equalshasCode,Hibernate 将使用这些方法来查找要更新的实体。假设分离的对象已更改,equalshasCode 将永远不会返回与附加实体相同的值,因此 Hibernate 将假定它是一个新实例。

您应该阅读有关 equals and hasCode 的 hibernate 文档.

关于mysql - EntityManager merge() 导致重复行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38173457/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com