Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPA规范+多对多字段动态排序,无重复项_Java_Jpa - Fatal编程技术网

Java JPA规范+多对多字段动态排序,无重复项

Java JPA规范+多对多字段动态排序,无重复项,java,jpa,Java,Jpa,我有一个有很多字段的类,多对一和多对多关系,我需要通过这个类中的一些列和连接类中的字段添加动态过滤器,并通过这些字段添加排序 我对按多对多字段进行过滤和排序有问题 @Entity class EntityA { ... @ManyToMany @JoinTable ( name = "EntityA_EntityB", joinColumns = { @JoinColumn(name = "EntityB") }, inverseJoinColum

我有一个有很多字段的类,多对一和多对多关系,我需要通过这个类中的一些列和连接类中的字段添加动态过滤器,并通过这些字段添加排序

我对按多对多字段进行过滤和排序有问题

@Entity
class EntityA {
...
@ManyToMany
@JoinTable (
        name = "EntityA_EntityB",
        joinColumns = { @JoinColumn(name = "EntityB") },
        inverseJoinColumns = { @JoinColumn(name = "entityb_id") }
)
private List<EntityB> bEntities;
...
}
作为EntityB.name连接到EntityA的字段失败。此外,我还有其他一些带有@ManyTone的字段失败,出现下一个异常:

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: ORDER BY items must appear in the select list if SELECT DISTINCT is specified
如果我删除criteriaQuery.distincttrue;一切都会好的,但我会有副本,我不想有他们


如何修复它,同时又不产生重复的结果

获取EntityA重复结果的原因是将EntityA与EntityB连接起来,并且谓词基于EntityB中的一个字段。因此,如果有多个EntityB条目满足您的条件,并且它们都属于同一个EntityA,那么您将得到多个EntityA条目。因此,解决方案是使用exists,而不是连接两个表,并且不再需要使用distinct。您的规格可以如下所示:

 public class EntityASpecifications {
 //other specifications
 ...

   public static Specification<EntityA> entityBNameContains(String query) {
       return (root, criteriaQuery, criteriaBuilder) -> {

          if (query == null) {
              return criteriaBuilder.conjunction();
          }
          Subquery< EntityB> subquery = query.subquery(EntityB.class);
          Root< EntityB> subqueryRoot = subquery.from(EntityB.class);
          subquery.select(subqueryRoot);

          subquery.where(criteriaBuilder.and(criteriaBuilder.equal(root, subqueryRoot.get("entitya_id")),
                                criteriaBuilder.like(criteriaBuilder.lower("name"), getContainsPattern(query)))
                   );

          return criteriaBuilder.exists(subquery);

       };
   } 
   private static String getContainsPattern(String searchTerm) {
     return (searchTerm.isEmpty()) ? "%" : "%" + searchTerm.toLowerCase() + "%";
 }
} 

你看到这篇文章了吗?typedQueryThintQueryHints.HINT\u传递\u DISTINCT\u,false可能对您有效。@chromanoid看起来我不能使用它,因为我使用规范,无法从那里访问实体管理器。请注意,在我的示例中,criteriaBuilder.equalroot,subqueryRoot.getentitya\u id应该是criteriaBuilder.equalroot.getid,subqueryRoot.joinaEntities.getid,这样它就可以工作了
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: ORDER BY items must appear in the select list if SELECT DISTINCT is specified
 public class EntityASpecifications {
 //other specifications
 ...

   public static Specification<EntityA> entityBNameContains(String query) {
       return (root, criteriaQuery, criteriaBuilder) -> {

          if (query == null) {
              return criteriaBuilder.conjunction();
          }
          Subquery< EntityB> subquery = query.subquery(EntityB.class);
          Root< EntityB> subqueryRoot = subquery.from(EntityB.class);
          subquery.select(subqueryRoot);

          subquery.where(criteriaBuilder.and(criteriaBuilder.equal(root, subqueryRoot.get("entitya_id")),
                                criteriaBuilder.like(criteriaBuilder.lower("name"), getContainsPattern(query)))
                   );

          return criteriaBuilder.exists(subquery);

       };
   } 
   private static String getContainsPattern(String searchTerm) {
     return (searchTerm.isEmpty()) ? "%" : "%" + searchTerm.toLowerCase() + "%";
 }
}