View Javadoc
1   /**
2    *    Copyright 2009-2020 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.apache.ibatis.submitted.member_access;
17  
18  import static org.junit.jupiter.api.Assertions.*;
19  
20  import java.io.Reader;
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  import org.apache.ibatis.annotations.Arg;
25  import org.apache.ibatis.annotations.ConstructorArgs;
26  import org.apache.ibatis.annotations.Result;
27  import org.apache.ibatis.annotations.Results;
28  import org.apache.ibatis.annotations.Select;
29  import org.apache.ibatis.io.Resources;
30  import org.apache.ibatis.session.SqlSession;
31  import org.apache.ibatis.session.SqlSessionFactory;
32  import org.apache.ibatis.session.SqlSessionFactoryBuilder;
33  import org.junit.jupiter.api.BeforeAll;
34  import org.junit.jupiter.api.Test;
35  
36  /**
37   * Tests for member access of Java Object.
38   */
39  class MemberAccessTest {
40  
41    private static SqlSessionFactory sqlSessionFactory;
42  
43    @BeforeAll
44    static void setUp() throws Exception {
45      try (Reader reader = Resources
46          .getResourceAsReader("org/apache/ibatis/submitted/member_access/mybatis-config.xml")) {
47        sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
48        sqlSessionFactory.getConfiguration().addMapper(Mapper.class);
49      }
50    }
51  
52    @Test
53    void parameterMappingAndResultAutoMapping() {
54      try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
55        Mapper mapper = sqlSession.getMapper(Mapper.class);
56  
57        Params params = new Params();
58        Bean bean = mapper.resultAutoMapping(params);
59  
60        assertEquals(params.privateField, bean.privateField);
61        assertEquals(params.packagePrivateField, bean.packagePrivateField);
62        assertEquals(params.protectedField, bean.protectedField);
63        assertEquals(params.publicField, bean.publicField);
64        assertEquals(params.getPrivateProperty(), bean.properties.get("privateProperty"));
65        assertEquals(params.getPackagePrivateProperty(),
66            bean.properties.get("packagePrivateProperty"));
67        assertEquals(params.getProtectedProperty(), bean.properties.get("protectedProperty"));
68        assertEquals(params.getPublicProperty(), bean.properties.get("publicProperty"));
69      }
70    }
71  
72    @Test // gh-1258
73    void parameterMappingAndResultAutoMappingUsingOgnl() {
74      try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
75        Mapper mapper = sqlSession.getMapper(Mapper.class);
76  
77        Params params = new Params();
78        Bean bean = mapper.resultAutoMappingUsingOgnl(params);
79  
80        assertEquals(params.privateField + "%", bean.privateField);
81        assertEquals(params.packagePrivateField + "%", bean.packagePrivateField);
82        assertEquals(params.protectedField + "%", bean.protectedField);
83        assertEquals(params.publicField + "%", bean.publicField);
84        assertEquals(params.getPrivateProperty() + "%", bean.properties.get("privateProperty"));
85        assertEquals(params.getPackagePrivateProperty() + "%",
86            bean.properties.get("packagePrivateProperty"));
87        assertEquals(params.getProtectedProperty() + "%", bean.properties.get("protectedProperty"));
88        assertEquals(params.getPublicProperty() + "%", bean.properties.get("publicProperty"));
89      }
90    }
91  
92    @Test
93    void parameterMappingAndResultMapping() {
94      try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
95        Mapper mapper = sqlSession.getMapper(Mapper.class);
96  
97        Params params = new Params();
98        Bean bean = mapper.resultMapping(params);
99  
100       assertEquals(params.privateField, bean.privateField);
101       assertEquals(params.packagePrivateField, bean.packagePrivateField);
102       assertEquals(params.protectedField, bean.protectedField);
103       assertEquals(params.publicField, bean.publicField);
104       assertEquals(params.getPrivateProperty(), bean.properties.get("privateProperty"));
105       assertEquals(params.getPackagePrivateProperty(),
106           bean.properties.get("packagePrivateProperty"));
107       assertEquals(params.getProtectedProperty(), bean.properties.get("protectedProperty"));
108       assertEquals(params.getPublicProperty(), bean.properties.get("publicProperty"));
109     }
110   }
111 
112   @Test
113   void constructorAutoMapping() {
114     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
115       Mapper mapper = sqlSession.getMapper(Mapper.class);
116 
117       {
118         Immutable immutable = mapper.privateConstructorAutoMapping();
119         assertEquals(1, immutable.properties.size());
120         assertEquals("1", immutable.properties.get("arg1"));
121       }
122 
123       {
124         Immutable immutable = mapper.packagePrivateConstructorAutoMapping();
125         assertEquals(2, immutable.properties.size());
126         assertEquals("1", immutable.properties.get("arg1"));
127         assertEquals("2", immutable.properties.get("arg2"));
128       }
129 
130       {
131         Immutable immutable = mapper.protectedConstructorAutoMapping();
132         assertEquals(3, immutable.properties.size());
133         assertEquals("1", immutable.properties.get("arg1"));
134         assertEquals("2", immutable.properties.get("arg2"));
135         assertEquals("3", immutable.properties.get("arg3"));
136       }
137 
138       {
139         Immutable immutable = mapper.publicConstructorAutoMapping();
140         assertEquals(4, immutable.properties.size());
141         assertEquals("1", immutable.properties.get("arg1"));
142         assertEquals("2", immutable.properties.get("arg2"));
143         assertEquals("3", immutable.properties.get("arg3"));
144         assertEquals("4", immutable.properties.get("arg4"));
145       }
146     }
147 
148   }
149 
150   @Test
151   void constructorMapping() {
152     try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
153       Mapper mapper = sqlSession.getMapper(Mapper.class);
154 
155       {
156         Immutable immutable = mapper.privateConstructorMapping();
157         assertEquals(1, immutable.properties.size());
158         assertEquals("1", immutable.properties.get("arg1"));
159       }
160 
161       {
162         Immutable immutable = mapper.packagePrivateConstructorMapping();
163         assertEquals(2, immutable.properties.size());
164         assertEquals("1", immutable.properties.get("arg1"));
165         assertEquals("2", immutable.properties.get("arg2"));
166       }
167 
168       {
169         Immutable immutable = mapper.protectedConstructorMapping();
170         assertEquals(3, immutable.properties.size());
171         assertEquals("1", immutable.properties.get("arg1"));
172         assertEquals("2", immutable.properties.get("arg2"));
173         assertEquals("3", immutable.properties.get("arg3"));
174       }
175 
176       {
177         Immutable immutable = mapper.publicConstructorMapping();
178         assertEquals(4, immutable.properties.size());
179         assertEquals("1", immutable.properties.get("arg1"));
180         assertEquals("2", immutable.properties.get("arg2"));
181         assertEquals("3", immutable.properties.get("arg3"));
182         assertEquals("4", immutable.properties.get("arg4"));
183       }
184     }
185 
186   }
187 
188   interface Mapper {
189     @Select({
190         // @formatter:off
191         "SELECT"
192           ,"#{privateField} as privateField"
193           ,",#{packagePrivateField} as packagePrivateField"
194           ,",#{protectedField} as protectedField"
195           ,",#{publicField} as publicField"
196           ,",#{privateProperty} as privateProperty"
197           ,",#{packagePrivateProperty} as packagePrivateProperty"
198           ,",#{protectedProperty} as protectedProperty"
199           ,",#{publicProperty} as publicProperty"
200         ,"FROM"
201           ,"INFORMATION_SCHEMA.SYSTEM_USERS"
202         // @formatter:on
203     })
204     Bean resultAutoMapping(Params params);
205 
206     @Select({
207         // @formatter:off
208         "<script>"
209 
210           ,"<bind name=\"privateFieldValue\" value=\"_parameter.privateField + '%'\" />"
211           ,"<bind name=\"packagePrivateFieldValue\" value=\"_parameter.packagePrivateField + '%'\" />"
212           ,"<bind name=\"protectedFieldValue\" value=\"_parameter.protectedField + '%'\" />"
213           ,"<bind name=\"publicFieldValue\" value=\"_parameter.publicField + '%'\" />"
214           ,"<bind name=\"privatePropertyValue\" value=\"_parameter.privateProperty + '%'\" />"
215           ,"<bind name=\"packagePrivatePropertyValue\" value=\"_parameter.packagePrivateProperty + '%'\" />"
216           ,"<bind name=\"protectedPropertyValue\" value=\"_parameter.getProtectedProperty() + '%'\" />"
217           ,"<bind name=\"publicPropertyValue\" value=\"_parameter.publicProperty + '%'\" />"
218 
219           ,"SELECT"
220           ,"#{privateFieldValue} as privateField"
221           ,",#{packagePrivateFieldValue} as packagePrivateField"
222           ,",#{protectedFieldValue} as protectedField"
223           ,",#{publicFieldValue} as publicField"
224           ,",#{privatePropertyValue} as privateProperty"
225           ,",#{packagePrivatePropertyValue} as packagePrivateProperty"
226           ,",#{protectedPropertyValue} as protectedProperty"
227           ,",#{publicPropertyValue} as publicProperty"
228 
229           ,"FROM"
230             ,"INFORMATION_SCHEMA.SYSTEM_USERS"
231 
232         ,"</script>"}
233         // @formatter:on
234     )
235     Bean resultAutoMappingUsingOgnl(Params params);
236 
237     @Results({
238         // @formatter:off
239         @Result(property = "privateField", column = "private_field")
240         ,@Result(property = "packagePrivateField", column = "package_private_field")
241         ,@Result(property = "protectedField", column = "protected_field")
242         ,@Result(property = "publicField", column = "public_field")
243         ,@Result(property = "privateProperty", column = "private_property")
244         ,@Result(property = "packagePrivateProperty", column = "package_private_property")
245         ,@Result(property = "protectedProperty", column = "protected_property")
246         ,@Result(property = "publicProperty", column = "public_property")
247         // @formatter:on
248     })
249     @Select({
250         // @formatter:off
251         "SELECT"
252           ,"#{privateField} as private_field"
253           ,",#{packagePrivateField} as package_private_field"
254           ,",#{protectedField} as protected_field"
255           ,",#{publicField} as public_field"
256           ,",#{privateProperty} as private_property"
257           ,",#{packagePrivateProperty} as package_private_property"
258           ,",#{protectedProperty} as protected_property"
259           ,",#{publicProperty} as public_property"
260         ,"FROM"
261           ,"INFORMATION_SCHEMA.SYSTEM_USERS"
262         // @formatter:on
263     })
264     Bean resultMapping(Params params);
265 
266     @Select("SELECT '1' FROM INFORMATION_SCHEMA.SYSTEM_USERS")
267     Immutable privateConstructorAutoMapping();
268 
269     @Select("SELECT '1', '2' FROM INFORMATION_SCHEMA.SYSTEM_USERS")
270     Immutable packagePrivateConstructorAutoMapping();
271 
272     @Select("SELECT '1', '2', '3' FROM INFORMATION_SCHEMA.SYSTEM_USERS")
273     Immutable protectedConstructorAutoMapping();
274 
275     @Select("SELECT '1', '2', '3', '4' FROM INFORMATION_SCHEMA.SYSTEM_USERS")
276     Immutable publicConstructorAutoMapping();
277 
278     @ConstructorArgs({@Arg(column = "c1", javaType = String.class)})
279     @Select("SELECT '1' as c1 FROM INFORMATION_SCHEMA.SYSTEM_USERS")
280     Immutable privateConstructorMapping();
281 
282     @ConstructorArgs({
283         // @formatter:off
284         @Arg(column = "c1", javaType = String.class)
285         ,@Arg(column = "c2", javaType = String.class)
286         // @formatter:on
287     })
288     @Select("SELECT '1' as c1, '2' as c2 FROM INFORMATION_SCHEMA.SYSTEM_USERS")
289     Immutable packagePrivateConstructorMapping();
290 
291     @ConstructorArgs({
292         // @formatter:off
293         @Arg(column = "c1", javaType = String.class)
294         ,@Arg(column = "c2", javaType = String.class)
295         ,@Arg(column = "c3", javaType = String.class)
296         // @formatter:on
297     })
298     @Select("SELECT '1' as c1, '2' as c2, '3' as c3 FROM INFORMATION_SCHEMA.SYSTEM_USERS")
299     Immutable protectedConstructorMapping();
300 
301     @ConstructorArgs({
302         // @formatter:off
303         @Arg(column = "c1", javaType = String.class)
304         ,@Arg(column = "c2", javaType = String.class)
305         ,@Arg(column = "c3", javaType = String.class)
306         ,@Arg(column = "c4", javaType = String.class)
307         // @formatter:on
308     })
309     @Select("SELECT '1' as c1, '2' as c2, '3' as c3, '4' as c4 FROM INFORMATION_SCHEMA.SYSTEM_USERS")
310     Immutable publicConstructorMapping();
311 
312   }
313 
314   static class Params {
315     private String privateField = "privateField";
316     String packagePrivateField = "packagePrivateField";
317     protected String protectedField = "protectedField";
318     public String publicField = "publicField";
319 
320     private String getPrivateProperty() {
321       return "privateProperty";
322     }
323 
324     String getPackagePrivateProperty() {
325       return "packagePrivateProperty";
326     }
327 
328     protected String getProtectedProperty() {
329       return "protectedProperty";
330     }
331 
332     public String getPublicProperty() {
333       return "publicProperty";
334     }
335   }
336 
337   @SuppressWarnings("unused")
338   static class Bean {
339     private String privateField;
340     String packagePrivateField;
341     protected String protectedField;
342     public String publicField;
343     private Map<String, String> properties = new HashMap<>();
344 
345     private void setPrivateProperty(String value) {
346       properties.put("privateProperty", value);
347     }
348 
349     void setPackagePrivateProperty(String value) {
350       properties.put("packagePrivateProperty", value);
351     }
352 
353     protected void setProtectedProperty(String value) {
354       properties.put("protectedProperty", value);
355     }
356 
357     public void setPublicProperty(String value) {
358       properties.put("publicProperty", value);
359     }
360   }
361 
362   @SuppressWarnings("unused")
363   static class Immutable {
364     private Map<String, String> properties = new HashMap<>();
365 
366     private Immutable(String arg1) {
367       properties.put("arg1", arg1);
368     }
369 
370     Immutable(String arg1, String arg2) {
371       properties.put("arg1", arg1);
372       properties.put("arg2", arg2);
373     }
374 
375     protected Immutable(String arg1, String arg2, String arg3) {
376       properties.put("arg1", arg1);
377       properties.put("arg2", arg2);
378       properties.put("arg3", arg3);
379     }
380 
381     public Immutable(String arg1, String arg2, String arg3, String arg4) {
382       properties.put("arg1", arg1);
383       properties.put("arg2", arg2);
384       properties.put("arg3", arg3);
385       properties.put("arg4", arg4);
386     }
387 
388   }
389 
390 }