MemberAccessTest.java
/*
* Copyright 2009-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.submitted.member_access;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;
import org.apache.ibatis.annotations.Arg;
import org.apache.ibatis.annotations.ConstructorArgs;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/**
* Tests for member access of Java Object.
*/
class MemberAccessTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeAll
static void setUp() throws Exception {
try (
Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/member_access/mybatis-config.xml")) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
sqlSessionFactory.getConfiguration().addMapper(Mapper.class);
}
}
@Test
void parameterMappingAndResultAutoMapping() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Params params = new Params();
Bean bean = mapper.resultAutoMapping(params);
assertEquals(params.privateField, bean.privateField);
assertEquals(params.packagePrivateField, bean.packagePrivateField);
assertEquals(params.protectedField, bean.protectedField);
assertEquals(params.publicField, bean.publicField);
assertEquals(params.getPrivateProperty(), bean.properties.get("privateProperty"));
assertEquals(params.getPackagePrivateProperty(), bean.properties.get("packagePrivateProperty"));
assertEquals(params.getProtectedProperty(), bean.properties.get("protectedProperty"));
assertEquals(params.getPublicProperty(), bean.properties.get("publicProperty"));
}
}
@Test // gh-1258
void parameterMappingAndResultAutoMappingUsingOgnl() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Params params = new Params();
Bean bean = mapper.resultAutoMappingUsingOgnl(params);
assertEquals(params.privateField + "%", bean.privateField);
assertEquals(params.packagePrivateField + "%", bean.packagePrivateField);
assertEquals(params.protectedField + "%", bean.protectedField);
assertEquals(params.publicField + "%", bean.publicField);
assertEquals(params.getPrivateProperty() + "%", bean.properties.get("privateProperty"));
assertEquals(params.getPackagePrivateProperty() + "%", bean.properties.get("packagePrivateProperty"));
assertEquals(params.getProtectedProperty() + "%", bean.properties.get("protectedProperty"));
assertEquals(params.getPublicProperty() + "%", bean.properties.get("publicProperty"));
}
}
@Test
void parameterMappingAndResultMapping() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Params params = new Params();
Bean bean = mapper.resultMapping(params);
assertEquals(params.privateField, bean.privateField);
assertEquals(params.packagePrivateField, bean.packagePrivateField);
assertEquals(params.protectedField, bean.protectedField);
assertEquals(params.publicField, bean.publicField);
assertEquals(params.getPrivateProperty(), bean.properties.get("privateProperty"));
assertEquals(params.getPackagePrivateProperty(), bean.properties.get("packagePrivateProperty"));
assertEquals(params.getProtectedProperty(), bean.properties.get("protectedProperty"));
assertEquals(params.getPublicProperty(), bean.properties.get("publicProperty"));
}
}
@Test
void constructorAutoMapping() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
{
Immutable immutable = mapper.privateConstructorAutoMapping();
assertEquals(1, immutable.properties.size());
assertEquals("1", immutable.properties.get("arg1"));
}
{
Immutable immutable = mapper.packagePrivateConstructorAutoMapping();
assertEquals(2, immutable.properties.size());
assertEquals("1", immutable.properties.get("arg1"));
assertEquals("2", immutable.properties.get("arg2"));
}
{
Immutable immutable = mapper.protectedConstructorAutoMapping();
assertEquals(3, immutable.properties.size());
assertEquals("1", immutable.properties.get("arg1"));
assertEquals("2", immutable.properties.get("arg2"));
assertEquals("3", immutable.properties.get("arg3"));
}
{
Immutable immutable = mapper.publicConstructorAutoMapping();
assertEquals(4, immutable.properties.size());
assertEquals("1", immutable.properties.get("arg1"));
assertEquals("2", immutable.properties.get("arg2"));
assertEquals("3", immutable.properties.get("arg3"));
assertEquals("4", immutable.properties.get("arg4"));
}
}
}
@Test
void constructorMapping() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
{
Immutable immutable = mapper.privateConstructorMapping();
assertEquals(1, immutable.properties.size());
assertEquals("1", immutable.properties.get("arg1"));
}
{
Immutable immutable = mapper.packagePrivateConstructorMapping();
assertEquals(2, immutable.properties.size());
assertEquals("1", immutable.properties.get("arg1"));
assertEquals("2", immutable.properties.get("arg2"));
}
{
Immutable immutable = mapper.protectedConstructorMapping();
assertEquals(3, immutable.properties.size());
assertEquals("1", immutable.properties.get("arg1"));
assertEquals("2", immutable.properties.get("arg2"));
assertEquals("3", immutable.properties.get("arg3"));
}
{
Immutable immutable = mapper.publicConstructorMapping();
assertEquals(4, immutable.properties.size());
assertEquals("1", immutable.properties.get("arg1"));
assertEquals("2", immutable.properties.get("arg2"));
assertEquals("3", immutable.properties.get("arg3"));
assertEquals("4", immutable.properties.get("arg4"));
}
}
}
interface Mapper {
// @formatter:off
@Select({
"SELECT"
, "#{privateField} as privateField"
, ",#{packagePrivateField} as packagePrivateField"
, ",#{protectedField} as protectedField"
, ",#{publicField} as publicField"
, ",#{privateProperty} as privateProperty"
, ",#{packagePrivateProperty} as packagePrivateProperty"
, ",#{protectedProperty} as protectedProperty"
, ",#{publicProperty} as publicProperty"
, "FROM"
, "INFORMATION_SCHEMA.SYSTEM_USERS"
})
// @formatter:on
Bean resultAutoMapping(Params params);
// @formatter:off
@Select({
"<script>"
, "<bind name=\"privateFieldValue\" value=\"_parameter.privateField + '%'\" />"
, "<bind name=\"packagePrivateFieldValue\" value=\"_parameter.packagePrivateField + '%'\" />"
, "<bind name=\"protectedFieldValue\" value=\"_parameter.protectedField + '%'\" />"
, "<bind name=\"publicFieldValue\" value=\"_parameter.publicField + '%'\" />"
, "<bind name=\"privatePropertyValue\" value=\"_parameter.privateProperty + '%'\" />"
, "<bind name=\"packagePrivatePropertyValue\" value=\"_parameter.packagePrivateProperty + '%'\" />"
, "<bind name=\"protectedPropertyValue\" value=\"_parameter.getProtectedProperty() + '%'\" />"
, "<bind name=\"publicPropertyValue\" value=\"_parameter.publicProperty + '%'\" />"
, "SELECT"
, "#{privateFieldValue} as privateField"
, ",#{packagePrivateFieldValue} as packagePrivateField"
, ",#{protectedFieldValue} as protectedField"
, ",#{publicFieldValue} as publicField"
, ",#{privatePropertyValue} as privateProperty"
, ",#{packagePrivatePropertyValue} as packagePrivateProperty"
, ",#{protectedPropertyValue} as protectedProperty"
, ",#{publicPropertyValue} as publicProperty"
, "FROM INFORMATION_SCHEMA.SYSTEM_USERS"
, "</script>"}
)
// @formatter:on
Bean resultAutoMappingUsingOgnl(Params params);
// @formatter:off
@Results({
@Result(property = "privateField", column = "private_field")
, @Result(property = "packagePrivateField", column = "package_private_field")
, @Result(property = "protectedField", column = "protected_field")
, @Result(property = "publicField", column = "public_field")
, @Result(property = "privateProperty", column = "private_property")
, @Result(property = "packagePrivateProperty", column = "package_private_property")
, @Result(property = "protectedProperty", column = "protected_property")
, @Result(property = "publicProperty", column = "public_property")
})
@Select({
"SELECT"
, "#{privateField} as private_field"
, ",#{packagePrivateField} as package_private_field"
, ",#{protectedField} as protected_field"
, ",#{publicField} as public_field"
, ",#{privateProperty} as private_property"
, ",#{packagePrivateProperty} as package_private_property"
, ",#{protectedProperty} as protected_property"
, ",#{publicProperty} as public_property"
, "FROM INFORMATION_SCHEMA.SYSTEM_USERS"
})
// @formatter:on
Bean resultMapping(Params params);
@Select("SELECT '1' FROM INFORMATION_SCHEMA.SYSTEM_USERS")
Immutable privateConstructorAutoMapping();
@Select("SELECT '1', '2' FROM INFORMATION_SCHEMA.SYSTEM_USERS")
Immutable packagePrivateConstructorAutoMapping();
@Select("SELECT '1', '2', '3' FROM INFORMATION_SCHEMA.SYSTEM_USERS")
Immutable protectedConstructorAutoMapping();
@Select("SELECT '1', '2', '3', '4' FROM INFORMATION_SCHEMA.SYSTEM_USERS")
Immutable publicConstructorAutoMapping();
@ConstructorArgs({ @Arg(column = "c1", javaType = String.class) })
@Select("SELECT '1' as c1 FROM INFORMATION_SCHEMA.SYSTEM_USERS")
Immutable privateConstructorMapping();
// @formatter:off
@ConstructorArgs({
@Arg(column = "c1", javaType = String.class)
, @Arg(column = "c2", javaType = String.class)
})
// @formatter:on
@Select("SELECT '1' as c1, '2' as c2 FROM INFORMATION_SCHEMA.SYSTEM_USERS")
Immutable packagePrivateConstructorMapping();
// @formatter:off
@ConstructorArgs({
@Arg(column = "c1", javaType = String.class)
, @Arg(column = "c2", javaType = String.class)
, @Arg(column = "c3", javaType = String.class)
})
// @formatter:on
@Select("SELECT '1' as c1, '2' as c2, '3' as c3 FROM INFORMATION_SCHEMA.SYSTEM_USERS")
Immutable protectedConstructorMapping();
// @formatter:off
@ConstructorArgs({
@Arg(column = "c1", javaType = String.class)
, @Arg(column = "c2", javaType = String.class)
, @Arg(column = "c3", javaType = String.class)
, @Arg(column = "c4", javaType = String.class)
})
// @formatter:on
@Select("SELECT '1' as c1, '2' as c2, '3' as c3, '4' as c4 FROM INFORMATION_SCHEMA.SYSTEM_USERS")
Immutable publicConstructorMapping();
}
static class Params {
private final String privateField = "privateField";
String packagePrivateField = "packagePrivateField";
protected String protectedField = "protectedField";
public String publicField = "publicField";
private String getPrivateProperty() {
return "privateProperty";
}
String getPackagePrivateProperty() {
return "packagePrivateProperty";
}
protected String getProtectedProperty() {
return "protectedProperty";
}
public String getPublicProperty() {
return "publicProperty";
}
}
@SuppressWarnings("unused")
static class Bean {
private String privateField;
String packagePrivateField;
protected String protectedField;
public String publicField;
private Map<String, String> properties = new HashMap<>();
private void setPrivateProperty(String value) {
properties.put("privateProperty", value);
}
void setPackagePrivateProperty(String value) {
properties.put("packagePrivateProperty", value);
}
protected void setProtectedProperty(String value) {
properties.put("protectedProperty", value);
}
public void setPublicProperty(String value) {
properties.put("publicProperty", value);
}
}
@SuppressWarnings("unused")
static class Immutable {
private Map<String, String> properties = new HashMap<>();
private Immutable(String arg1) {
properties.put("arg1", arg1);
}
Immutable(String arg1, String arg2) {
properties.put("arg1", arg1);
properties.put("arg2", arg2);
}
protected Immutable(String arg1, String arg2, String arg3) {
properties.put("arg1", arg1);
properties.put("arg2", arg2);
properties.put("arg3", arg3);
}
public Immutable(String arg1, String arg2, String arg3, String arg4) {
properties.put("arg1", arg1);
properties.put("arg2", arg2);
properties.put("arg3", arg3);
properties.put("arg4", arg4);
}
}
}