在 Hibernate 的根 table 中使用 Where 子句检索分层数据 object
Retrieve hierarchical data object with Where clause in root table in Hibernate
我有一个小项目,其中有一个主 table,它是 table 层次结构的根,而这个 table 有一个 "ID"和一个 "instance ID",它们都代表一个主键。这是因为如果行中有任何更改,我想继续跟踪更改。此外,在这个根 table 中,我有一个属性将行标记为 "deleted".
我想做的是以下查询:给定一个 "ID"(第一个)请求,我想获得具有属性 "deleted" 的单行到 0(这意味着它是当前活动行,因为标记为 1 的那些是存储在同一 table 中的历史记录的一部分)以及层次结构的后续属性。
例如,如果我有一个名为 Animal 的 table,它有一个名为 Dog 的 child table,我想恢复整个 Dog object他的 "ID",这是来自 Animal 的外键。 Hibernate 有一个方法可以做到这一点,但问题是,如果我想使用它,我不能使用 Where 子句,如果我编写查询,我必须根据 [=40 显式编写连接=] object class 我想得到的。
// This is what I have
public Dog returnAnimalData(String ID) {
List<Dog> dogs = hibernate.getCurrentSession().get(Dog.class, ID);
for (Dog dog : dogs) {
if(dog.getMarkAsDeleted().equals(0)){
return dog;
}
}
return null;
}
// This is what I would like
public Dog returnAnimalData(String ID) {
@Where(clause="deleted=0")
Dog dog = hibernate.getCurrentSession().get(Dog.class, ID);
// Or
Dog dog = hibernate.getCurrentSession().get(Dog.class, ID, 'where deleted = 0');
return dog;
}
编辑:
一个例子:
Animal 有 ID、InstanceID、deletedFlag 和 typeOfAnimal
Dog 有 ID、InstanceID 和 Name,Dog 扩展了 Animal
Cat 有 ID、InstanceID、Name 和 isFat,Cat extends Animal
过程是这样的:
Ask for animal 1
-> Animal 1 is a Dog
-> search Dog with ID=1 and deletedFlag=0
-> retrieve Dog (IDs, deletedFlag, animalType, Name)
Ask for animal 2
-> Animal 2 is a Cat
-> search Cat with ID=2 and deletedFlag=0
-> retrieve Cat (IDs, deletedFlag, animalType, Name, isFat)
问题是解决此查询而不用担心 Animal 的 child class 的数量,例如 "SELECT animal FROM CONCRETE_ANIMAL_TABLE where deletedFlag=0",其中 CONCRETE_ANIMAL_TABLE 可能是名称table 狗、猫等。我会先尝试做 Naros 的回答。
如果我找到答案,我会 post 它,因为我认为这是一个非常有趣的问题,也许它应该有助于理解如何使用 Hibernate 管理层次结构。
您需要使用 HQL/JPQL 来获取您的 Dog
或 JPA 标准 API。由于您使用的是本机 Hibernate API,我将在这种情况下说明 HQL:
public List<Dog> getDogsByDeletedFlag(boolean deletedFlag) {
return hibernate.getCurrentSession()
.createQuery( "SELECT d FROM Dog d WHERE d.deleted = :deletedFlag" )
.setParameter( "deletedFlag", deletedFlag )
.getResultList();
}
方法 Session#get
和 Session#load
仅用于通过标识符获取特定实体类型的实例,而不是用于潜在地获取可能结果的列表。
如果您只想获取第一个命中而不是所有可能的行,您可以对上述查询施加限制约束,例如:
public Dog getFirstDogByDeletedFlag(boolean deletedFlag) {
return hibernate.getCurrentSession()
.createQuery( "SELECT d FROM Dog d WHERE d.deleted = :deletedFlag" )
.setParameter( "deletedFlag", deletedFlag )
.setMaxResults( 1 ) // only gets the first hit
.getSingleResult();
}
更新
如果您想使用单一方法获得多态性类,您需要做的就是传入适当的值来完成:
public <T> T getFirstAnimalByDeletedFlag(Class<T> clazz, boolean deletedFlag) {
// NOTE: We assume that the class name is also the entity name.
// Since you can explicitly name entities, e.g. @Entity(name = "MyName"),
// you'd need to pass this String value separately if you use this.
StringBuilder sb = new StringBuilder();
sb.append( "FROM " ).append( clazz.getName() ).append( " o " );
sb.append(" WHERE o.deleted = :deletedFlag" );
return hibernate.getCurrentSession()
.createQuery( sb.toString(), clazz )
.setParameter( "deletedFlag", deletedFlag )
.setMaxResults( 1 )
.getSingleResult();
}
那么您需要做的就是调用它:#getFirstAnimalByDeletedFlag( Dog.class, true )
或 #getFirstAnimalByDeletedFlag( Cat.class, true )
。
我有一个小项目,其中有一个主 table,它是 table 层次结构的根,而这个 table 有一个 "ID"和一个 "instance ID",它们都代表一个主键。这是因为如果行中有任何更改,我想继续跟踪更改。此外,在这个根 table 中,我有一个属性将行标记为 "deleted".
我想做的是以下查询:给定一个 "ID"(第一个)请求,我想获得具有属性 "deleted" 的单行到 0(这意味着它是当前活动行,因为标记为 1 的那些是存储在同一 table 中的历史记录的一部分)以及层次结构的后续属性。
例如,如果我有一个名为 Animal 的 table,它有一个名为 Dog 的 child table,我想恢复整个 Dog object他的 "ID",这是来自 Animal 的外键。 Hibernate 有一个方法可以做到这一点,但问题是,如果我想使用它,我不能使用 Where 子句,如果我编写查询,我必须根据 [=40 显式编写连接=] object class 我想得到的。
// This is what I have
public Dog returnAnimalData(String ID) {
List<Dog> dogs = hibernate.getCurrentSession().get(Dog.class, ID);
for (Dog dog : dogs) {
if(dog.getMarkAsDeleted().equals(0)){
return dog;
}
}
return null;
}
// This is what I would like
public Dog returnAnimalData(String ID) {
@Where(clause="deleted=0")
Dog dog = hibernate.getCurrentSession().get(Dog.class, ID);
// Or
Dog dog = hibernate.getCurrentSession().get(Dog.class, ID, 'where deleted = 0');
return dog;
}
编辑:
一个例子:
Animal 有 ID、InstanceID、deletedFlag 和 typeOfAnimal Dog 有 ID、InstanceID 和 Name,Dog 扩展了 Animal Cat 有 ID、InstanceID、Name 和 isFat,Cat extends Animal
过程是这样的:
Ask for animal 1
-> Animal 1 is a Dog
-> search Dog with ID=1 and deletedFlag=0
-> retrieve Dog (IDs, deletedFlag, animalType, Name)
Ask for animal 2
-> Animal 2 is a Cat
-> search Cat with ID=2 and deletedFlag=0
-> retrieve Cat (IDs, deletedFlag, animalType, Name, isFat)
问题是解决此查询而不用担心 Animal 的 child class 的数量,例如 "SELECT animal FROM CONCRETE_ANIMAL_TABLE where deletedFlag=0",其中 CONCRETE_ANIMAL_TABLE 可能是名称table 狗、猫等。我会先尝试做 Naros 的回答。
如果我找到答案,我会 post 它,因为我认为这是一个非常有趣的问题,也许它应该有助于理解如何使用 Hibernate 管理层次结构。
您需要使用 HQL/JPQL 来获取您的 Dog
或 JPA 标准 API。由于您使用的是本机 Hibernate API,我将在这种情况下说明 HQL:
public List<Dog> getDogsByDeletedFlag(boolean deletedFlag) {
return hibernate.getCurrentSession()
.createQuery( "SELECT d FROM Dog d WHERE d.deleted = :deletedFlag" )
.setParameter( "deletedFlag", deletedFlag )
.getResultList();
}
方法 Session#get
和 Session#load
仅用于通过标识符获取特定实体类型的实例,而不是用于潜在地获取可能结果的列表。
如果您只想获取第一个命中而不是所有可能的行,您可以对上述查询施加限制约束,例如:
public Dog getFirstDogByDeletedFlag(boolean deletedFlag) {
return hibernate.getCurrentSession()
.createQuery( "SELECT d FROM Dog d WHERE d.deleted = :deletedFlag" )
.setParameter( "deletedFlag", deletedFlag )
.setMaxResults( 1 ) // only gets the first hit
.getSingleResult();
}
更新
如果您想使用单一方法获得多态性类,您需要做的就是传入适当的值来完成:
public <T> T getFirstAnimalByDeletedFlag(Class<T> clazz, boolean deletedFlag) {
// NOTE: We assume that the class name is also the entity name.
// Since you can explicitly name entities, e.g. @Entity(name = "MyName"),
// you'd need to pass this String value separately if you use this.
StringBuilder sb = new StringBuilder();
sb.append( "FROM " ).append( clazz.getName() ).append( " o " );
sb.append(" WHERE o.deleted = :deletedFlag" );
return hibernate.getCurrentSession()
.createQuery( sb.toString(), clazz )
.setParameter( "deletedFlag", deletedFlag )
.setMaxResults( 1 )
.getSingleResult();
}
那么您需要做的就是调用它:#getFirstAnimalByDeletedFlag( Dog.class, true )
或 #getFirstAnimalByDeletedFlag( Cat.class, true )
。