如何在值范围内构建搜索查询?

问题描述 投票:0回答:1

我在使用标准生成器创建查询时遇到麻烦。我有 Employee 表,该表具有“SALARY”列,并且工资以以下格式保存:价值 + 货币(例如:“1000 欧元”)。我没有为此使用

@Embeddable
类。相反,我使用休眠转换器来存储和读取工资,这是我的金钱课程:

public class Money implements Comparable<Money> {
    private BigDecimal amount;
    private Currency currency;

    @Override
    public String toString() {
        return getAmount() + " " + getCurrency();
    }

    public static Money getMoneyFromString(String s) {
        String[] strings = s.split(" ");
        return new Money(new BigDecimal(strings[0]),Currency.getInstance(strings[1]));
    }

    @Override
    public int compareTo(Money o) {
        if (o.getCurrency() == null || !o.getCurrency().equals(this.currency))
            throw new IllegalArgumentException();

        return this.amount.compareTo(o.getAmount());
    }
}

这是我如何在实体类中保留此类的字段

    @NotNull
    @Convert(
            converter = MoneyConverter.class
    )
    @Column(name = "SALARY", length = 63)
    private Money salary;

问题是我不知道如何通过使用条件来构建查询来查找工资在该范围内的员工,例如:

  1. 起薪=“1000 欧元”
  2. 最终工资=“30000 欧元”
  3. 员工工资 =“1500 欧元”- 应该可以找到

我尝试过这样的:

public static Specification<Employee> isSalaryBetween(Money salaryStart, Money salaryEnd) {
        return (root, query, criteriaBuilder) -> {
            Predicate salaryBetween = criteriaBuilder.between(
                    root.get(Employee_.salary), salaryStart, salaryEnd);

            return criteriaBuilder.and(salaryBetween);
        };
    }

但这并没有返回正确的值。所以我也尝试了这样的事情:

    Predicate predicate = builder.between(
                root.get("salary").get("amount"), 
                minSalary.getAmount(), 
                maxSalary.getAmount()
            );

但这会触发异常:

org.springframework.dao.InvalidDataAccessApiUsageException: Basic paths cannot 
be dereferenced

我也尝试使用某种功能,但没有成功

那么还有什么其他可能找到薪资在一定范围内的员工呢?实现这一目标的唯一方法是更改数据库架构吗?

java spring jpa spring-data-jpa criteria
1个回答
0
投票

你可以尝试这样的事情

public static Specification<Employee> isSalaryBetween(Money salaryStart, Money salaryEnd) {
    return (root, query, criteriaBuilder) -> {
        Join<Employee, Money> salaryJoin = root.join("salary");
        
        Predicate salaryBetween = criteriaBuilder.between(
                salaryJoin.get("amount"), salaryStart.getAmount(), salaryEnd.getAmount());

        return salaryBetween;
    };
}
© www.soinside.com 2019 - 2024. All rights reserved.