2014-09-02 58 views
3

实体层次说我有以下实体:JPA标准查询比使用单表继承

@Entity 
@Inheritance(strategy = SINGLE_TABLE) 
@DiscriminatorColumn(name = "type") 
public abstract class BaseEntity { 
    private Date someDate; 
    private Date otherDate; 
    private boolean flag; 
} 

@Entity 
@DiscriminatorValue("entity1") 
public class Entity1 extends BaseEntity { 
    private String someProperty; 
} 

@Entity 
@DiscriminatorValue("entity2") 
public class Entity2 extends BaseEntity { 
    private String otherProperty; 
} 

我试图建立一个标准查询,返回基于在BaseEntity以及两者的性能BaseEntity的情况下,子类。所以基本上我正在寻找一个对应于该伪SQL条件查询:

SELECT * FROM <BaseEntity table name> 
WHERE someDate < ? AND otherDate > ? AND flag = ? 
AND someProperty = ? AND otherProperty = ?; 

我宁愿不建立两个单独的查询,因为他们有这么多的重复(即大多数的属性是在基类)。但是,如果我将BaseEntity声明为根,我还没有想出在查询中引用子类属性的方法。是否有可能建立这样的标准查询?

UPDATE:

也许一些代码会澄清的问题。我基本上是喜欢做这样的事情:

CriteriaBuilder builder = ...; 
CriteriaQuery<BaseEntity> query = ...; 
Root<BaseEntity> root = ...; 

query.select(root).where(builder.and(
     builder.lessThan(root.get(BaseEntity_.someDate), new Date()), 
     builder.greaterThan(root.get(BaseEntity_.otherDate), new Date()), 
     builder.isTrue(root.get(BaseEntity_.flag)), 
     builder.equal(root.get(Entity1_.someProperty), "foo"), <-- This won't work 
     builder.equal(root.get(Entity2_.otherProperty), "bar") <-- Neither will this 
)); 

现在,我才明白为什么上面的代码示例不工作,但我想知道是否有一种方法来绕过它。

回答

5

我设法向下转换的BaseEntity根成对应于子类型的CriteriaBuilder.treat()喜欢这个新根来解决这个:基于

CriteriaBuilder builder = ...; 
CriteriaQuery<BaseEntity> query = ...; 
Root<BaseEntity> root = ...; 
Root<Entity1> entity1 = builder.treat(root, Entity1.class); 
Root<Entity2> entity2 = builder.treat(root, Entity2.class); 

query.select(root).where(builder.and(
     builder.lessThan(root.get(BaseEntity_.someDate), new Date()), 
     builder.greaterThan(root.get(BaseEntity_.otherDate), new Date()), 
     builder.isTrue(root.get(BaseEntity_.flag)), 
     builder.equal(entity1.get(Entity1_.someProperty), "foo"), 
     builder.equal(entity2.get(Entity2_.otherProperty), "bar") 
)); 
0

尝试Junction。你总是可以这样做:

Criteria crit = session.createCriteria(YourClassName.class); 
Criterion cr1 = Restrictions.lt("propertyname", propertyvalue); 
Criterion cr2 = Restrictions.gt("propertyname", propertyvalue); 
Criterion cr3 = Restrictions.eq("propertyname", propertyvalue); 
Criterion cr4 = Restrictions.eq("propertyname", propertyvalue); 
Junction cond = Restrictions.conjunction(); 
cond.add(cr1).add(cr2).add(cr3).add(cr4) 
crit.add(cond); 

我希望我的问题得到了正确的答复。

+0

该解决方案完全基于Hibernate的,但我在寻找一个在JPA Criteria API上。另外,我宁愿使用JPA2元模型来引用属性而不是字符串标识符。 – 2014-09-03 05:40:52