11/*
2- * Copyright 2009-2023 the original author or authors.
2+ * Copyright 2009-2024 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1616package org .apache .ibatis .executor .resultset ;
1717
1818import static org .junit .jupiter .api .Assertions .assertEquals ;
19+ import static org .junit .jupiter .api .Assertions .assertNull ;
1920import static org .mockito .ArgumentMatchers .any ;
2021import static org .mockito .Mockito .mock ;
2122import static org .mockito .Mockito .when ;
@@ -130,6 +131,74 @@ void shouldThrowExceptionWithColumnName() throws Exception {
130131 }
131132 }
132133
134+ @ Test
135+ void shouldNormallyWhenHasNoArgsConstructor () throws Exception {
136+ Class <ResultClassNoArgsConstructor > resultTypeClazz = ResultClassNoArgsConstructor .class ;
137+ final DefaultResultSetHandler fastResultSetHandler = getDefaultResultSetHandler (resultTypeClazz );
138+ final List <Object > results = fastResultSetHandler .handleResultSets (stmt );
139+ assertEquals (1 , results .size ());
140+
141+ ResultClassNoArgsConstructor result = resultTypeClazz .cast (results .get (0 ));
142+ assertEquals (10 , result .id );
143+ assertEquals ("tom" , result .name );
144+ assertNull (result .gender );
145+ }
146+
147+ @ Test
148+ void shouldNormallyWhenHasNoArgsAndAllArgsConstructor () throws Exception {
149+ Class <ResultClassNoArgsAndAllArgsConstructor > resultTypeClazz = ResultClassNoArgsAndAllArgsConstructor .class ;
150+ final DefaultResultSetHandler fastResultSetHandler = getDefaultResultSetHandler (resultTypeClazz );
151+ final List <Object > results = fastResultSetHandler .handleResultSets (stmt );
152+ assertEquals (1 , results .size ());
153+
154+ ResultClassNoArgsAndAllArgsConstructor result = resultTypeClazz .cast (results .get (0 ));
155+ assertEquals (10 , result .id );
156+ assertEquals ("tom" , result .name );
157+ assertNull (result .gender );
158+ }
159+
160+ @ Test
161+ void shouldThrowExceptionWithConstructorParameterMismatch () throws Exception {
162+
163+ final Configuration config = new Configuration ();
164+ MappedStatement ms = new MappedStatement .Builder (config , "testSelect" ,
165+ new StaticSqlSource (config , "some select statement" ), SqlCommandType .SELECT ).resultMaps (new ArrayList <>() {
166+ private static final long serialVersionUID = 1L ;
167+ {
168+ add (new ResultMap .Builder (config , "testMap" , ResultClassOnlyHasAllArgsConstructor .class ,
169+ Collections .emptyList ()).build ());
170+ }
171+ }).build ();
172+
173+ final Executor executor = null ;
174+ final ParameterHandler parameterHandler = null ;
175+ final ResultHandler resultHandler = null ;
176+ final BoundSql boundSql = null ;
177+ final RowBounds rowBounds = new RowBounds (0 , 100 );
178+ final DefaultResultSetHandler fastResultSetHandler = new DefaultResultSetHandler (executor , ms , parameterHandler ,
179+ resultHandler , boundSql , rowBounds );
180+
181+ when (stmt .getResultSet ()).thenReturn (rs );
182+ when (rs .getMetaData ()).thenReturn (rsmd );
183+ when (rs .getType ()).thenReturn (ResultSet .TYPE_FORWARD_ONLY );
184+ when (rs .next ()).thenReturn (true ).thenReturn (false );
185+ when (rsmd .getColumnCount ()).thenReturn (2 );
186+ when (rsmd .getColumnLabel (1 )).thenReturn ("id" );
187+ when (rsmd .getColumnType (1 )).thenReturn (Types .INTEGER );
188+ when (rsmd .getColumnClassName (1 )).thenReturn (Integer .class .getCanonicalName ());
189+ when (rsmd .getColumnLabel (2 )).thenReturn ("name" );
190+ when (rsmd .getColumnType (2 )).thenReturn (Types .VARCHAR );
191+ when (rsmd .getColumnClassName (2 )).thenReturn (String .class .getCanonicalName ());
192+ try {
193+ fastResultSetHandler .handleResultSets (stmt );
194+ } catch (Exception e ) {
195+ Assertions .assertTrue (e instanceof ExecutorException , "Expected ExecutorException" );
196+ Assertions .assertTrue (e .getMessage ().contains ("No constructor found in" ));
197+ ResultSetWrapper resultSetWrapper = new ResultSetWrapper (rs , config );
198+ Assertions .assertTrue (e .getMessage ().contains ("matching " + resultSetWrapper .getClassNames ()));
199+ }
200+ }
201+
133202 MappedStatement getMappedStatement () {
134203 final Configuration config = new Configuration ();
135204 final TypeHandlerRegistry registry = config .getTypeHandlerRegistry ();
@@ -148,4 +217,109 @@ MappedStatement getMappedStatement() {
148217 }).build ();
149218 }
150219
220+ DefaultResultSetHandler getDefaultResultSetHandler (Class <?> clazz ) throws SQLException {
221+ final Configuration config = new Configuration ();
222+ MappedStatement ms = new MappedStatement .Builder (config , "testSelect" ,
223+ new StaticSqlSource (config , "some select statement" ), SqlCommandType .SELECT ).resultMaps (new ArrayList <>() {
224+ private static final long serialVersionUID = 1L ;
225+ {
226+ add (new ResultMap .Builder (config , "testMap" , clazz , Collections .emptyList ()).build ());
227+ }
228+ }).build ();
229+
230+ final Executor executor = null ;
231+ final ParameterHandler parameterHandler = null ;
232+ final ResultHandler resultHandler = null ;
233+ final BoundSql boundSql = null ;
234+ final RowBounds rowBounds = new RowBounds (0 , 100 );
235+ final DefaultResultSetHandler fastResultSetHandler = new DefaultResultSetHandler (executor , ms , parameterHandler ,
236+ resultHandler , boundSql , rowBounds );
237+
238+ when (stmt .getResultSet ()).thenReturn (rs );
239+ when (rs .getMetaData ()).thenReturn (rsmd );
240+ when (rs .getType ()).thenReturn (ResultSet .TYPE_FORWARD_ONLY );
241+ when (rs .next ()).thenReturn (true ).thenReturn (false );
242+ when (rs .getInt ("id" )).thenReturn (10 );
243+ when (rs .getString ("name" )).thenReturn ("tom" );
244+ when (rsmd .getColumnCount ()).thenReturn (2 );
245+ when (rsmd .getColumnLabel (1 )).thenReturn ("id" );
246+ when (rsmd .getColumnType (1 )).thenReturn (Types .INTEGER );
247+ when (rsmd .getColumnClassName (1 )).thenReturn (Integer .class .getCanonicalName ());
248+ when (rsmd .getColumnLabel (2 )).thenReturn ("name" );
249+ when (rsmd .getColumnType (2 )).thenReturn (Types .VARCHAR );
250+ when (rsmd .getColumnClassName (2 )).thenReturn (String .class .getCanonicalName ());
251+ when (stmt .getConnection ()).thenReturn (conn );
252+ when (conn .getMetaData ()).thenReturn (dbmd );
253+ when (dbmd .supportsMultipleResultSets ()).thenReturn (false ); // for simplicity.
254+
255+ return fastResultSetHandler ;
256+ }
257+
258+ static class ResultClassNoArgsConstructor {
259+ private int id ;
260+ private String name ;
261+ private String gender ;
262+
263+ public void setId (int id ) {
264+ this .id = id ;
265+ }
266+
267+ public void setName (String name ) {
268+ this .name = name ;
269+ }
270+
271+ public void setGender (String gender ) {
272+ this .gender = gender ;
273+ }
274+ }
275+
276+ static class ResultClassNoArgsAndAllArgsConstructor {
277+ private int id ;
278+ private String name ;
279+ private String gender ;
280+
281+ public ResultClassNoArgsAndAllArgsConstructor () {
282+ }
283+
284+ public ResultClassNoArgsAndAllArgsConstructor (int id , String name ) {
285+ this .id = id ;
286+ this .name = name ;
287+ }
288+
289+ public void setId (int id ) {
290+ this .id = id ;
291+ }
292+
293+ public void setName (String name ) {
294+ this .name = name ;
295+ }
296+
297+ public void setGender (String gender ) {
298+ this .gender = gender ;
299+ }
300+ }
301+
302+ static class ResultClassOnlyHasAllArgsConstructor {
303+ private int id ;
304+ private String name ;
305+ private String gender ;
306+
307+ public ResultClassOnlyHasAllArgsConstructor (int id , String name , String gender ) {
308+ this .id = id ;
309+ this .name = name ;
310+ this .gender = gender ;
311+ }
312+
313+ public void setId (int id ) {
314+ this .id = id ;
315+ }
316+
317+ public void setName (String name ) {
318+ this .name = name ;
319+ }
320+
321+ public void setGender (String gender ) {
322+ this .gender = gender ;
323+ }
324+ }
151325}
0 commit comments