多个可选的@RequestParam 未在 spring 引导中获取数据
Multiple optional @RequestParam not fetching Data in spring boot
我想对 Spring 引导项目中的响应数据进行分页。根据业务逻辑,我添加了多个RequestParam。一切正常,如果我为所有请求参数传递值,即性别和国家/地区。但是,如果我不给一个或两个值,我会得到 500 状态代码,尽管我将性别和国家/地区请求参数设置为可选。这意味着,
如果我命中
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"
}
这里使用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 是否不为 null 将 gender = :gender 附加到主查询。
是的,您得到的错误是正确的,因为您的查询值不存在我建议您进行以下更改...
@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))
}
}
}
这样您的所有查询都会 运行 因为它们没有空值。
最后,我通过帮助创建动态查询的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
)
}
}
我想对 Spring 引导项目中的响应数据进行分页。根据业务逻辑,我添加了多个RequestParam。一切正常,如果我为所有请求参数传递值,即性别和国家/地区。但是,如果我不给一个或两个值,我会得到 500 状态代码,尽管我将性别和国家/地区请求参数设置为可选。这意味着,
如果我命中
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"
}
这里使用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 是否不为 null 将 gender = :gender 附加到主查询。
是的,您得到的错误是正确的,因为您的查询值不存在我建议您进行以下更改...
@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))
}
}
}
这样您的所有查询都会 运行 因为它们没有空值。
最后,我通过帮助创建动态查询的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
)
}
}