Instead of executing separate select statements (which can cause N+1 performance issues), you can use a single SQL JOIN to retrieve all data at once and map it into a nested object graph using resultMap within an <association> tag.
Key Attributes for <association>:
resultMap: The ID of an external resultMap used to map the nested results. This allows for reusable mappings.columnPrefix: Used when joining tables to avoid column name collisions. It allows you to map aliased columns to an external resultMap by applying a prefix.notNullColumn: Specifies which columns must be non-null for MyBatis to create the child object. You can provide a comma-separated list of column names.autoMapping: Enables or disables automapping for this property, overriding the global autoMappingBehavior.
Best Practice: Use <id> elements
When using Nested Result mapping, always specify one or more <id> elements to uniquely identify results. Omitting them causes a severe performance penalty during the decomposition of the ResultSet into the object graph.
<!-- Using an external resultMap for the association -->
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author" resultMap="authorResult" />
</resultMap>
<resultMap id="authorResult" type="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
</resultMap>
<select id="selectBlog" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
A.bio as author_bio
from Blog B left outer join Author A on B.author_id = A.id
where B.id = #{id}
</select>