这篇文章主要讲如何通过xml方式实现SaveOrUpdate,但是仍然建议在Service中实现。

例子

<insert id="saveOrUpdate" >
<selectKey keyProperty="count" resultType="int" order="BEFORE">
select count(*) from country where id = #{id}
</selectKey>
<if test="count > 0">
update country
set countryname = #{countryname},countrycode = #{countrycode}
where id = #{id}
</if>
<if test="count==0">
insert into country values(#{id},#{countryname},#{countrycode})
</if>
</insert>

条件限制

根据不同的判断逻辑,会有所不同,就上面这个例子而言,就要求实体类中包含count属性(可以是别的名字)。否则selectKey的结果没法保存,如果入参是个Map类型,就没有这个限制。

说明

从例子来看除了有个限制外,也没别的麻烦。

通过selectKey做第一次查询,然后根据结果进行判断,所以这里的order="BEFORE"是必须的。

也是因为BEFORE,所以没法通过<bind>标签来临时存储中间的值,只能在入参中增加属性来存放。

测试代码

//数据库中已经存在该ID,但是countryname=China
Country country = new Country();
country.setId(35);
country.setCountryname("中国");
country.setCountrycode("CN");
//由于存在,这里会update
int result = countryMapper.saveOrUpdate(country); //查询结果,判断是否已经改变
Country c2 = countryMapper.selectById(35);
assertEquals("中国",c2.getCountryname()); //id=300的不存在
c2 = countryMapper.selectById(300);
assertNull(c2); //将id=300
country.setId(300);
//由于id=300不存在,这里会Insert
result = countryMapper.saveOrUpdate(country); //查询结果
c2 = countryMapper.selectById(300);
assertNotNull(c2);

输出日志

DEBUG ==>  Preparing: select count(*) from country where id = ?
DEBUG ==> Parameters: 35(Integer)
TRACE <== Columns: C1
TRACE <== Row: 1
DEBUG <== Total: 1
DEBUG ==> Preparing: update country set countryname = ?,countrycode = ? where id = ?
DEBUG ==> Parameters: 中国(String), CN(String), 35(Integer)
DEBUG <== Updates: 1
DEBUG ==> Preparing: select * from country where id = ?
DEBUG ==> Parameters: 35(Integer)
TRACE <== Columns: ID, COUNTRYNAME, COUNTRYCODE
TRACE <== Row: 35, 中国, CN
DEBUG <== Total: 1
DEBUG ==> Preparing: select * from country where id = ?
DEBUG ==> Parameters: 300(Integer)
DEBUG <== Total: 0
DEBUG ==> Preparing: select count(*) from country where id = ?
DEBUG ==> Parameters: 300(Integer)
TRACE <== Columns: C1
TRACE <== Row: 0
DEBUG <== Total: 1
DEBUG ==> Preparing: insert into country values(?,?,?)
DEBUG ==> Parameters: 300(Integer), 中国(String), CN(String)
DEBUG <== Updates: 1
DEBUG ==> Preparing: select * from country where id = ?
DEBUG ==> Parameters: 300(Integer)
TRACE <== Columns: ID, COUNTRYNAME, COUNTRYCODE
TRACE <== Row: 300, 中国, CN
DEBUG <== Total: 1

最后

这种方式只是利用了selectKey会多执行一次查询来实现的,但是如果你同时还需要通过selectKey获取序列或者自增的id,就会麻烦很多(Oracle麻烦,其他支持自增的还是很容易)。

建议在复杂情况下,还是选择在Service中实现更好。

MyBatis工具:www.mybatis.tk

http://blog.csdn.net/isea533/article/details/45578415

MyBatis实现SaveOrUpdate的更多相关文章

  1. MyBatis 配置/注解 SQL CRUD 经典解决方案(2019.08.15持续更新)

    本文旨在记录使用各位大神的经典解决方案. 2019.08.14 更新 Mybatis saveOrUpdate SelectKey非主键的使用 MyBatis实现SaveOrUpdate mybati ...

  2. 集成框架 javaweb开发平台ssmy_m(生成代码) java struts2 mybatis spring maven jquery

    网页地址 http://blog.csdn.net/lpy3654321/article/details/31841573 项目设想,在项目开发中,我们的开发者大多数时间都在反复开发 相同的keywo ...

  3. 从JDBC到hibernate再到mybatis之路

    一.传统的JDBC编程 在java开发中,以前都是通过JDBC(Java Data Base Connectivity)与数据库打交道的,至少在ORM(Object Relational Mappin ...

  4. MySQL保存或更新 saveOrUpdate

    1. 引子 在项目开发过程中,有一些数据在写入时候,若已经存在,则覆盖即可.这样可以防止多次重复写入唯一键冲突报错.下面先给出两个MyBatis配置文件中使用saveOrUpdate的示例 <! ...

  5. jdbc、Mybatis、Hibernate介绍(非原创)

    文章大纲 一.jdbc介绍二.Mybatis介绍三.Hibernate介绍四.jdbc.Mybatis.Hibernate比较五.参考文章   一.jdbc介绍 1. jdbc编程步骤 (1)加载数据 ...

  6. MyBatis从入门到精通(第9章):Spring集成MyBatis(下)

    MyBatis从入门到精通(第9章):Spring集成MyBatis(下) springmvc执行流程原理 mybatis-spring  可以帮助我们将MyBatis代码无缝整合到Spring中.使 ...

  7. Spring Boot demo系列(三):Spring Web+MyBatis Plus

    2021.2.24 更新 1 概述 Spring Web+MyBatis Plus的一个Demo,内容和上一篇类似,因此重点放在MyBatis Plus这里. 2 dao层 MyBatis Plus相 ...

  8. ssm 框架实现增删改查CRUD操作(Spring + SpringMVC + Mybatis 实现增删改查)

    ssm 框架实现增删改查 SpringBoot 项目整合 一.项目准备 1.1 ssm 框架环境搭建 1.2 项目结构图如下 1.3 数据表结构图如下 1.4 运行结果 二.项目实现 1. Emplo ...

  9. 【分享】标准springMVC+mybatis项目maven搭建最精简教程

    文章由来:公司有个实习同学需要做毕业设计,不会搭建环境,我就代劳了,顺便分享给刚入门的小伙伴,我是自学的JAVA,所以我懂的.... (大图直接观看显示很模糊,请在图片上点击右键然后在新窗口打开看) ...

随机推荐

  1. java基础学习之对象转型

    对象转型(casting): 1)一个基类的引用类型变量可以指向其子类的对象 2)一个基类的引用不可以访问其子类对象新增加的成员(属性和方法) 3)可以使用引用变量instanceof类名,来判断该引 ...

  2. chart.js图表库案例赏析,饼图添加文字

    chart.js图表库案例赏析,饼图添加文字 Chart.js 是一个令人印象深刻的 JavaScript 图表库,建立在 HTML5 Canvas 基础上.目前,它支持6种图表类型(折线图,条形图, ...

  3. Analyzer使用第二Y轴,以及同一分析图不同量值使用不同的图形样式

    Analyzer的建立分析图后,图中有两个量值,希望能显示成不同的图形样式,如一个是柱图.一个是线图. 1.设置显示多个量值: 3.设置显示出图例,即表明图中量值内容的说明: 2.右键图例中要修改为不 ...

  4. MySQL自动化安装(双主多从读写分离)

    shell #!/bin/bash # Create by # version 1.0 # // # # check out lockfile whether or not exist IsInput ...

  5. Netsharp快速入门(之14) 销售管理(报表A 热销滞销品统计)

    作者:秋时 杨昶   转载须说明出处 4.5     销售报表 4.5.1  热销滞销品统计 1.建立部件工作区,主部件选择报表.统计表,辅部件选择查询方案 2.设置报表模版.选择主部件,选择工具-报 ...

  6. 匿名类型(C# 编程指南)

    匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型. 类型名由编译器生成,并且不能在源代码级使用.  每个属性的类型由编译器推断. 可通过使用 new 运算 ...

  7. Python编码设置

    系统编码顺序: 1, a.encode(sys.stdout.encoding) 2, a.encode(default_string) sys.stdout.encoding里的值可以用环境变量PY ...

  8. 【数据结构】通用的最小堆(最大堆)D-ary Heap

    听说有一种最小(大)堆,不限于是完全二叉树,而是完全D叉树,名为D-ary Heap(http://en.wikipedia.org/wiki/D-ary_heap).D可以是1,2,3,4,100, ...

  9. hdu 3487 Play with Chain

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 YaoYao is fond of playing his chains. He has a c ...

  10. IOS CoreData 多表查询demo解析

    在IOS CoreData中,多表查询上相对来说,没有SQL直观,但CoreData的功能还是可以完成相关操作的. 下面使用CoreData进行关系数据库的表与表之间的关系演示.生成CoreData和 ...