英文:
How to make spring data jpa generated methods throw exception on null parameters
问题
Service method:
public User findUserByEmail(String email) {
try {
Assert.notNull(email, "email is null!");
Optional<User> userOptional = userRepo.findUserDAOByEmail(email);
return userOptional.orElseThrow();
}
catch (...){
...
}
}
Repo:
public interface UserRepo extends JpaRepository<User, Long> {
Optional<User> findUserByEmail(String email);
}
我有这个调用存储库方法的服务方法,而该方法又是由Spring生成的:
服务方法:
public User findUserByEmail(String email) {
try {
Assert.notNull(email, "email为空!");
Optional<User> userOptional = userRepo.findUserDAOByEmail(email);
return userOptional.orElseThrow();
}
catch (...){
...
}
}
存储库:
public interface UserRepo extends JpaRepository<User, Long> {
Optional<User> findUserByEmail(String email);
}
我希望存储库方法像其它方法一样(与Jparepository
自带的方法一样)抛出IllegalArgumentException
,但实际上它接受了空参数“email”,在数据库中搜索并返回了不存在的用户结果(附注:根据我的模式,email不能为空)。
因此,我执行了Assert.notNull(email, "email为空!");
但我想知道是否有更好的方法来验证“email”不为空?
英文:
I have this service method which calls a repo method which is in turn generated by spring:
Service method:
public User findUserByEmail(String email) {
try {
Assert.notNull(email,"email is null!");
Optional<User> userOptional = userRepo.findUserDAOByEmail(email);
return userOptional.orElseThrow();
}
catch (...){
...
}
}
Repo:
public interface UserRepo extends JpaRepository<User, Long> {
Optional<User> findUserByEmail(String email);
}
I wanted the repo method to throw IllegalArgumentException
as its friends (the methods that come out of the box with Jparepository
do), but instead it accepted the null parameter "email" and searched for it in the database and returned a result that no such user exist (p.s.: email is constrained to be not null in my schema)
So I did Assert.notNull(email,"email is null!");
But I wonder if there is a better way to validate that "email" is not null?
答案1
得分: 2
以下是翻译好的内容:
一个约束也可以放在参数上,就像这样 -
@Validated
@Repository
public interface UserRepo extends JpaRepository<User, Long> {
Optional<User> findUserByEmail(@NotNull String email);
}
@Validated 启用 Spring 调用各种验证约束。
工作示例
Gradle 依赖项
compile 'org.springframework.boot:spring-boot-starter'
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-validation'
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile("mysql:mysql-connector-java:8.0.16")
UserRepository.java
@Validated
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findUserByName(@NotEmpty String name);
}
控制台输出
javax.validation.ConstraintViolationException: findUserByName.name: 不能为空
at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:117) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at com.sun.proxy.$Proxy88.findUserByName(Unknown Source) ~[na:na]
at com.test.validation.controller.UserController.get(UserController.java:18) ~[main/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
英文:
A constraint can be put on the parameter as well like this -
@Validated
@Repository
public interface UserRepo extends JpaRepository<User, Long> {
Optional<User> findUserByEmail(@NotNull String email);
}
@Validated enables Spring to invoke various Validation Constraints.
Working Example
gradle dependency
compile 'org.springframework.boot:spring-boot-starter'
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-validation'
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile("mysql:mysql-connector-java:8.0.16")
UserRepository.java
@Validated
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findUserByName(@NotEmpty String name);
}
Console Output
javax.validation.ConstraintViolationException: findUserByName.name: must not be empty
at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:117) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at com.sun.proxy.$Proxy88.findUserByName(Unknown Source) ~[na:na]
at com.test.validation.controller.UserController.get(UserController.java:18) ~[main/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
答案2
得分: 0
这些存储库无法直接从服务类访问,因此您需要创建一个带有@Service注解的服务类,然后实现自己的方法来使用UserRepo存储库接口查找用户,然后您可以将该服务类注入到测试单元中并进行自己的测试。
英文:
the repositories has no way to access it directly out of services classes so you need to create a service class annotated with @Service then implement your own method to find the user using the UserRepo repository interface then you can inject the service class into the testing unit and make your own tests.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论