Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.io.IOException;
import java.io.Reader;
import java.net.URL;
import java.util.Arrays;
import java.util.List;

/**
Expand Down Expand Up @@ -45,55 +46,56 @@ public void testSelect() {

System.out.println("------selectAll------");
users = mapper.selectAll();
users.forEach(u -> {
System.out.println(u);
Assert.assertNotNull(u.getUname());
Assert.assertNotNull(u.getAge());
Assert.assertNotNull(u.getCreateTime());
Assert.assertNull(u.getEmail());
});
System.out.println("------------");
userAssert(users);
System.out.println("###################");

System.out.println("------selectRawAnnotation------");
users = mapper.selectRawAnnotation();
users.forEach(u -> {
System.out.println(u);
Assert.assertNotNull(u.getUname());
Assert.assertNotNull(u.getAge());
Assert.assertNotNull(u.getCreateTime());
Assert.assertNotNull(u.getEmail());
});
System.out.println("------------");
userAssert(users);
System.out.println("###################");

System.out.println("------selectRawAnnotationResultMap------");
users = mapper.selectRawAnnotationResultMap();
userAssert(users);
System.out.println("###################");

System.out.println("------fetchRawResultMap------");
users = mapper.fetchRawResultMap();
users.forEach(u -> {
System.out.println(u);
Assert.assertNotNull(u.getUname());
Assert.assertNotNull(u.getAge());
Assert.assertNotNull(u.getCreateTime());
Assert.assertNotNull(u.getEmail());
});
System.out.println("------------");
userAssert(users);
System.out.println("###################");

System.out.println("------fetchDynamicResultMap------");
users = mapper.fetchDynamicResultMap();
userAssert(users);
System.out.println("###################");

System.out.println("------fetchRawResultType------");
users = mapper.fetchRawResultType();
users.forEach(u -> {
System.out.println(u);
Assert.assertNotNull(u.getUname());
Assert.assertNotNull(u.getAge());
Assert.assertNotNull(u.getCreateTime());
Assert.assertNotNull(u.getEmail());
});
System.out.println("------------");
userAssert(users);
System.out.println("###################");

System.out.println("------fetchDynamicSqlType------");
users = mapper.fetchDynamicSqlType(Arrays.asList(1, 2, 3));
userAssert(users);
System.out.println("###################");

System.out.println("------getMapUser------");
System.out.println(mapper.getMapUser());
System.out.println("------------");
System.out.println("###################");

System.out.println(mapper.selectCount2());

} finally {
sqlSession.close();
}
}

private static void userAssert(List<User> users) {
users.forEach(u -> {
System.out.println(u);
Assert.assertNotNull(u.getUname());
Assert.assertNotNull(u.getAge());
Assert.assertNotNull(u.getCreateTime());
});
Comment on lines +93 to +99
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

测试用的 userAssert() 现在只断言 uname/age/createTime 非空,移除了之前对 email 的断言,导致无法验证本次修复的核心行为(resultType/动态 SQL 下是否正确应用实体的 ResultMap,以及 @transient 字段是否应被映射)。建议针对不同查询分别断言 email 应为 null(resultType/自动映射走实体 ResultMap)或非 null(显式 BaseResultMap),以避免回归。

Copilot uses AI. Check for mistakes.
}
}
10 changes: 10 additions & 0 deletions base/src/test/java/tk/mybatis/mapper/rawresultmap/UserMapper.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package tk.mybatis.mapper.rawresultmap;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.common.BaseMapper;

Expand All @@ -15,10 +17,18 @@ public interface UserMapper extends BaseMapper<User> {
@Select("SELECT * FROM user")
List<User> selectRawAnnotation();

@Select("SELECT * FROM user")
@ResultMap("BaseResultMap")
List<User> selectRawAnnotationResultMap();

List<User> fetchRawResultType();

List<User> fetchDynamicSqlType(@Param("ids") List<Integer> ids);

List<User> fetchRawResultMap();

List<User> fetchDynamicResultMap();

Map<String, Object> getMapUser();

Integer selectCount2();
Expand Down
22 changes: 21 additions & 1 deletion base/src/test/java/tk/mybatis/mapper/rawresultmap/UserMapper.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,38 @@
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="user_name" jdbcType="VARCHAR" property="uname" />
<result column="email" jdbcType="VARCHAR" property="email" />
<result column="age____aa" jdbcType="INTEGER" property="age" />
<result column="age__int__aa" jdbcType="INTEGER" property="age" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
</resultMap>

<select id="fetchRawResultType" resultType = "tk.mybatis.mapper.rawresultmap.User">
select * from user
</select>

<select id="fetchDynamicSqlType" resultType = "tk.mybatis.mapper.rawresultmap.User">
select * from user
<where>
<if test="ids != null and ids.size() != 0">
id
<foreach collection="ids" open="in (" close=")" separator="," item="id">
#{id}
</foreach>
</if>
</where>
</select>

<select id="fetchRawResultMap" resultMap="BaseResultMap">
select * from user
</select>

<select id="fetchDynamicResultMap" resultMap="BaseResultMap">
select * from user
<where>
1=1
</where>
</select>


<select id="getMapUser" resultType="Map">
select * from user where id = 1
</select>
Expand Down
47 changes: 22 additions & 25 deletions core/src/main/java/tk/mybatis/mapper/mapperhelper/MapperHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.scripting.defaults.RawSqlSource;
import org.apache.ibatis.session.Configuration;
import tk.mybatis.mapper.MapperException;
import tk.mybatis.mapper.annotation.RegisterMapper;
Expand Down Expand Up @@ -303,11 +303,27 @@ public void processMappedStatement(MappedStatement ms) {
setSqlSource(ms, mapperTemplate);
}

// 如果是原生mybatisSqlSource的查询,添加ResultMap
if (ms.getSqlSource() instanceof RawSqlSource
&& ms.getSqlCommandType() == SqlCommandType.SELECT) {
if (ms.getResultMaps() != null && !ms.getResultMaps().isEmpty()) {
setRawSqlSourceMapper(ms);
// 如果没有resultMaps, 有则设置一个默认的resultMaps
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注释“如果没有resultMaps, 有则设置一个默认的resultMaps”与实际逻辑不一致:当前代码是在 SELECT 时对已有 resultMaps 中“只有 type、没有 mappings”的条目做替换,并没有处理 resultMaps 为空的情况。建议更新注释,准确描述触发条件与行为,避免误导后续维护。

Suggested change
// 如果没有resultMaps, 有则设置一个默认的resultMaps
// 对于 SELECT 语句,如果已有 resultMaps 中存在仅指定 type 而未定义 mappings 的条目,则根据实体的 @Table 元数据生成并替换为默认的 ResultMap

Copilot uses AI. Check for mistakes.
if (ms.getSqlCommandType() == SqlCommandType.SELECT) {
List<ResultMap> resultMaps = ms.getResultMaps();
if (resultMaps != null) {
List<ResultMap> modifiableResultMaps = new ArrayList<>(resultMaps);
for (int i = 0; i < resultMaps.size(); i++) {
List<ResultMapping> mappings = resultMaps.get(i).getResultMappings();
// 只有type,没有mappings的情况下
if (mappings == null || mappings.isEmpty()) {
EntityTable entityTable = EntityHelper.getEntityTableOrNull(resultMaps.get(i).getType());
// 如果有@Table注解,则可以获取到entityTable
if (entityTable != null) {
ResultMap resultMap = entityTable.getResultMap(ms.getConfiguration());
if (resultMap != null) {
modifiableResultMaps.set(i, resultMap);
MetaObject metaObject = MetaObjectUtil.forObject(ms);
metaObject.setValue("resultMaps", Collections.unmodifiableList(modifiableResultMaps));
}
Comment on lines +310 to +323
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里在循环内每次替换一个 ResultMap 都会重新构建 MetaObject 并多次 setValue("resultMaps")。建议用一个 changed 标记:先在循环里只更新 modifiableResultMaps,循环结束后(且仅当发生替换时)再一次性把新的不可变 List 回写到 ms,避免重复反射写入并让逻辑更清晰。

Copilot uses AI. Check for mistakes.
}
}
}
}
}
}
Expand Down Expand Up @@ -396,23 +412,4 @@ public void setSqlSource(MappedStatement ms, MapperTemplate mapperTemplate) {
}
}

/**
* 设置原生Mybatis查询的实体映射,
* </p>
* JPA的注解优先级将高于mybatis自动映射
*/
public void setRawSqlSourceMapper(MappedStatement ms) {

EntityTable entityTable = EntityHelper.getEntityTableOrNull(ms.getResultMaps().get(0).getType());
if (entityTable != null) {
List<ResultMap> resultMaps = new ArrayList<>();
ResultMap resultMap = entityTable.getResultMap(ms.getConfiguration());
if (resultMap != null) {
resultMaps.add(resultMap);
MetaObject metaObject = MetaObjectUtil.forObject(ms);
metaObject.setValue("resultMaps", Collections.unmodifiableList(resultMaps));
}
}
}

}
Loading