2012-03-06 37 views
2

这可能是一个非常愚蠢的问题,但...为什么JPA生成的更新查询包含比必要的字段更多的字段?

我使用JPA 2.0与Hibernate 4.我有一个持久对象,有很多领域。

我创建并在一次事务中坚持它。然后,在另一个,我期待该对象并改变其一个字段的值:当事务提交

try{ 
    tx.begin(); 
    MyObj object = myObjDAO.findById(objectId); 
    object.setFieldA("Different value"); 
} finally { 
    tx.commit(); 
} 

JPA持续这种变化,但我可以从我的MySQL看到genquery.log的更新语句它生成涉及该对象上的所有字段:

439查询
/*更新uk.co.core.objects.MyObj * /更新MyObj中集创建= '2012-03-06 13时39分37秒' ,modified ='2012-03-06 13:39:37',version = 1,fieldA ='Different value',fieldB ='originalValue',fieldC ='originalValue'其中id ='objectId'和版本= 0; 439查询提交

为什么它包括所有不变字段及其现有值查询,而不仅仅是:

更新MyObj中设置FIELDA =“不同的价值”,版本= 1, modified ='somedate'其中id ='objectId'和version = 0;

这个例子看起来可能没有太大区别,但我有一些对象具有更多字段,所有这些对象都包含在它们的更新语句中。

即使纯粹从字符串数据的角度来看,更新查询中只包含更改的字段,它会不会更快/更高效?如果是这样,是否有一个配置选项可以让它这样做?

希望你能帮忙,谢谢!

回答

1

您可以配置休眠到排除更新查询中的未修改字段,如article中所述。

这是通过在您的类映射中添加dynamic-update="true"来完成的。

<class ... table="your_table" .... dynamic-update="true"> 

在包含许多列(传统设计)或包含大量数据的大型表中,这会对系统性能产生很大影响。

它可以有一些性能影响,如告诉here。因此,在实现代码之前,请测量代码的性能。

阅读API here了解更多信息。

1

要坚持只是差异的你的ORM必须:

  1. 阅读你的对象的当前版本,与数据库中的所有它的子实体, 。
  2. 迭代每个属性并比较它们的值,看它是否有 已更改。
  3. 生成专门的查询,仅用于更新 已更改的属性。

这显著不仅仅是发放所有列的标准更新更加复杂,而且也将是显著高性能,由于增加了复杂性。

+0

一个专门的** HQL **是一个好主意,当你确切知道要更新什么时,无论版本。但是恐怕你的解决方案可能是**性能开销,因为对象必须加载到内存中,然后应该进行比较**。 – ManuPK 2012-03-06 14:37:59

0

现在发现在同一问题中提出2个问题的危险。 ManuPK和Perception都给出了很好的,有用的,正确的答案。不过,我从ManuPk获得了更多的信息和理解,因此我接受了它。

肯定与他同意 - 设置属性应该只对某些表格进行设置,并且性能应该在测试前后进行测试。

未来,我会尽量让我的问题更有针对性。