Java IllegalArgumentException:类型不能为null
我正面临一个问题,似乎很多人都遇到了,而且可能无法解决它 我有以下MYSQL存储过程。这只是一个示例,看看是否一切正常,然后我会开始添加参数,如Java IllegalArgumentException:类型不能为null,java,mysql,spring,hibernate,jpa,Java,Mysql,Spring,Hibernate,Jpa,我正面临一个问题,似乎很多人都遇到了,而且可能无法解决它 我有以下MYSQL存储过程。这只是一个示例,看看是否一切正常,然后我会开始添加参数,如inactive CREATE DEFINER=`root`@`localhost` PROCEDURE `get_resource_types`() BEGIN SELECT * FROM resource_types WHERE inactive = 0; END 映射资源类型表和命名存储过程查询的实体 @NamedStor
inactive
CREATE DEFINER=`root`@`localhost` PROCEDURE `get_resource_types`()
BEGIN
SELECT *
FROM resource_types
WHERE inactive = 0;
END
映射资源类型
表和命名存储过程查询的实体
@NamedStoredProcedureQuery(
name="getResourceTypes",
procedureName="get_resource_types",
resultClasses = ResourceType.class,
parameters = {}
)
@Entity
@Table(name = "resource_types")
public class ResourceType {
... fields with annotations used for validation + getters and setters ...
}
这是我的JpaRepository
,我从中调用存储过程
@Repository
public interface ResourceTypeRepository extends JpaRepository<ResourceType, Long> {
@Procedure("ResourceType.getResourceTypes")
List<ResourceType> getResourceTypes();
}
当我尝试运行此命令时,会得到以下堆栈跟踪:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Type cannot be null; nested exception is java.lang.IllegalArgumentException: Type cannot be null
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:144)
at com.test.ihbs.controller.ResourceTypeControllerTest.test_getAll(ResourceTypeControllerTest.java:111)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:64)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:360)
at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Type cannot be null; nested exception is java.lang.IllegalArgumentException: Type cannot be null
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:381)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy87.getResourceTypes(Unknown Source)
at com.ihbs.service.ResourceTypeService.getAll(ResourceTypeService.java:34)
at com.ihbs.controller.ResourceTypeController.getAllResourceTypes(ResourceTypeController.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
... 58 more
Caused by: java.lang.IllegalArgumentException: Type cannot be null
at org.hibernate.procedure.internal.AbstractParameterRegistrationImpl.setHibernateType(AbstractParameterRegistrationImpl.java:182)
at org.hibernate.procedure.internal.AbstractParameterRegistrationImpl.<init>(AbstractParameterRegistrationImpl.java:131)
at org.hibernate.procedure.internal.AbstractParameterRegistrationImpl.<init>(AbstractParameterRegistrationImpl.java:140)
at org.hibernate.procedure.internal.AbstractParameterRegistrationImpl.<init>(AbstractParameterRegistrationImpl.java:77)
at org.hibernate.procedure.internal.PositionalParameterRegistration.<init>(PositionalParameterRegistration.java:41)
at org.hibernate.procedure.internal.ProcedureCallImpl.registerParameter(ProcedureCallImpl.java:275)
at org.hibernate.jpa.internal.StoredProcedureQueryImpl.registerStoredProcedureParameter(StoredProcedureQueryImpl.java:128)
at org.springframework.data.jpa.repository.query.StoredProcedureJpaQuery.newAdhocStoredProcedureQuery(StoredProcedureJpaQuery.java:147)
at org.springframework.data.jpa.repository.query.StoredProcedureJpaQuery.createStoredProcedure(StoredProcedureJpaQuery.java:110)
at org.springframework.data.jpa.repository.query.StoredProcedureJpaQuery.doCreateQuery(StoredProcedureJpaQuery.java:68)
at org.springframework.data.jpa.repository.query.StoredProcedureJpaQuery.createQuery(StoredProcedureJpaQuery.java:58)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$ProcedureExecution.doExecute(JpaQueryExecution.java:295)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:74)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:97)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:88)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:395)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:373)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$DefaultMethodInvokingMethodInterceptor.invoke(RepositoryFactorySupport.java:486)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 80 more
更新2
我没有使用EclipseLink(或者至少我不知道他的存在)
更新3
我无法找到这个问题的原因,即使我通过代码调试。但我发现了一些可能有助于发现问题的东西
我在org/springframework/data/jpa/repository/query/StoredProcedureJpaQuery.java中找到了这段代码,如果您注意到最后一行有一个函数调用,它获取参数总数并添加一个额外的参数。这里可能有问题,额外的参数。不过,这可能不是问题所在,因为我认为在不同的情况下,它可能会走另一条路
/**
* Extracts the output value from the given {@link StoredProcedureQuery}.
*
* @param storedProcedureQuery must not be {@literal null}.
* @return
*/
Object extractOutputValue(StoredProcedureQuery storedProcedureQuery) {
Assert.notNull(storedProcedureQuery, "StoredProcedureQuery must not be null!");
if (!procedureAttributes.hasReturnValue()) {
return null;
}
if (StringUtils.hasText(procedureAttributes.getOutputParameterName())) {
return storedProcedureQuery.getOutputParameterValue(procedureAttributes.getOutputParameterName());
}
return storedProcedureQuery.getOutputParameterValue(getQueryMethod().getParameters().getNumberOfParameters() + 1);
}
映射结果时出现问题(无法键入结果实体)
尝试更改:
@Procedure("ResourceType.getResourceTypes")
List<ResourceType> getResourceTypes();
并删除NamedStoredProcess中的ResultClass
希望有帮助。Spring Data JPA从1.11.1起不支持SPs返回结果集。我提交了Spring的数据
解决方案是降低API级别,只使用JPA。下面是我编写的一个通用类,它与MS SQL SPs一起工作
import com.google.common.base.Strings;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.ParameterMode;
import javax.persistence.Query;
import javax.persistence.StoredProcedureQuery;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class StoredProcRepository {
//region Injected beans (via a RequiredArgsConstructor)
private final EntityManager em;
//endregion
/**
* Calls a stored procedure via JPA and retrieves a single implicit result set (in DBs that
* support them e.g. MS SQL or MySQL). The call is not dependent on a DB dialect. Be
* aware that large result sets should be paginated and not entirely read to memory. Recreates
* StoredProcedureQuery instance and its parameters on each call.
* To execute MS SQL SPs performing multiple queries, SET NOCOUNT ON.
*
* @param procedureName stored procedure name, optionally qualified per DB syntax
* @param resultClass converts (maps) each result set row into instances of resultClass via JPA
* @param spArgs stored procedure arguments, supplied positionally (optional SP arguments at the
* end of the list could be omitted)
* @param <T> class of row instances converted per JPA
* @return the entire result set
*/
public <T> List<T> queryViaStoredProc(String procedureName, Class<T> resultClass,
Object... spArgs) {
StoredProcedureQuery spq = em.createStoredProcedureQuery(procedureName, resultClass);
int pos = 0;
for (Object arg : spArgs) {
spq.registerStoredProcedureParameter(++pos, arg.getClass(), ParameterMode.IN);
spq.setParameter(pos, arg);
}
return spq.getResultList();
}
/**
* Calls a stored procedure via JPA and retrieves only the top row of a single implicit result
* set (in DBs that support them e.g. MS SQL or MySQL).
* Assumes that result set has at least one row.
* The call is not dependent on a DB dialect.
* Be aware that large result sets should be paginated and not entirely read to memory.
* Recreates StoredProcedureQuery instance and its parameters on each call.
* To execute MS SQL SPs performing multiple queries, SET NOCOUNT ON.
*
* @param procedureName stored procedure name, optionally qualified per DB syntax
* @param resultClass converts (maps) each result set row into instances of resultClass via JPA
* @param spArgs stored procedure arguments, supplied positionally (optional SP arguments at the
* end of the list could be omitted)
* @param <T> class of row instances converted per JPA
* @return the entire result set
*/
public <T> T queryTopRowViaStoredProc(String procedureName, Class<T> resultClass,
Object... spArgs) {
return queryViaStoredProc(procedureName, resultClass, spArgs).get(0);
}
}
我有相同的错误,通过将ParameterMode.OUT更改为
ParameterMode.REF_光标。
我写错了
query.registerStoredProcedureParameter(12,ResultSet.class,ParameterMode.OUT)代码>
query.registerStoredProcedureParameter(12,ResultSet.class,ParameterMode.REF\u游标)代码>您可以尝试这两种方法
换行
@过程(“ResourceType.getResourceTypes”)
列出getResourceTypes()
像这样
List<ResourceType> getResourceTypes(); // because as per JPA if your method name matches with the @NamedStoredProcedure -> name then no need to mention @Procedure annotation.
@Procedure(name="getResourceTypes")
List<ResourceType> getResourceTypes();
列出getResourceTypes();//因为根据JPA,如果您的方法名称和@NamedStoredProcedure->name匹配,则无需提及@Procedure注释。
如果要使用@Procedure annotation,请更改以下行
@过程(“ResourceType.getResourceTypes”)
列出getResourceTypes()
像这样
List<ResourceType> getResourceTypes(); // because as per JPA if your method name matches with the @NamedStoredProcedure -> name then no need to mention @Procedure annotation.
@Procedure(name="getResourceTypes")
List<ResourceType> getResourceTypes();
@过程(name=“getResourceTypes”)
列出getResourceTypes();
问题可能是,如果没有参数,为什么Spring“StoredProcedureJpaQuery.newAdhocStoredProcedureQuery”会调用“StoredProcedureQuery.registerStoredProcedureParameter”?也许您应该深入研究Spring源代码并对其进行调试?您是否尝试过删除@namedStoredProcedureRequesty
定义中的(可选)参数
?是的,我尝试过删除它们,并且得到了相同的结果。是否需要有一个参数?我感觉系统需要一个参数,如OUT
或REF\u游标
。您是否找到了解决此问题的方法?不,我没有。在遇到这个问题并试图找到一个解决方案大约一周后,我决定选择纯JDBC。MS SQL SP也有同样的问题。切换到列表和无结果类并没有解决这个问题。我面临着同样的问题,简直疯了。只需在@Procedure注释中添加“name=”。细微的差别让我浪费了几个小时。。。
List<ResourceType> getResourceTypes(); // because as per JPA if your method name matches with the @NamedStoredProcedure -> name then no need to mention @Procedure annotation.
@Procedure(name="getResourceTypes")
List<ResourceType> getResourceTypes();