【问题标题】:JPQL not returning null value if combined with LIKE如果与 LIKE 结合使用,JPQL 不会返回空值
【发布时间】:2022-01-04 07:24:50
【问题描述】:

您好,我是 JPA 新手,在添加到 JPA @Query 注释时难以返回空值,下面我将尝试解释我遇到的问题:

@Query("SELECT new dto.salesman.SalesmanGridDto(" +
            "sal.id, CONCAT(sal.firstName, ' ', sal.lastName), " +
            "sal.level, CONCAT(sup.firstName, ' ', sup.lastName))" +
            "FROM Salesman sal " +
            "LEFT JOIN Salesman sup ON  sal.superior = sup.id " +
            "WHERE sal.id LIKE %?1% " +
            "AND CONCAT(sal.firstName, ' ', sal.lastName) LIKE %?2% " +
            "AND sal.level LIKE %?3% ")
    public List<SalesmanGridDto> getAllSalesmen(String employeeNumber, String employeeFullName,
                                                String employeeLevel, String superiorFullName,
                                                Pageable page);

它按预期工作,并给了我优越的全名 以下是部分数据:

[
{
"salesmanEmployeeNumber": "J101",
"salesmanFullName": "Galuh Rajata",
"salesmanLevel": "Regional_Sales_Director",
"superiorFullName": null
},
{
"salesmanEmployeeNumber": "J109",
"salesmanFullName": "Wiwied Sunanto",
"salesmanLevel": "Retail_Sales",
"superiorFullName": "Banni Ayudhani"
},
{
"salesmanEmployeeNumber": "J200",
"salesmanFullName": "Angel Widyatmo",
"salesmanLevel": "Retail_Sales",
"superiorFullName": "Banni Ayudhani"
},
{
"salesmanEmployeeNumber": "J227",
"salesmanFullName": "Ulya Michele",
"salesmanLevel": "Inside_Sales_Representative",
"superiorFullName": null
}
]

但是在我为上级全名添加了新条件之后:

    @Query("SELECT new dto.salesman.SalesmanGridDto(" +
            "sal.id, CONCAT(sal.firstName, ' ', sal.lastName), " +
            "sal.level, CONCAT(sup.firstName, ' ', sup.lastName))" +
            "FROM Salesman sal " +
            "LEFT JOIN Salesman sup ON  sal.superior = sup.id " +
            "WHERE sal.id LIKE %?1% " +
            "AND CONCAT(sal.firstName, ' ', sal.lastName) LIKE %?2% " +
            "AND sal.level LIKE %?3% " +
            "AND CONCAT(sup.firstName, ' ', sup.lastName) LIKE %?4%")
    public List<SalesmanGridDto> getAllSalesmen(String employeeNumber, String employeeFullName,
                                                String employeeLevel, String superiorFullName,
                                                Pageable page);

它只给了我那些拥有优越全名的人。 (我想要的是它们也返回 null

[
{
"salesmanEmployeeNumber": "J109",
"salesmanFullName": "Wiwied Sunanto",
"salesmanLevel": "Retail_Sales",
"superiorFullName": "Banni Ayudhani"
},
{
"salesmanEmployeeNumber": "J200",
"salesmanFullName": "Angel Widyatmo",
"salesmanLevel": "Retail_Sales",
"superiorFullName": "Banni Ayudhani"
},
{
"salesmanEmployeeNumber": "J567",
"salesmanFullName": "Jill Vianto",
"salesmanLevel": "Sales_Engineer",
"superiorFullName": "Banni Ayudhani"
},
{
"salesmanEmployeeNumber": "J889",
"salesmanFullName": "Olivia Puspasari",
"salesmanLevel": "Sales_Assistant",
"superiorFullName": "Banni Ayudhani"
}
]

我使用的 DTO 如下(我使用 Lombok):

@Data
public class SalesmanGridDto implements Serializable {
    private final String salesmanEmployeeNumber;
    private final String salesmanFullName;
    private final String salesmanLevel;
    private final String superiorFullName;
}

控制器的默认值如下:

    @GetMapping
    @ResponseBody
    public List<SalesmanGridDto> getAll(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "") String employeeNumber,
            @RequestParam(defaultValue = "") String name,
            @RequestParam(defaultValue = "") String employeeLevel,
            @RequestParam(defaultValue = "") String superiorName
    ){
        return service.getAllSalesmen(page, employeeNumber, name, employeeLevel,superiorName);
    }

我很困惑为什么在添加新条件之前记录了空值 如果参数为“”,在添加新条件后如何使空值也存在? 或者,还有更好的方法?请赐教

