MyBatis version

3.5.0 and 3.5.16

Database vendor and version

mysql 8.0.29

Test case or example project

MapperA.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test.com.example.MapperA">
  <sql id="Base_Column_List">
    'A'
  </sql>
  <select id="select" resultType="java.util.Map">
    select <include refid="test.com.example.MapperB.More_Column_List"/>
  </select>
</mapper>

MapperB.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test.com.example.MapperB">
  <sql id="Base_Column_List">
    'B'
  </sql>
  <sql id="More_Column_List">
    <include refid="Base_Column_List"/>
  </sql>
</mapper>

MapperA.class

public interface MapperA {
    Map<String, Object> select();
}

MapperB.class

public interface MapperB {
}

Steps to reproduce

run MapperA#select

Expected result

==> Preparing: select 'B'

Actual result

==> Preparing: select 'A'

Comment From: harawata

Hello @lyw0210 ,

MyBatis resolves include sequentially when it's nested.

So, this is original.

<select id="select" resultType="java.util.Map">
  select <include refid="test.com.example.MapperB.More_Column_List"/>
</select>

First step is obvious.

<select id="select" resultType="java.util.Map">
  select <include refid="Base_Column_List"/>
</select>

In the second step, refid is not fully-qualified, so it references Base_Column_List in the same mapper i.e. test.com.example.MapperA.

That example is not realistic, so it's unclear what exactly you want to achieve, but you should use fully-qualified ID or <property>.

Comment From: lyw0210

@harawata The fact is, this is a simplified example of a problem I encountered in a real project. I want to reuse the <SQL> from MapperB in MapperA.
I believe the <sql id="More_Column_List"> should behave consistently in both MapperA and MapperB, so the <include> should be parsed from the inside out, right?

(Sorry, English is not my native language, so there might be some grammatical errors.)

Comment From: harawata

You English is probably better than mine. :)

It does behave consistently. It is just parsed from the outside in, not from the inside out.

It seems to be the only possible way technically, but even if there is a way to change the behavior, it will break backward compatibility, so we can't/won't change it.

this is a simplified example of a problem I encountered in a real project

I know. My point is, if you explain the problem, we might be able to propose another solution. It's called XY problem.

Comment From: lyw0210

My English comes from ChatGPT, haha. XD

I now understand that this is the expected behavior of Mybatis, and that’s enough for me. I think I can find a better solution.

Thank you for clarifying!