Hibernate saveOrUpdate() 更新时创建新条目

Posted

技术标签:

【中文标题】Hibernate saveOrUpdate() 更新时创建新条目【英文标题】:Hibernate saveOrUpdate() creates new entry when updating 【发布时间】:2017-11-29 00:17:23 【问题描述】:

我创建了一个名为“gauge_category”的表,它只有一个字段gauge_category_id”作为主键,数据类型为varchar。我尝试了 CRUD 操作。创建、读取、删除操作完美运行。当我更新时,它正在创建一个新条目,而不是更新。我从一些文章中了解了 saveOrUpdate() 。单击编辑按钮时从 URL 传递的参数正常工作。

但我注意到我尝试了另一个类,它有两个字段 id(int)(primarykey) ,college(Varchar)。当 id add <form:hidden path="id" /> 以 jsp 形式添加时,此处更新正确。

saveOrUpdate() 执行以下操作:

如果对象已在此会话中持久存在,则不执行任何操作 如果与会话关联的另一个对象具有相同的标识符,则抛出异常 如果对象没有标识符属性,则保存()它 如果对象的标识符具有分配给新实例化对象的值,则保存()它 如果对象由 or 版本化,并且版本属性值与分配给新的值相同 实例化对象,保存()它 否则更新()对象

模型类

@Entity
@Table(name = "gauge_category")
public class GaugeCategory 

    @Id
    @Column(name = "gauge_category_id", unique = true, nullable = false)
    private String category;    

    public GaugeCategory() 
        super();
    

    public GaugeCategory(String category) 
        super();
        this.category = category;
    

    public String getCategory() 
        return category;
    

    public void setCategory(String category) 
        this.category = category;
       

Dao 实现类

//other methods, @Autowired

        @Override
        public void saveOrUpdate(GaugeCategory GaugeCategory) 
            sessionFactory.getCurrentSession().saveOrUpdate(GaugeCategory);     
        

控制器类

//other methods, @Autowired

@RequestMapping(value = "/save", method = RequestMethod.POST)
    public ModelAndView saveCategory(@ModelAttribute("gaugeCategoryForm") GaugeCategory gaugeCategory) 
        gaugeCategoryService.saveOrUpdate(gaugeCategory);
        return new ModelAndView("redirect:/gaugeCategory/list");
    

用于添加的jsp页面

<spring:url value="/gaugeCategory/save" var="saveURL"></spring:url>

<form:form action="$saveURL " modelAttribute="gaugeCategoryForm"> 

     <form:input path="category" />

</form:form>

【问题讨论】:

如果表只有一个字段,则无法将旧 id 获取到 update。如果旧 id 是例如1,如果您只有一个字段,则将其更改为 2,则无法检测旧值 1 来执行更新。因此创建了一个新实例。如果有多个字段 id (PK) 和一些数据字段,则该 id 用于执行更新。 我们是否需要在所有表中始终包含 id (INT)? 【参考方案1】:

问题是您的模型只有一个字段并且它是主键。当您尝试更新实体时,您会更改表单中键的值,因此 hibernate 不知道它应该更新哪个实体,而是创建一个新实体。

另外,只有一个字段的模型的目的是什么?最好有一些实体,例如:

@Entity
@Table(name = "gauge_category")
public class GaugeCategory 

    @Id
    @GeneratedValue
    private Integer id;

    @Id
    @Column(name = "name", unique = true, nullable = false)
    private String name;

    // ...


拥有这样的实体,您将能够使用 id 更新类别的名称,并在其他数据库表中引用该 id。如果您使用字符串外键,则很难更新其他表,尤其是在它们有很多记录的情况下。

【讨论】:

所以你建议我拥有多个领域,不是吗?我得到了你的解释。我的疑问是,如果我有两个数据类型为 varchar 的字段,一个是主键,会发生什么?这个问题也一样。或者我们是否至少需要数据类型为 INT 的 id? @varman 是的,我建议您使用一个INT 和一个VARCHAR 字段,有关更多详细信息,请参阅this answer 了解为什么最好使用代理整数键。 非常感谢您提供的建议。我已经完成了整数 ID。

以上是关于Hibernate saveOrUpdate() 更新时创建新条目的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate中saveOrUpdate()和merge()的区别

关于hibernate的saveOrUpdate方法的一个问题

jooq中hibernate的saveOrUpdate方法的等价物是啥?

hibernate save,update,saveorupdate方法有什么区别

在休眠 saveOrUpdate() 期间获取 org.hibernate.StaleStateException

hibernate saveOrUpdate()方法执行数据库操作不成功