【问题标题】:How do I selectively update properties on Spring beans with Hibernate?如何使用 Hibernate 选择性地更新 Spring bean 上的属性?
【发布时间】:2014-10-22 03:43:11
【问题描述】:

给定一个域对象,例如:

class MyPojo
  get/setA
  get/setB
  get/setC

如果我将 MyPojo 用作表单的 modelAttribute,则类似于:

 <form:form modelAttribute="myPojo" action="nextPage" method="POST">
    <form:input path="a"/>
    <form:input path="b"/>
 </form> 

我有一个控制器方法,例如:

@RequestMapping(value = {"/nextPage"}, method = RequestMethod.POST)
public String theNextPageMethod(@ModelAttribute("myPojo") MyPojo myPojoObj) {
         //call to a service/dao impl are omitted for brevity
         //but the dao impl does:
        sessionFactory.getCurrentSession().saveOrUpdate(myPojoObj);
}

Spring/Hibernate 使用属性“a”和“b”的表单输入值更新 myPojoObj,但在我的例子中,它还将属性“c”的值设置为 null。

这是预期的行为吗?如果是这样,保留分配给属性“c”的任何值的最佳做法是什么?是否有注释或其他方式仅更新属性“a”和“b”?

澄清: 理想情况下,我正在寻找允许在一个页面上更新“a”和“b”以及在另一个页面上更新“b”和“c”并为每个特定请求保持所有其他属性静态的东西。

【问题讨论】:

  • 谷歌这个:@Column(insertable=false, updatable=false)
  • 所以你会将该注释添加到属性“c”?
  • 我认为根据您对要求的描述,属性 C 将只是 @Column(updatable=false)。这将允许您插入一个值,但不能插入此列的任何后续更新。跨度>
  • 感谢您的回复。您的解决方案在技术上将满足要求,尽管您必须先验知道哪些列要保持静态(它总是必须是“c”)。所以我真的在视图或控制器级别上寻找类似的东西(例如,在一个 JSP 上,只更新 A 和 B,在另一个 JSP 上只更新 B 和 C)。我可以更准确地更新我的问题。
  • 好的 - 一个运行时解决方案。当您更新持久化的对象时,您将使用一些锁定机制来确保在您处理记录时其他人没有更新您的记录。最喜欢的方法通常是使用版本字段的光学锁,该字段可以是计数或时间戳,可以与您为更新提供的对象进行比较(请参阅@Version)。我提到这一点的唯一原因是 Hibernate 需要获取有问题的对象作为更新的前兆。因为获取的对象是缓存的,所以获取它并使用它的值对您没有任何害处。 . .

标签: java hibernate spring-mvc


【解决方案1】:

您想在哪里存储实体的状态?会话、视图还是数据库?

添加

@SessionAttributes({"myPojo"})

到你的控制器

或者在视图中使用隐藏的输入字段和 c 的值

或者用@ModelAttribute注解控制器方法,每次请求从数据库返回实体

您还可以为表单创建一个新的、较小的 POJO,并使用 Dozer 将值复制到您的真实实体或从您的真实实体复制值,并使用动态更新。

【讨论】:

  • 如果 MyPojo 很小,这些都是很好的建议,但可能不会很好,因为它是一个具有很多属性的大对象。无论如何,我现在可以使用@SessionAttributes。
【解决方案2】:

尝试动态更新属性应该可以解决您的问题。

@DynamicUpdate

现在只会更新更改的列。另见示例http://www.mkyong.com/hibernate/hibernate-dynamic-update-attribute-example/

【讨论】:

  • 嗯 - 我在 MyPojo bean 上尝试了 @DynamicUpdate 和 @SelectBeforeUpdate 但仍然没有看到预期的行为。 (实体注释在 Hibernate 4 中已弃用。)将调查并查看生成的 SQL。
  • 我仍然看到 UPDATE 语句设置了所有属性,而不仅仅是脏属性。我尝试了 Hibernate 4.1.4、4.2.8 和 4.3.6,因为我看到了一些有关 dynamicUpdate 的记录问题。我还确保使用@Transactional。会继续寻找。
  • 请记住,如果您使用 openSession() 而不是 getCurrentSession(),您还需要将对象放在带有注释 @SelectBeforeUpadete 的会话中
  • 我希望这是问题所在。我正在自动装配我的 SessionFactory 并在我的 dao 实现中调用 sessionFactory.getCurrentSession()。
猜你喜欢
  • 1970-01-01
  • 2017-11-24
  • 1970-01-01
  • 2016-08-04
  • 2012-02-04
  • 2017-08-04
  • 2013-11-20
  • 2015-08-30
  • 1970-01-01
相关资源
最近更新 更多