从层次结构中检索的实体类

时间:2014-02-12 14:15:48

标签: jpa

在我的项目中,我有一个JPA层次结构Location -> Site

@Entity
@Table(name = "LOCATION")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="LOC_TYPE",discriminatorType=DiscriminatorType.STRING)
public class Location {
  ...
}

@Entity
@DiscriminatorValue("SI")
public class Site extends Location {
  ...
}

现在,每个Employee都有一个Location分配的列表(就我所知,所有这些位置实际上都是Site)。在某些情况下,我需要Site已分配Employee的列表(请注意,我已定义的关系是Location)。

使用Hibernate 3.2,我可以只为Location编写查询并按判别式进行过滤;返回的类是更具体的子类的实例,例如:

Query query = em.createQuery("SELECT loc FROM Location loc WHERE loc.type=\"SI\"");
List<Location> locations = (List<Location>) query.getResultList();
for (Location location : locations) {
  Site mySite = (Site) location;
  ...
}

但是,我找不到任何文档来说明JPA规范是否保证了这种行为,或者只是来自Hibernate的实现决策。在最后一种情况下,我不应该使用这种方法,因为如果我切换提供者,它可能会改变。)

你能否告诉我标准是否支持我的方法?

BTW,我在Hibernate 3.2上使用JPA 1

更新:

在orden中澄清我想要的东西,这是我实施的“安全警报”。请记住,disc属性是鉴别器列,因此我确信返回的对象保留为Site个实例。

Query query = em.createQuery("SELECT lo FROM Employee em JOIN em.location lo WHERE lo.disc = 'SI'");
List<Location> locations = (List<Location>) query.getResultList();
List<Site> site = new ArrayList<Site>();
for (Location location : locations) {
  if (location instanceof Site) {
    sites.add((Site) location);
  } else {
    log.warn("Found a Location that is not instance of Site");
  }
}

JPA规范是否指定永远不会调用我的log.warn语句? AFAIK,也许一个实现可以返回一堆不是Location实例的Site。当然,在这种情况下,只有Location属性可用;这种行为有点像在C ++中切片。

1 个答案:

答案 0 :(得分:5)

在从2.0版开始的JPA中,您具有TYPE(e)功能。规范示例:

SELECT e FROM Employee e WHERE TYPE(e) IN (Exempt, Contractor)

摘自JPA 2.0规范( 4.6.17.4实体类型表达式):

  

实体类型表达式可用于限制查询多态性。   TYPE运算符返回参数的确切类型。


注意JPA。另一方面,您的示例对基本的JPA机制产生怀疑,我想再次强调:当您使用其鉴别器从DB获取行(使用JPA查询)时特定于Site实体的值,您可以确定Java对象将是该类的实例(即Site类的实例)。现在我认为规范并没有强制提供者认为它的类是Site(即fetchedEntity.getClass()==Site.class),但你可以100%确定fetchedEntity instanceof Site返回true。


注意Hibernate。根据我对Hibernate的经验,我只能补充说fetchedEntity.getClass() == Site.class在Hibernate中返回true(当然除了fetchedEntity instanceof Site)。