【问题讨论】:

  • 添加附加条件(或名称为null)。它返回的正是你告诉它返回的内容。
  • @M.Deinum 嗨,先生,我想说的是我需要结果与第一个结果(显示为 JSON 数据)相同,它在 SSMS SQL Server 上工作尽管添加了新条件,它也会返回 null 值
  • 如前所述,它返回正是您告诉它返回的内容。您添加了对全名的限制,使其成为 like 的东西。 null 不是类似的东西它是null,不匹配所以不包括在内。您的初始查询没有此限制。如果您还希望返回 null,则必须在查询中写下它,而您目前还没有。
  • @M.Deinum 啊,我明白了!非常感谢您的进一步解释,我现在明白我必须做什么了:)
  • 取决于您要实现的逻辑。如果您不想在提供参数 时显示那些空行,那么您可能需要下面的自己的解决方案

标签: java sql-server spring-boot jpa


【解决方案1】:

在@M.Deinum 的帮助下,我有一个解决方案,我现在明白它必须返回一个值(不能为空)。因此我的解决方案是根据用户的输入创建 2 个查询。

这里的区别是参数。

    @Query("SELECT new com.indocyber.basilisk.dto.salesman.SalesmanGridDto(" +
            "sal.id, CONCAT(sal.firstName, ' ', sal.lastName), " +
            "sal.level, CONCAT(sup.firstName, ' ', sup.lastName))" +
            "FROM Salesman sal " +
            "LEFT JOIN Salesman sup ON  sal.superior = sup.id " +
            "WHERE sal.id LIKE %?1% " +
            "AND CONCAT(sal.firstName, ' ', sal.lastName) LIKE %?2% " +
            "AND sal.level LIKE %?3% ")
    public List<SalesmanGridDto> getAllSalesmen(String employeeNumber, String employeeFullName,
                                                String employeeLevel, Pageable page);

    @Query("SELECT new com.indocyber.basilisk.dto.salesman.SalesmanGridDto(" +
            "sal.id, CONCAT(sal.firstName, ' ', sal.lastName), " +
            "sal.level, CONCAT(sup.firstName, ' ', sup.lastName))" +
            "FROM Salesman sal " +
            "LEFT JOIN Salesman sup ON  sal.superior = sup.id " +
            "WHERE sal.id LIKE %?1% " +
            "AND CONCAT(sal.firstName, ' ', sal.lastName) LIKE %?2% " +
            "AND sal.level LIKE %?3% " +
            "AND CONCAT(sup.firstName, ' ', sup.lastName) LIKE %?4%")
    public List<SalesmanGridDto> getAllSalesmen(String employeeNumber, String employeeFullName,
                                                String employeeLevel, String superiorFullName,
                                                Pageable page);

然后在@Service 部分,我添加了以下代码:

    @Override
    public List<SalesmanGridDto> getAllSalesmen(Integer page, String employeeNumber, String name, String employeeLevel, String superiorName) {
        Pageable chosenPage = PageRequest.of((page - 1), 10);
        if (superiorName.trim().equals("")) {
            return salesmanRepository.getAllSalesmen(employeeNumber, name, employeeLevel, chosenPage);
        } else {
            return salesmanRepository.getAllSalesmen(employeeNumber, name, employeeLevel, superiorName, chosenPage);
        }
    }

我希望这对处理同样问题的人有所帮助

【讨论】:

  • 不要,只需在查询中包含 OR 子句。或者更好地使用 JPA 标准 API(或 Sprnig Data JPA JpaSpecificationExecutor 来动态构建查询,而不是为所有可能(和不可能)的组合创建大量查找器方法)。
  • @M.Deinum 我确实尝试添加AND (CONCAT(sup.firstName, ' ', sup.lastName) LIKE %?4% OR CONCAT(sup.firstName, ' ', sup.lastName) IS NULL)。它起作用了,唯一的问题是,当我设置一个参数时,它也会显示空值。我的代码中是否缺少某些内容?
  • 现在这是您在帖子中没有解释的内容。但是,如果您想动态包含参数,我强烈建议您阅读如何使用JpaSpecificationExecutor,这样可以更轻松地编写动态查询。
  • @M.Deinum 啊,很抱歉给我造成的沟通失误。我是stackoverflow的新手,对我提供冗余信息有点紧张。好的,看起来令人兴奋!我会试一试..再次感谢您的持续咨询我真的很感激! :)
【解决方案2】:

在选择时应该使用大小写,而不是添加 where 条件

【讨论】:

  • 嗨! cmiiw 但查询不能使用“用例”,因为它来自 T-SQL,JPQL 只理解 SQL
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-15
  • 1970-01-01
  • 2018-05-28
  • 2020-12-30
  • 2013-10-01
  • 1970-01-01
相关资源
最近更新 更多