这篇文章主要讲如何通过xml方式实现SaveOrUpdate,但是仍然建议在Service中实现。
<code class="language-xml hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">insert</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">id</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"saveOrUpdate"</span> ></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">selectKey</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">keyProperty</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"count"</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">resultType</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"int"</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">order</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"BEFORE"</span>></span> select count(*) from country where id = #{id} <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">selectKey</span>></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">if</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">test</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"count > 0"</span>></span> update country set countryname = #{countryname},countrycode = #{countrycode} where id = #{id} <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">if</span>></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">if</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">test</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"count==0"</span>></span> insert into country values(#{id},#{countryname},#{countrycode}) <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">if</span>></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">insert</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>
根据不同的判断逻辑,会有所不同,就上面这个例子而言,就要求实体类中包含count
属性(可以是别的名字)。否则selectKey
的结果没法保存,如果入参是个Map
类型,就没有这个限制。
从例子来看除了有个限制外,也没别的麻烦。
通过selectKey做第一次查询,然后根据结果进行判断,所以这里的order="BEFORE"
是必须的。
也是因为BEFORE
,所以没法通过<bind>
标签来临时存储中间的值,只能在入参中增加属性来存放。
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//数据库中已经存在该ID,但是countryname=China</span> Country country = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Country(); country.setId(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">35</span>); country.setCountryname(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"中国"</span>); country.setCountrycode(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CN"</span>); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//由于存在,这里会update</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> result = countryMapper.saveOrUpdate(country); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//查询结果,判断是否已经改变</span> Country c2 = countryMapper.selectById(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">35</span>); assertEquals(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"中国"</span>,c2.getCountryname()); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//id=300的不存在</span> c2 = countryMapper.selectById(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>); assertNull(c2); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将id=300</span> country.setId(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//由于id=300不存在,这里会Insert</span> result = countryMapper.saveOrUpdate(country); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//查询结果</span> c2 = countryMapper.selectById(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>); assertNotNull(c2);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li></ul>
<code class="hljs vbnet has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">DEBUG ==> Preparing: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">select</span> count(*) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> country <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">where</span> id = ? DEBUG ==> Parameters: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">35</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Integer</span>) TRACE <== Columns: C1 TRACE <== Row: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> DEBUG <== Total: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> DEBUG ==> Preparing: update country <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">set</span> countryname = ?,countrycode = ? <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">where</span> id = ? DEBUG ==> Parameters: 中国(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>), CN(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>), <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">35</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Integer</span>) DEBUG <== Updates: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> DEBUG ==> Preparing: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">select</span> * <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> country <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">where</span> id = ? DEBUG ==> Parameters: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">35</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Integer</span>) TRACE <== Columns: ID, COUNTRYNAME, COUNTRYCODE TRACE <== Row: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">35</span>, 中国, CN DEBUG <== Total: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> DEBUG ==> Preparing: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">select</span> * <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> country <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">where</span> id = ? DEBUG ==> Parameters: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Integer</span>) DEBUG <== Total: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> DEBUG ==> Preparing: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">select</span> count(*) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> country <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">where</span> id = ? DEBUG ==> Parameters: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Integer</span>) TRACE <== Columns: C1 TRACE <== Row: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> DEBUG <== Total: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> DEBUG ==> Preparing: insert <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">into</span> country values(?,?,?) DEBUG ==> Parameters: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Integer</span>), 中国(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>), CN(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>) DEBUG <== Updates: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> DEBUG ==> Preparing: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">select</span> * <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> country <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">where</span> id = ? DEBUG ==> Parameters: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Integer</span>) TRACE <== Columns: ID, COUNTRYNAME, COUNTRYCODE TRACE <== Row: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>, 中国, CN DEBUG <== Total: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li></ul>
这种方式只是利用了selectKey会多执行一次查询来实现的,但是如果你同时还需要通过selectKey获取序列或者自增的id,就会麻烦很多(oracle麻烦,其他支持自增的还是很容易)。
建议在复杂情况下,还是选择在Service中实现更好。