insert, update and delete
The data modification statements insert, update and delete are very similar in their implementation:
<insert
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20">
<update
id="updateAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20">
<delete
id="deleteAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20">
Attribute | Description |
---|---|
id | A unique identifier in this namespace that can be used to reference this statement. |
parameterType | The 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 . |
parameterMap | |
flushCache | Setting 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. |
timeout | This 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). |
statementType | Any 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. |
databaseId | In 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.
<insert id="insertAuthor">
insert into Author (id,username,password,email,bio)
values (#{id},#{username},#{password},#{email},#{bio})
</insert>
<update id="updateAuthor">
update Author set
username = #{username},
password = #{password},
email = #{email},
bio = #{bio}
where id = #{id}
</update>
<delete id="deleteAuthor">
delete from Author where id = #{id}
</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:
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username,password,email,bio)
values (#{username},#{password},#{email},#{bio})
</insert>
If your database also supports multi-row insert, you can pass a list or an array of Author
s and retrieve the auto-generated keys.
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username, password, email, bio) values
<foreach item="item" collection="list" separator=",">
(#{item.username}, #{item.password}, #{item.email}, #{item.bio})
</foreach>
</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):
<insert id="insertAuthor">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
</selectKey>
insert into Author
(id, username, password, email,bio, favourite_section)
values
(#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
</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:
<selectKey
keyProperty="id"
resultType="int"
order="BEFORE"
statementType="PREPARED">
Attribute | Description |
---|---|
keyProperty | The 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. |
keyColumn | The 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. |
resultType | The 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. |
order | This 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. |
statementType | Same 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.
<select id="insertAndGetAuthor" resultType="domain.blog.Author"
affectData="true" flushCache="true">
insert into Author (username, password, email, bio)
values (#{username}, #{password}, #{email}, #{bio})
returning id, username, password, email, bio
</select>