Auto-mapping

As you have already seen in the previous sections, in simple cases MyBatis can auto-map the results for you and in others you will need to build a result map. But as you will see in this section you can also mix both strategies. Let’s have a deeper look at how auto-mapping works.

When auto-mapping results MyBatis will get the column name and look for a property with the same name ignoring case. That means that if a column named ID and property named id are found, MyBatis will set the id property with the ID column value.

Usually database columns are named using uppercase letters and underscores between words and java properties often follow the camelcase naming covention. To enable the auto-mapping between them set the setting mapUnderscoreToCamelCase to true.

Auto-mapping works even when there is an specific result map. When this happens, for each result map, all columns that are present in the ResultSet that have not a manual mapping will be auto-mapped, then manual mappings will be processed. In the following sample id and userName columns will be auto-mapped and hashed_password column will be mapped.

  1. <select id="selectUsers" resultMap="userResultMap">
  2. select
  3. user_id as "id",
  4. user_name as "userName",
  5. hashed_password
  6. from some_table
  7. where id = #{id}
  8. </select>
  1. <resultMap id="userResultMap" type="User">
  2. <result property="password" column="hashed_password"/>
  3. </resultMap>

There are three auto-mapping levels:

  • NONE - disables auto-mapping. Only manually mapped properties will be set.
  • PARTIAL - will auto-map results except those that have nested result mappings defined inside (joins).
  • FULL - auto-maps everything.

The default value is PARTIAL, and it is so for a reason. When FULL is used auto-mapping will be performed when processing join results and joins retrieve data of several different entities in the same row hence this may result in undesired mappings. To understand the risk have a look at the following sample:

  1. <select id="selectBlog" resultMap="blogResult">
  2. select
  3. B.id,
  4. B.title,
  5. A.username,
  6. from Blog B left outer join Author A on B.author_id = A.id
  7. where B.id = #{id}
  8. </select>
  1. <resultMap id="blogResult" type="Blog">
  2. <association property="author" resultMap="authorResult"/>
  3. </resultMap>
  4. <resultMap id="authorResult" type="Author">
  5. <result property="username" column="author_username"/>
  6. </resultMap>

With this result map both Blog and Author will be auto-mapped. But note that Author has an id property and there is a column named id in the ResultSet so Author’s id will be filled with Blog’s id, and that is not what you were expecting. So use the FULL option with caution.

Regardless of the auto-mapping level configured you can enable or disable the automapping for an specific ResultMap by adding the attribute autoMapping to it:

  1. <resultMap id="userResultMap" type="User" autoMapping="false">
  2. <result property="password" column="hashed_password"/>
  3. </resultMap>