Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.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
Spring 按条件动态搜索_Spring_Hibernate_Jpa_Spring Data_Querydsl - Fatal编程技术网

Spring 按条件动态搜索

Spring 按条件动态搜索,spring,hibernate,jpa,spring-data,querydsl,Spring,Hibernate,Jpa,Spring Data,Querydsl,我正在使用QueryDSL和Spring数据Jpa进行动态搜索 我遵循这一点,它与BooleanBuilder没有关系,但在我的情况下,我必须进行连接 那么,如果我在player、player\u team、team上有3个连接,并且我在player的名称和他的团队的名称上有可选参数,我怎么能做到呢 ________ ___________________ _______ | player | | player_team | | team

我正在使用
QueryDSL
Spring数据Jpa
进行动态搜索

我遵循这一点,它与
BooleanBuilder
没有关系,但在我的情况下,我必须进行连接

那么,如果我在
player
player\u team
team
上有3个连接,并且我在player的名称和他的团队的名称上有可选参数,我怎么能做到呢

 ________       ___________________       _______
| player |    | player_team         |    | team  |
|------  |    |----------------     |    |-------|
| id     |    | player_team_id (pk) |    | id    |
| name   |    | player_id (fk)      |    | name  |
  ------      | team_id (fk)        |     -------
                -----------      
player.java

@Entity
@Table(...)
public class Player implements java.io.Serializable {

    private Integer idPlayer ;
    private String namePlayer;
    private Set<PlayerTeam> player_teams = new HashSet<PlayerTeam>(0);  
    ...
}
对于每个庄园,我都有这样的回答:

public interface PlayerRespository extends JpaRepository<Player, Integer>, QueryDslPredicateExecutor<Player> {

}
公共接口PlayerRespository扩展了JpaRepository、QueryDSL谓词执行器{
}

您是否尝试过使用
规范
?Spring的JPA存储库使用以下方法使用规范查找结果:

清单findAll(规范规范)

构建规范有不同的方法,我的方法是为接受来自REST服务的请求而定制的,因此我基本上创建了一个给定类型的空白实体(本例中为Foo)并设置请求中提供的任何搜索条件(例如名称),然后从每个字段构建谓词(如果指定了名称字段,则添加“name等于”bob“谓词)

以下是规范生成器的示例:

import static org.springframework.data.jpa.domain.Specifications.where;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.jpa.domain.Specification;

import com.acme.model.security.Principal;

public class FooSpecification { 

    private final Foo criteria;
    private String query;

    public FooSpecification(String query, Foo criteria) {
        this.query = query;
        this.criteria = criteria;
    }

    public Specification<Foo> trainerEquals() {
        if (criteria.getTrainer() == null) {
            return null;
        }

        return new Specification<Foo>() {

            @Override
            public Predicate toPredicate(Root<Foo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.equal(root.<Principal>get("trainer").<Long>get("id"), criteria.getTrainer().getId());
            }
        };
    }

    public <T> Specification<Foo> valueEquals(final T value, final String field) {
        if (value == null) {
            return null;
        }

        return new Specification<Foo>() {

            @Override
            public Predicate toPredicate(Root<Foo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.equal(root.<T> get(field), value);
            }
        };
    }

    /**
     * Convert input string to lower case, appends '%' around it and does SQL LIKE comparison with the field value, also lower cased.
     * If value is null, no comparison is done.  Example:
     * 
     * value = "John";
     * field = "firstName";
     * 
     * resulting specification = "name like '%john%'"
     * 
     * @param value string or null
     * @param field field name
     * @return SQL LIKE specification for the given value or null if value is null
     */
    public Specification<Foo> stringLike(final String value, final String field) {
        if (StringUtils.isBlank(value)) {
            return null;
        }

        return new Specification<Foo>() {

            @Override
            public Predicate toPredicate(Root<Foo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.like(cb.lower(root.<String> get(field)), getLikePattern(value));
            }
        };
    }

    private String getLikePattern(String searchTerm) {
        return new StringBuilder("%")
                .append(searchTerm.toLowerCase().replaceAll("\\*", "%"))
                .append("%")
                .toString();
    }

