【问题标题】:JPA 2.0: Load a subset of fields for an entityJPA 2.0:加载实体的字段子集
【发布时间】:2011-09-25 10:40:53
【问题描述】:

我有一个名为地址的实体。地址实体有几个字段,其中之一是 CITY。我通过调用 entityManager.createQuery 创建了一个查询,但我的查询仅包含 select 子句中的 CITY 字段(因为我只想加载该字段)。 CITY 字段是字符串类型。当我得到我的 resultList 时,我没有得到 Address 对象的列表,而是得到 Object[] 的列表。

有什么方法可以创建地址列表而不是 Object[] 列表?我的 JPA 提供程序是休眠的,最新版本。我想要一个不需要使用任何特定于 Hibernate 的解决方案。

【问题讨论】:

  • JPA 没有“获取组”,所以不,你不能这样做......除了将“城市”之外的所有字段定义为延迟加载。显然,使用 JDO 你可以做到

标签: hibernate jpa


【解决方案1】:

这可以通过查询中的构造函数表达式来实现。通常,您会将其与自定义 DTO 一起使用,但它也应与实体一起使用。首先在您的实体中创建一个额外的构造函数,只获取所需的字段:

public Address() {
    //default constructor
}

public Address(String city) {
    this.city = city;
}

您的查询可能如下所示:

select new your.package.Address(a.city) from Address a where ...

请注意,生成的对象未附加到 EntityManager,因此对它的更改不会自动持久化。

【讨论】:

  • 如果它是你想要的,你应该接受这个答案。否则,分享您的解决方案以帮助他人。
【解决方案2】:

如果您请求城市,Hibernate 将如何加载 Address 实例? JPA 实体是对象,并且对象应该尊重不变量。例如,一个这样的不变量可能是一个地址总是有一个 ID、一条街道等。如果 Hibernate 加载了部分对象(只填充了城市属性),这些不变量将被破坏,你不能再依赖自己的代码了.如果您尝试将此类地址附加到另一个对象,或者您只是尝试删除它,您也会遇到各种问题,因为它甚至不再有 ID。

所以简短的回答是否定的:不可能。

答案很长,因为 Adress 是 POJO,您只需要自己从加载的城市创建地址,或者使用 ResultTransformer。但是你会得到临时的 Address 实例而不是附加的 Adress 实体。这是造成无数错误和混乱的秘诀,恕我直言。

【讨论】:

  • "...这是无数错误和混乱的秘诀,恕我直言..." 你怎么能在不知道用例的情况下这么说???
  • 因为我在开发 Hibernate 应用程序方面的经验告诉我,Hibernate 不是一个易于使用的工具,而且有时将 Address 用作持久实体,有时用作数据对象,当您或一些初级开发人员将不得不在两年内维护代码。但你是决定者。我只是来帮忙的。
  • 另外,您还没有告诉我们为什么让地址只包含城市属性而不是简单地使用城市作为字符串是个好主意。
【解决方案3】:

有一种方法可以做到这一点,但它涉及一些代码重复。您必须创建一个名为“AddressWithCityOnly”的新实体,其中仅包含 ID 和 CITY 属性,并将其指向 db(地址表)中的同一个表。

然后您可以使用这个新实体对地址表进行部分加载(加载这些实体将仅加载 CITY 字段)和部分更新(将仅更新 CITY 字段)到地址表。

我面临着类似的问题。我有一个包含大约 70 列和大约 100,000 行的 PERSON 表,我只想更新所有行中的一列。加载原始实体会检索所有 70 列,开销太大。

【讨论】:

    猜你喜欢
    • 2015-06-24
    • 1970-01-01
    • 2011-02-19
    • 1970-01-01
    • 1970-01-01
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多