【问题标题】:Multiple optional @RequestParam not fetching Data in spring boot多个可选的@RequestParam 未在 Spring Boot 中获取数据
【发布时间】:2021-06-10 04:59:58
【问题描述】:

我想在 Spring Boot 项目中对响应数据进行分页。根据业务逻辑,我添加了多个RequestParam。一切都好,如果我传递所有请求参数的值,即性别和国家。但是,如果我没有给出任何一个或两个值,我会得到 500 状态代码,尽管我将性别和国家/地区 requestParam 设为可选。这意味着,

如果我打了

http://localhost:8080/api/v1/users?page=1&country=Russia&gender=M,

我得到了分页响应。

但是如果我打了

http://localhost:8080/api/v1/users?page=1&gender=M

http://localhost:8080/api/v1/users?page=1&country=俄罗斯

http://localhost:8080/api/v1/users?page=1.

我得到异常

这是我的代码。

UserRepository.kt

@Repository
interface UserRepository: JpaRepository<User, Long> {

    @Query(
        nativeQuery = true,
        value = "SELECT * FROM user_info WHERE gender =:gender AND country =:country"
    )
    fun getUsers(gender: String?, country: String?, pageable: Pageable): Page<User>

}

UserServiceImpl.kt

@Service
class UserServiceImpl(
    @Autowired private val userRepository: UserRepository
): UserService {

    override fun getUsers(gender: String?, country: String?, pageable: Pageable): Page<User> {
        return userRepository.getUsers(gender, country, pageable)
    }

}

UserController.kt

@RestController
@RequestMapping(
    path = [
        "/api/v1/"
    ]
)
class UserController(
    @Autowired private val userService: UserService
) {

    @GetMapping("users")
    fun getUsers(
        @RequestParam(required = true) page: Int,
        @RequestParam(required = false) gender: String?,
        @RequestParam(required = false) country: String?
    ): Page<User> {
        return userService.getUsers(gender, country, PageRequest.of(page, 10))
    }

}

response

{
    "status": "500 INTERNAL_SERVER_ERROR",
    "message": "Internal server error occurs",
    "error": "could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet"
}

【问题讨论】:

  • 为国家和性别字段添加默认值。它将解决问题。
  • 对于具有不同参数的动态查询,使用谓词而不是方法来执行查询。

标签: spring spring-boot kotlin pagination


【解决方案1】:

这里最好像这样使用 jdbcTemplate:

String query = "SELECT * FROM user_info WHERE gender = :gender AND country = :country";
Map<String, Object> params = new HashMap<>();
params.put("gender", gender);
params.put("country", country);
Map<String, Long> results = new HashMap<>();
// Execute Your Query Here like: users = jdbcTemplate.query(query, params, ...

对于这些参数,您可以检查例如,gender not null 是否将 gender = :gender 附加到主查询。

【讨论】:

    【解决方案2】:

    是的,您遇到的错误是正确的,因为您的查询值不存在,我建议您进行以下更改...

    @Repository
    interface UserRepository: JpaRepository<User, Long> {
    
    @Query(
        nativeQuery = true,
        value = "SELECT * FROM user_info WHERE country =:country"
    )
    fun getUsersWithoutGender( country: String?, pageable: Pageable): Page<User>
    
     @Query(
        nativeQuery = true,
        value = "SELECT * FROM user_info WHERE gender =:gender AND country =:country"
    )
    fun getUsersWithoutCountry(gender: String?, pageable: Pageable): Page<User>
    
     @Query(
        nativeQuery = true,
        value = "SELECT * FROM user_info WHERE gender =:gender AND country =:country"
    )
    fun getUsers(gender: String?, country: String?, pageable: Pageable): Page<User>
    
    @Query(
        nativeQuery = true,
        value = "SELECT * FROM user_info"
    )
    fun getallUsers(): Page<User>
    
    }
    

    在你的控制器中

    RestController
    @RequestMapping(
    path = [
        "/api/v1/"
    ]
    )
    class UserController(
    @Autowired private val userService: UserService
    ) {
    
    @GetMapping("users")
    fun getUsers(
        @RequestParam(required = true) page: Int,
        @RequestParam(required = false) gender: String?,
        @RequestParam(required = false) country: String?
    ): Page<User> {
    
    if(country == null && gender =! null){
        return userService.getUsersWithoutCountry(gender,PageRequest.of(page, 10))
    } else if (gender== null && country =! null){
        return userService.getUsersWithoutGender(country,PageRequest.of(page, 10))
    }else if (gender && country == null){
        return userService.getAllUsers()
    }else {
        return userService.getUsers(gender, country, PageRequest.of(page, 10))    
    }
    }
    
    }
    

    这样您的所有查询都将运行,因为它们没有空值。

    【讨论】:

    • 感谢兄弟的回复。我已经写了这段代码。但我想笼统地解决这个问题。假设将来有越来越多的参数出现。那么就很难处理了
    【解决方案3】:

    最后,我通过 JpaSpecificationExecutor 解决了这个问题,它有助于创建动态查询。代码如下。

    UserSpecification.kt

    import com.example.demo.entity.User
    import org.springframework.data.jpa.domain.Specification
    import javax.persistence.criteria.CriteriaBuilder
    import javax.persistence.criteria.CriteriaQuery
    import javax.persistence.criteria.Root
    import java.text.MessageFormat.format
    
    object UserSpecification {
    
        fun countryContains(country: String?): Specification<User>? {
            return country?.let {
                Specification { root: Root<User>, _: CriteriaQuery<*>, criteriaBuilder: CriteriaBuilder ->
                    criteriaBuilder.like(root.get("country"), format("%{0}%", country))
                }
            }
        }
    
        fun genderContains(gender: String?): Specification<User>? {
            return gender?.let {
                Specification { root: Root<User>, _: CriteriaQuery<*>, criteriaBuilder: CriteriaBuilder ->
                    criteriaBuilder.equal(root.get<String>("gender"), gender)
                }
            }
        }
    
    }
    

    UserRepository.kt

    @Repository
    interface UserRepository: JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
    
    }
    

    UserServiceImpl.kt

    @Service
    class UserServiceImpl(
        @Autowired private val userRepository: UserRepository
    ): UserService {
    
        override fun getUsers(gender: String?, country: String?, pageable: Pageable): Page<User> {
            return userRepository.findAll(
                where(
                    countryContains(country)
                ).and(
                    genderContains(gender)
                ), pageable
            )
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-07-11
      • 2020-04-19
      • 1970-01-01
      • 2019-07-04
      • 2016-12-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-13
      • 2018-11-05
      相关资源
      最近更新 更多