在JPA实体中,如何定义getter上使用的SQL?

时间:2013-02-07 22:22:59

标签: java jpa eclipselink

我有一个名为PetOwner的实体。 PetOwner有一份宠物清单。每只宠物都有一个商店(即:这只宠物来自的商店)。 Pet是一个抽象类,获得具体版本会进行大量连接(@Inheritance(strategy = InheritanceType.JOINED))。我希望在PetOwner上有一个带有此签名的方法:

Set<Store> getAllStores();

问题是加载Pets列表非常慢,实际上没有必要获取商店列表。当我调用getAllStores时,我希望它像这样运行SQL:

SELECT DISTINCT store_id
FROM pet
WHERE petowner_id = x;

但如果我这样实现它:

Set<Stores> stores = //
for (pet : pets)
   stores.add(pet.getStore());
return stores;

它会吸引所有的宠物并且非常慢。那我怎么能阻止它拉进所有的宠物?理想情况下,我确实想在PetOwner对象上使用此方法,因为我认为代码 以这种方式更加面向对象。

此外,在PetOwner中还有其他方法,我需要加载Pets列表,即使它很慢。但我并不总是这么称呼它,这就是我想要避免这种方法的原因 加载宠物清单。

2 个答案:

答案 0 :(得分:1)

我假设您有一项服务用于获取PetOwners。我建议您在服务上创建一种新方法,而不是将您的方法添加到PetOwner中。

public Set<Stores> getStoresForOwner( PetOwner owner );

并使用您用于数据访问层的任何内容(hibernate模板,Spring-data-jpa存储库,直接使用EntityManager)来使用命名查询进行调用。

@NamedQuery(name="PetOwnerStore.findAll", query="SELECT distinct p.Store from Pet p where p.Owner.id = :petOwnerId");

可以说,既然你从Pet中选择了JPA可能不得不做所有的连接...

以上所有假设(除了你没有给出任何实体映射之外),你的Pet和Store之间的关系是懒惰的提取,因此尚未填充。

答案 1 :(得分:1)

没有标准的方法可以执行此操作,因为您没有映射此数据。我看到的不同选项是

  1. 直接在EM上使用命名查询
  2. 将方法添加到接受ENntityManager的PetOwner并执行 直接查询,或
  3. 将一个临时列表添加到宠物主人并在postload中填充它 运行查询的事件。但是,这将无法看到更新 除非重新加载PetOwner。