insert, update and delete

The data modification statements insert, update and delete are very similar in their implementation:

  1. <insert
  2. id="insertAuthor"
  3. parameterType="domain.blog.Author"
  4. flushCache="true"
  5. statementType="PREPARED"
  6. keyProperty=""
  7. keyColumn=""
  8. useGeneratedKeys=""
  9. timeout="20">
  10. <update
  11. id="updateAuthor"
  12. parameterType="domain.blog.Author"
  13. flushCache="true"
  14. statementType="PREPARED"
  15. timeout="20">
  16. <delete
  17. id="deleteAuthor"
  18. parameterType="domain.blog.Author"
  19. flushCache="true"
  20. statementType="PREPARED"
  21. timeout="20">
Insert, Update and Delete Attributes
AttributeDescription
idA unique identifier in this namespace that can be used to reference this statement.
parameterTypeThe fully qualified class name or alias for the parameter that will be passed into this statement. This attribute is optional because MyBatis can calculate the TypeHandler to use out of the actual parameter passed to the statement. Default is unset.
parameterMapThis is a deprecated approach to referencing an external parameterMap. Use inline parameter mappings and the parameterType attribute.
flushCacheSetting this to true will cause the 2nd level and local caches to be flushed whenever this statement is called. Default: true for insert, update and delete statements.
timeoutThis sets the maximum number of seconds the driver will wait for the database to return from a request, before throwing an exception. Default is unset (driver dependent).
statementTypeAny one of STATEMENT, PREPARED or CALLABLE. This causes MyBatis to use Statement, PreparedStatement or CallableStatement respectively. Default: PREPARED.
useGeneratedKeys(insert and update only) This tells MyBatis to use the JDBC getGeneratedKeys method to retrieve keys generated internally by the database (e.g. auto increment fields in RDBMS like MySQL or SQL Server). Default: false.
keyProperty(insert and update only) Identifies a property into which MyBatis will set the key value returned by getGeneratedKeys, or by a selectKey child element of the insert statement. Default: unset. Can be a comma separated list of property names if multiple generated columns are expected.
keyColumn(insert and update only) Sets the name of the column in the table with a generated key. This is only required in certain databases (like PostgreSQL) when the key column is not the first column in the table. Can be a comma separated list of columns names if multiple generated columns are expected.
databaseIdIn case there is a configured databaseIdProvider, MyBatis will load all statements with no databaseId attribute or with a databaseId that matches the current one. If case the same statement if found with and without the databaseId the latter will be discarded.

The following are some examples of insert, update and delete statements.

  1. <insert id="insertAuthor">
  2. insert into Author (id,username,password,email,bio)
  3. values (#{id},#{username},#{password},#{email},#{bio})
  4. </insert>
  5. <update id="updateAuthor">
  6. update Author set
  7. username = #{username},
  8. password = #{password},
  9. email = #{email},
  10. bio = #{bio}
  11. where id = #{id}
  12. </update>
  13. <delete id="deleteAuthor">
  14. delete from Author where id = #{id}
  15. </delete>

As mentioned, insert is a little bit more rich in that it has a few extra attributes and sub-elements that allow it to deal with key generation in a number of ways.

First, if your database supports auto-generated key fields (e.g. MySQL and SQL Server), then you can simply set useGeneratedKeys="true" and set the keyProperty to the target property and you’re done. For example, if the Author table above had used an auto-generated column type for the id, the statement would be modified as follows:

  1. <insert id="insertAuthor" useGeneratedKeys="true"
  2. keyProperty="id">
  3. insert into Author (username,password,email,bio)
  4. values (#{username},#{password},#{email},#{bio})
  5. </insert>

If your database also supports multi-row insert, you can pass a list or an array of Authors and retrieve the auto-generated keys.

  1. <insert id="insertAuthor" useGeneratedKeys="true"
  2. keyProperty="id">
  3. insert into Author (username, password, email, bio) values
  4. <foreach item="item" collection="list" separator=",">
  5. (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  6. </foreach>
  7. </insert>

MyBatis has another way to deal with key generation for databases that don’t support auto-generated column types, or perhaps don’t yet support the JDBC driver support for auto-generated keys.

Here’s a simple (silly) example that would generate a random ID (something you’d likely never do, but this demonstrates the flexibility and how MyBatis really doesn’t mind):

  1. <insert id="insertAuthor">
  2. <selectKey keyProperty="id" resultType="int" order="BEFORE">
  3. select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
  4. </selectKey>
  5. insert into Author
  6. (id, username, password, email,bio, favourite_section)
  7. values
  8. (#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
  9. </insert>

In the example above, the selectKey statement would be run first, the Author id property would be set, and then the insert statement would be called. This gives you a similar behavior to an auto-generated key in your database without complicating your Java code.

The selectKey element is described as follows:

  1. <selectKey
  2. keyProperty="id"
  3. resultType="int"
  4. order="BEFORE"
  5. statementType="PREPARED">
selectKey Attributes
AttributeDescription
keyPropertyThe target property where the result of the selectKey statement should be set. Can be a comma separated list of property names if multiple generated columns are expected.
keyColumnThe column name(s) in the returned result set that match the properties. Can be a comma separated list of column names if multiple generated columns are expected.
resultTypeThe type of the result. MyBatis can usually figure this out, but it doesn’t hurt to add it to be sure. MyBatis allows any simple type to be used as the key, including Strings. If you are expecting multiple generated columns, then you can use an Object that contains the expected properties, or a Map.
orderThis can be set to BEFORE or AFTER. If set to BEFORE, then it will select the key first, set the keyProperty and then execute the insert statement. If set to AFTER, it runs the insert statement and then the selectKey statement – which is common with databases like Oracle that may have embedded sequence calls inside of insert statements.
statementTypeSame as above, MyBatis supports STATEMENT, PREPARED and CALLABLE statement types that map to Statement, PreparedStatement and CallableStatement respectively.

As an irregular case, some databases allow INSERT, UPDATE or DELETE statement to return result set (e.g. RETURNING clause of PostgreSQL and MariaDB or OUTPUT clause of MS SQL Server). This type of statement must be written as <select> to map the returned data.

  1. <select id="insertAndGetAuthor" resultType="domain.blog.Author"
  2. affectData="true" flushCache="true">
  3. insert into Author (username, password, email, bio)
  4. values (#{username}, #{password}, #{email}, #{bio})
  5. returning id, username, password, email, bio
  6. </select>