在我的项目中,我有一个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 ++中切片。
答案 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
)。