#java #spring-boot #mybatis
Вопрос:
Я работаю над приложением springboot, в котором mybatis вызывает хранимую процедуру DB2, и эта хранимая процедура возвращает 2 набора результатов: и для каждого набора результатов я определил модель(Fruit.java и Animal.java)
набор результатов #1
ID | Имя | кол-во |
---|---|---|
1 | Apple | 2 |
2 | Оранжевый | 3 |
3 | банан | 5 |
набор результатов #2
Тип | номер | ЛОК |
---|---|---|
обезьяна | 2000 | Лондон |
собака | 3000 | НЬЮ-ЙОРК |
кошка | 8000 | LA |
в MyMapper.java, каким должен быть мой тип результата?
Я пытался:
@Select(Value = "{call ....})
@Options(StatementType = StatementType.CALLABLE)
@Results({
@Result(property="id", column="ID",
@Result(property="name", column="NAME",
@Result(property="qty", column="QTY" })
List<Fruit> getFruits(Map<String, String> params);
@Select(Value = "{call ....})
@Options(StatementType = StatementType.CALLABLE)
@Results({
@Result(property="type", column="TYPE",
@Result(property="num", column="NUM",
@Result(property="loc", column="LOC"
})
List<Animal> getAnimals(Map<String, String> params);
что не сработало, я получил результирующий набор #1 таким образом, но не получил результирующий набор #2 (все поля из результирующего набора#2 вернулись пустыми) .
Я тоже пытался:
@Select(Value = "{call ....})
@Options(StatementType = StatementType.CALLABLE)
List<?> getResultSets(Map<String, String> params);
и:
@Select(Value = "{call ....})
@Options(StatementType = StatementType.CALLABLE)
List<List<?>> getResultSets(Map<String, String> params);
Для обоих я получил «java.lang.Исключение UnsupportedOperationException»:
Caused by: java.lang.UnsupportedOperationException
at org.apache.ibatis.reflection.wrapper.CollectionWrapper.findProperty(CollectionWrapper.java:42)
at org.apache.ibatis.reflection.MetaObject.findProperty(MetaObject.java:76)
at org.apache.ibatis.executor.resultset.FastResultSetHandler.applyAutomaticMappings(FastResultSetHandler.java:342)
at org.apache.ibatis.executor.resultset.FastResultSetHandler.getRowValue(FastResultSetHandler.java:267)
at org.apache.ibatis.executor.resultset.FastResultSetHandler.handleRowValues(FastResultSetHandler.java:216)
at org.apache.ibatis.executor.resultset.FastResultSetHandler.handleResultSet(FastResultSetHandler.java:188)
at org.apache.ibatis.executor.resultset.FastResultSetHandler.handleResultSets(FastResultSetHandler.java:154)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:57)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:70)
at org.apache.ibatis.executor.ReuseExecutor.doQuery(ReuseExecutor.java:54)
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:259)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:132)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:105)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:81)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:104)
Google говорит, что это потому, что я должен использовать конкретный тип вместо дженериков.
Но результирующие наборы бывают разных типов: Список фруктов и Список животных , что мне делать?
Я использую все аннотации и не использую xml для mybatis. в pom.xml Я использую mybatis-spring-boot-starter, если это поможет.
Я застрял на этом навсегда. Спасибо.
Ответ №1:
Я проверил это с помощью следующей процедуры.
Она принимает два параметра и возвращает результаты fruit
сначала, затем animal
.
Дайте мне знать, если вам нужно, чтобы я внес некоторые коррективы.
create or replace procedure test_proc (
in p1 varchar(20),
in p2 varchar(20)
)
dynamic result sets 2
begin
declare c1 cursor with return to caller for
select * from animal;
declare c2 cursor with return to caller for
select * from fruit;
open c2;
open c1;
end
Метод Java-картографа будет выглядеть следующим образом.
Поскольку вы получаете два набора результатов, вам необходимо указать две карты результатов в @ResultMap
.
Обратите внимание, что порядок имеет значение.
@Select("{call test_proc(#{p1,mode=IN,jdbcType=VARCHAR},#{p2,mode=IN,jdbcType=VARCHAR})}")
@Options(statementType = StatementType.CALLABLE)
@ResultMap("fruitResultMap,animalResultMap")
List<List<?>> execProc(Map<String, String> params);
Возвращаемый список содержит два списка. Первый есть List<Fruit>
, а второй есть List<Animal>
.
Теперь, чтобы определить эти карты результатов без XML-картографа, вам нужно объявить дополнительные методы.
@Results(id = "fruitResultMap", value = {
@Result(property = "id", column = "ID"),
@Result(property = "name", column = "NAME"),
@Result(property = "qty", column = "QTY")
})
@Select("select * from fruit")
List<Fruit> getFruits();
@Results(id = "animalResultMap", value = {
@Result(property = "type", column = "TYPE"),
@Result(property = "num", column = "NUM"),
@Result(property = "loc", column = "LOC")
})
@Select("select * from animal")
List<Animal> getAnimals();
А вот исполняемый демо-проект:
https://github.com/harawata/mybatis-issues/tree/master/so-69145531
Комментарии:
1. Большое вам спасибо !!! Ты просто спасатель! в моей ситуации я заменил имена таблиц именами курсоров, и Вуаля, я получил два набора результатов.