    public Specification<Foo> fullSearch() {
        return where(trainerEquals())
                .and(valueEquals(criteria.getName(), "name"))
                .and(valueEquals(criteria.getInstructions(), "description"))
                .and(valueEquals(criteria.isAwesome(), "isAwesome"))
                .and(
                    where(
                            stringLike(query, "name"))
                        .or(stringLike(query, "instructions")
                    )
                );
    }
}
导入静态org.springframework.data.jpa.domain.Specifications.where;
导入javax.persistence.criteria.CriteriaBuilder;
导入javax.persistence.criteria.CriteriaQuery;
导入javax.persistence.criteria.Predicate;
导入javax.persistence.criteria.Root;
导入org.apache.commons.lang3.StringUtils;
导入org.springframework.data.jpa.domain.Specification;
导入com.acme.model.security.Principal;
公共类规范{
私人最终食品标准;
私有字符串查询;
公共Foo规范(字符串查询、Foo条件){
this.query=query;
本标准=标准;
}
公共规范培训资格(){
if(criteria.getTrainer()==null){
返回null;
}
返回新规范(){
@凌驾
公共谓词toPredicate(根根、CriteriaQuery查询、CriteriaBuilder cb){
返回cb.equal(root.get(“trainer”).get(“id”)、criteria.getTrainer().getId());
}
};
}
公共规范值等于(最终T值,最终字符串字段){
如果(值==null){
返回null;
}
返回新规范(){
@凌驾
公共谓词toPredicate(根根、CriteriaQuery查询、CriteriaBuilder cb){
返回cb.equal(root.get(字段),value);
}
};
}
/**
*将输入字符串转换为小写,在其周围附加“%”,并与字段值(也是小写)进行类似SQL的比较。
*如果值为null,则不进行比较。示例:
* 
*value=“约翰”;
*field=“firstName”;
* 
*结果规范=“名称类似于“%john%””
* 
*@param值字符串或null
*@param字段名
*@返回给定值的类似SQL的规范,如果值为null,则返回null
*/
公共规范stringLike(最终字符串值、最终字符串字段){
if(StringUtils.isBlank(值)){
返回null;
}
返回新规范(){
@凌驾
公共谓词toPredicate(根根、CriteriaQuery查询、CriteriaBuilder cb){
返回cb.like(cb.lower(root.get(field)),getLikePattern(value));
}
};
}
私有字符串getLikePattern(字符串搜索术语){
返回新的StringBuilder(“%”)
.append(searchTerm.toLowerCase().replaceAll(“\\*”,“%”)
.附加(“%”)
.toString();
}
公共规范fullSearch(){
返回位置(trainerEquals())
.和(valueEquals(criteria.getName(),“name”))
和(valueEquals(criteria.getInstructions(),“description”))
.和(valueEquals(criteria.isAwesome(),“isAwesome”))
.及(
在哪里(
stringLike(查询,“名称”))
.或(stringLike(查询,“说明”)
)
);
}
}

如果不在PlayerTeam中添加额外属性,则不应将其建模为实体

player.namePlayer.eq(...)


域模型是什么样子的?我已经更新了我的问题,给出了域模型的代码。什么搜索?什么连接?问题是关于
QueryDSL
not
Specifications
,但我只想选择玩家,我的PlayerTeam中有额外的字段。为什么你使用JPASubQuery()而不是playerResposition,这是findall()方法?给定的两个表达式是findAll方法的参数,您可以通过first.和(second)组合它们
import static org.springframework.data.jpa.domain.Specifications.where;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.jpa.domain.Specification;

import com.acme.model.security.Principal;

public class FooSpecification { 

    private final Foo criteria;
    private String query;

    public FooSpecification(String query, Foo criteria) {
        this.query = query;
        this.criteria = criteria;
    }

    public Specification<Foo> trainerEquals() {
        if (criteria.getTrainer() == null) {
            return null;
        }

        return new Specification<Foo>() {

            @Override
            public Predicate toPredicate(Root<Foo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.equal(root.<Principal>get("trainer").<Long>get("id"), criteria.getTrainer().getId());
            }
        };
    }

    public <T> Specification<Foo> valueEquals(final T value, final String field) {
        if (value == null) {
            return null;
        }

        return new Specification<Foo>() {

            @Override
            public Predicate toPredicate(Root<Foo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.equal(root.<T> get(field), value);
            }
        };
    }

    /**
     * Convert input string to lower case, appends '%' around it and does SQL LIKE comparison with the field value, also lower cased.
     * If value is null, no comparison is done.  Example:
     * 
     * value = "John";
     * field = "firstName";
     * 
     * resulting specification = "name like '%john%'"
     * 
     * @param value string or null
     * @param field field name
     * @return SQL LIKE specification for the given value or null if value is null
     */
    public Specification<Foo> stringLike(final String value, final String field) {
        if (StringUtils.isBlank(value)) {
            return null;
        }

        return new Specification<Foo>() {

            @Override
            public Predicate toPredicate(Root<Foo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.like(cb.lower(root.<String> get(field)), getLikePattern(value));
            }
        };
    }

    private String getLikePattern(String searchTerm) {
        return new StringBuilder("%")
                .append(searchTerm.toLowerCase().replaceAll("\\*", "%"))
                .append("%")
                .toString();
    }

    public Specification<Foo> fullSearch() {
        return where(trainerEquals())
                .and(valueEquals(criteria.getName(), "name"))
                .and(valueEquals(criteria.getInstructions(), "description"))
                .and(valueEquals(criteria.isAwesome(), "isAwesome"))
                .and(
                    where(
                            stringLike(query, "name"))
                        .or(stringLike(query, "instructions")
                    )
                );
    }
}
player.namePlayer.eq(...)
new JPASubQuery().from(playerTeam)
    .where(playerTeam.player.eq(player), palyerTeam.team.name.eq(...))
    .exists()