- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在使用 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;
}
}
最佳答案
由于您实现了 equals
和 hasCode
,Hibernate 将使用这些方法来查找要更新的实体。假设分离的对象已更改,equals
和 hasCode
将永远不会返回与附加实体相同的值,因此 Hibernate 将假定它是一个新实例。
您应该阅读有关 equals
and hasCode
的 hibernate 文档.
关于mysql - EntityManager merge() 导致重复行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38173457/
有一些使用多个数据源的示例: @Inject @DataSource("users") AgroalDataSource dataSource1; @Inject @DataSource("inven
我试图使用持久性和 servlet guice 扩展,让简单的 webapp 在 Jetty 上与 Guice 和 JPA 一起工作。 我写了这个服务实现类: public class PersonS
我使用 Hibernate 5.1.0.Final、Guice、Jersey。我有创建 EntityManagerFactory 的 HibernateModule并管理EntityManager实例
我正在使用 ThreadLocal 和请求/实体模式来获取实体。这种情况发生时,我关闭了一个实体管理器,并且在后台有一些实体可以编辑、复制和修改,然后我想将其保留或与新的实体管理器合并。我不知道这是一
好的,我正在使用 EJB 3.0 和 hibernate,我们将 .ear 文件放入嵌入 Apache Tomcat 6.0.18 的 Easy-Beans 1.0.1(带有 Hibernate)部署
我正在使用 Spring + JPA + Hibernate + EntityManager 与数据库对话。我收到“A JTA EntityManager cannot use getTransact
更新数据库时我应该更喜欢什么?这两种方法的优缺点是什么?我什么时候应该使用其中一种? public void disemployEmployee(Integer employeeId, Date en
我正在尝试在存储库中注入(inject) EntityManager。 编译成功,但是当我运行应用程序并发送一个发布请求时,我收到了这个错误: Unexpected error occurred: F
我正在尝试在 Spring Tools Suite 和 Pivotal tc Server Developer Edition 上开发 Spring+Hibernate+EntityManager+S
我有一个使用 spring boot + spring data JPA 的示例项目。在日志中,我观察到 EntityManagers 在我进行第一次 rest 调用之前被创建了几次。请澄清为什么会发
给定网络应用程序中的以下情况: // EntityManager em, one per Request with Spring's OpenEntityManagerInViewFilter //
当我们在 JAVA EE 环境中的 EntityManager 上使用 @PersistenceContext 注释时,容器将创建 entityManagerFactory(我猜是整个 session
我遇到了一种情况(我认为这很奇怪,但可能很正常),我使用 EntityManager.getReference(LObj.getClass(), LObj.getId()) 来获取数据库实体,然后通过
我有以下服务... @Stateless @LocalBean public class RandomService { @EJB RandomString stringTokenizer;
我在实体类中有这个函数,但 getDoctrine 不喜欢...... public function getObject() { $em = $this->getDoctrine()->ge
我正在尝试以级联方式保存某个对象并检索它。 我有 3 个对象超过 3 个实体。 实体: class Order { /** * @var integer $id *
我正在开发一个 JPA 应用程序(使用 hibernate ),我正在与 作斗争。自动冲洗 特征。 默认情况下,每当我们处理对任何实体的查询时,完整的 实体管理器 被冲洗。在大多数情况下这是可以的:我
我刚刚建立了一个到目前为止仍然非常小的项目 maven/jpa/hibernate 项目,我试图在其中持久化一个对象。 我的类(class)是一个非常简单的类(class): @Entity publ
我当前的项目使用 HSQLDB2.0 和 JPA2.0 。 场景是:我查询数据库以获取 contactDetails 的列表的 person .我删单contactInfo在 UI 中,但不保存该数据
我是 jpa 和 spring 世界的新手,我目前正在对一个简单的方法进行一些单元测试,但只有当我在单元测试模式下运行我的测试类时才会继续收到此错误消息: java.lang.IllegalState
我是一名优秀的程序员,十分优秀!