在单个表继承类型中查找特定类型的元素

想象以下实体层次:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type",columnDefinition = "varchar(60)")
abstract class Resource {

}


@Entity
@DiscriminatorValue("resource1")
class Resource1 extends Resource {
  @Embedded
  private Property property1;
}

@Entity
@DiscriminatorValue("resource2")
class Resource2 extends Resource {
  @Embedded
  private Property property2;
}

@Entity
@DiscriminatorValue("resource3")
class Resource3 extends Resource {
  @Embedded
  private Property property3;
}

@Entity
@DiscriminatorValue("resource4")
class Resource4 extends Resource {
  @Embedded
  private Property property4;
}

@Entity
class EntityUsingResource {
  @OneToMany(...)
  @JoinColumn(...)
  private List<Resource> resources;
}

我正在尝试创建一个UI来搜索EntityUsingResource,并且能够过滤具有具有特定属性资源的元素。

因此,在GUI的搜索字段中,您可以输入让说property4的值,它会过滤所有EntityUsingResource类型的资源,这些资源的类型为Resource4,其property4等于您输入的内容。

到目前为止,我已经通过使用弹簧规范使用以下标准api来做到这一点:

public static Specification<EntityUsingResource> 
withResource4HavingProperty4Like(String property4) {
    Join<EntityUsingResource,Resource> join = 
        root.join(EntityUsingResource_.resources,JoinType.INNER);
    Join<EntityUsingResource,Resource4> treatedJoin = 
      cb.treat(join,Resource4.class);

    return cb.like(
            treatedJoin.get(Resource4_.property4).get(Property_.value),"%" + property4 + "%");
}

public static Specification<EntityUsingResource> 
withResource2HavingProperty2Like(String property2) {
    Join<EntityUsingResource,Resource2> treatedJoin = 
        cb.treat(join,Resource2.class);

    return cb.like(
        treatedJoin.get(Resource2_.property2).get(Property_.value),"%" + property2 + "%");
}

我将这些规格与弹簧“规格”实用程序类一起使用,如下所示:     哪里(         withResource2HavingProperty2Like(property2)     )。和(         withResource4HavingProperty4Like(property4)     );

然后我将其传递给JpaRepository,并或多或少地将结果返回给gui。

这会在搜索property1时创建以下SQL:

select 
    entity_using_resource0.id as entityId
from 
    entity_using_resource entity_using_resource0
inner join resource resourceas1_ on 
    entity_using_resource0.id=resourceas1_.entity_using_resource_id
inner join resource resourceas2_ on 
    entity_using_resource0.id=resourceas2_.entity_using_resource_id
inner join resource resourceas3_ on 
    entity_using_resource0.id=resourceas3_.entity_using_resource_id
inner join resource resourceas4_ on 
    entity_using_resource0.id=resourceas4_.entity_using_resource_id
where (resourceas4_.property1 like 'property1')
    and (resourceas2_.property1 like '%property1%') limit ...;

问题是,此查询产生大量重复项。我尝试使用distinct来解决问题,但提出了另一个问题。在EntityUsingResource实体中,我有一列为json类型的列,因此无法使用distinct,因为数据库无法比较json值。

一个人如何编写使用条件api过滤Resource类型的查询?

预先感谢:-)

zhouzhou99 回答:在单个表继承类型中查找特定类型的元素

如果您的目标是创建有效的查询而不是使用标准API,则可以使用FluentJPA

({property2参数将自动捕获并作为参数传递)

public List<EntityUsingResource > findEntitiesUsingResource2(String property2) {

    FluentQuery query = FluentJPA.SQL((EntityUsingResource entity) -> {

        List<Long> resourceIds = subQuery((Resource res) -> {

            SELECT(res.getEntityUsingResource().getId());
            FROM(res);
            WHERE(typeOf(res,Resource2.class) &&
              ((Resource2) res).getProperty2().getValue().matches("%" + property2 + "%"));
        });

        SELECT(entity);
        FROM(entity);
        WHERE(resourceIds.contains(entity.getId()));
    });

    return query.createQuery(em,EntityUsingResource.class).getResultList();
}

产生以下SQL:

SELECT t0.*
FROM entity_using_resource t0
WHERE (t0.id IN (SELECT t1.entity_id
FROM resource t1
WHERE (t1.type = 'resource2' AND (t1.property2 LIKE  CONCAT( CONCAT( '%',?1 ),'%' )  ))) )

对JPA继承的支持记录在here中。

本文链接:https://www.f2er.com/3138643.html

大家都在问