我可以将列表作为参数传递给MyBatis映射器吗? [英] Can I pass a List as a parameter to a MyBatis mapper?
问题描述
我正在尝试在MyBatis中定义一个简单的@Select
批注,以基于由IN子句定义的条件来获取对象的集合. SQL看起来像:
I'm trying to define a simple @Select
annotation in MyBatis to get a collection of objects based on criteria defined by an IN clause. The SQL looks something like:
SELECT * FROM employees WHERE employeeID IN (1, 2, 3);
该列表是动态生成的,因此我不知道它将具有多少个参数.我只想传递List
值,例如:
The list is generated dynamically, so I don't know how many parameters it will have. I'd like to just pass in a List
of values, something like:
@Select("SELECT * FROM employees WHERE employeeID IN( #{employeeIds} )")
List<Employee> selectSpecificEmployees(@Param("employeeIds") List<Integer> employeeIds);
我正在创建Mapper
的实例,在其中定义了上面的注释,并按如下方式调用它:
I'm creating an instance of the Mapper
where the annotation above is defined and calling it as follows:
List<Integer> empIds = Arrays.asList(1, 2, 3);
List<Employee> result = mapper.selectSpecificEmployees(empIds);
我发现这行不通.
org.apache.ibatis.exceptions.PersistenceException:
###查询数据库时出错.原因:java.lang.NullPointerException
###错误可能涉及
com.mycompany.MySourceMapper.selectSpecificEmployees-Inline
###设置参数时发生错误 ###原因:java.lang.NullPointerException 在org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:8) 在org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:77) 在org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:69) 在org.apache.ibatis.binding.MapperMethod.executeForList(MapperMethod.java:85) 在org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:65) 在org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:35) 在$ Proxy23.selectSpecificProductTypes(未知来源) 在com.mycompany.MySourceMapperDebug.testSelectSpecificEmployees(MySourceMapperDebug.java:60) 在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处 在sun.reflect.NativeMethodAccessorImpl.invoke(未知来源) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源) 在java.lang.reflect.Method.invoke(未知来源) 在junit.framework.TestCase.runTest(TestCase.java:154) 在junit.framework.TestCase.runBare(TestCase.java:127) 在junit.framework.TestResult $ 1.protect(TestResult.java:106) 在junit.framework.TestResult.runProtected(TestResult.java:124) 在junit.framework.TestResult.run(TestResult.java:109) 在junit.framework.TestCase.run(TestCase.java:118) 在junit.framework.TestSuite.runTest(TestSuite.java:208) 在junit.framework.TestSuite.run(TestSuite.java:203) 在org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130) 在org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)上 在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 造成原因:java.lang.NullPointerException 在org.apache.ibatis.type.UnknownTypeHandler.setNonNullParameter(UnknownTypeHandler.java:21) 在org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:23) 在org.apache.ibatis.executor.parameter.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:73) 在org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:61)上 在org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:43) 在org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:56) 在org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:40) 在org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:216) 在org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:95) 在org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:72) 在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处 在sun.reflect.NativeMethodAccessorImpl.invoke(未知来源) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源) 在java.lang.reflect.Method.invoke(未知来源) 在org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:31)
...另外36个
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.NullPointerException
### The error may involve
com.mycompany.MySourceMapper.selectSpecificEmployees-Inline
### The error occurred while setting parameters ### Cause: java.lang.NullPointerException at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:8) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:77) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:69) at org.apache.ibatis.binding.MapperMethod.executeForList(MapperMethod.java:85) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:65) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:35) at $Proxy23.selectSpecificProductTypes(Unknown Source) at com.mycompany.MySourceMapperDebug.testSelectSpecificEmployees(MySourceMapperDebug.java:60) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at junit.framework.TestCase.runTest(TestCase.java:154) at junit.framework.TestCase.runBare(TestCase.java:127) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:118) at junit.framework.TestSuite.runTest(TestSuite.java:208) at junit.framework.TestSuite.run(TestSuite.java:203) at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: java.lang.NullPointerException at org.apache.ibatis.type.UnknownTypeHandler.setNonNullParameter(UnknownTypeHandler.java:21) at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:23) at org.apache.ibatis.executor.parameter.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:73) at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:61) at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:43) at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:56) at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:40) at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:216) at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:95) at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:72) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:31)
... 36 more
我认为问题出在注释本身.这似乎是一个相当普遍的要求.我是否需要自己将List
转换为String
并将其作为String
参数而不是List<Integer>
传递?还是有其他语法可以将List
作为参数传递给MyBatis批注?
I think the problem is in the annotation itself. This seems like it would be a fairly common requirement. Do I need to convert the List
to a String
myself and pass that in as a String
parameter instead of a List<Integer>
? Or is there some other syntax for passing a List
as a parameter to a MyBatis annotation?
推荐答案
我以前从未使用过注解和MyBatis.我一直走过xml配置文件路由(不是暗示使用批注有什么问题;只是在解释我不能为您提供帮助).
I've never used annotations and MyBatis before; I've always gone the xml configuration file route (not implying there is anything wrong with using annotations; just explaining I can't help you there).
话虽如此,《 MyBatis用户指南》中的第46页:
That being said, page 46 from the MyBatis user guide:
foreach
动态SQL的另一个常见需求是需要迭代一个 收集时,通常会建立一个IN条件.例如:
Another common necessity for dynamic SQL is the need to iterate over a collection, often to build an IN condition. For example:
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
foreach元素非常强大,可让您指定一个 收集,声明可以在内部使用的项目和索引变量 元素的主体.它还允许您指定打开和 关闭字符串,并添加一个分隔符以放置在两次迭代之间. 该元素很聪明,因为它不会意外地添加额外的内容 分隔符.
The foreach element is very powerful, and allows you to specify a collection, declare item and index variables that can be used inside the body of the element. It also allows you to specify opening and closing strings, and add a separator to place in between iterations. The element is smart in that it won’t accidentally append extra separators.
这篇关于我可以将列表作为参数传递给MyBatis映射器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!