以下讨论全部针对Mysql数据库:)
通常业务上至少需要两种类型的不重复插入记录的需求:
- 如果某些关键字段已经在Mysql中存在了,不要重复插入,而是改为更新某些字段。
- 如果某些关键字段已经在Mysql中存在了,不要重复插入,也不需要做更新操作,直接忽略即可。
1、针对上面的第一种,mysql提供了insert into ... on duplicate key update ... 语法(Mysql自己的语法,不属于标准SQL)来实现。这种场景相对常见。使用的前提是,需要定义主键或者唯一性索引,用来告诉Mysql哪些字段的重复会造成主键冲突或者违背唯一性约束条件。当这些情况出现时,就放弃insert操作,转而执行后面的update操作。上一个具体的例子,在ibatis中写的一个上面逻辑的sql:
<statement id="testInsertOnDuplicateKeyUpdate"
parameterClass="com.alibaba.ais.bdc.person.dataobject.UserInfo">
<!--Here the employ_id has been defined as a primary key-->
insert into T_USER_INFO (employ_id,fans_count,follow_count)
values (#employId#,#fansCount#,#followCount#)
ON DUPLICATE KEY UPDATE follow_count=follow_count+1
</statement>
上面的插入操作就会在employ_id发生主键冲突的时候,转变为更新follow_count字段(自增一个单位)。
2、针对上面的第二种,mysql提供了insert ignore into ... 语法(Mysql自己的语法,不属于标准SQL)来实现。这种场景相对要少见一些。 使用的前提是,需要定义主键或者唯一性索引,原因同上面一致。但不同的就是,违背唯一性约束时,直接忽略这次insert操作,然后啥也不干了,也不会报错。。。
但这里有个问题,就是有时业务本身还是需要知道语句到底执行了insert还是没有执行!因为需要根据这个反馈信息,做出不同的处理逻辑。这里给出使用ibatis时,两种不同的处理方法。
- 借助mysql的内置函数row_count()和ibatis的selectKey标签:
- 关于ibatis的selectKey标签,更为常见的用法是在插入对象到DB之后,返回DB自增产生的主键ID。比如:
-
<insert id="testSelectKey">
insert into T_TEST(WATCHER, WATCHEE) values (#watcher#,#watchee#)
<selectKey resultClass="int" keyProperty="id">
select last_insert_id() as ID from dependency limit 1
</selectKey>
</insert>
- 通过上面语句进行插入操作之后,可以通过如下方式在Java代码中获得这个DB自增产生的ID:
-
Integer id = (Integer) sqlMapClient.insert("testSelectKey", param);
- row_count()是Mysql提供可以获得insert、update、delete这几种操作成功处理行数的一个内置函数,有了这个函数,再结合上面给出的selectKey标签的例子,就可以做到获得insert ignore时,成功insert的行数。有了这个行数,也就知道了到底有没有发生insert操作。(发生了插入操作该函数返回值会大于0),于是改编一下上面的sql-map中的sql(注意其中的ignore关键字):
-
<insert id="testInsertIgnore">
insert ignore into T_TEST(WATCHER, WATCHEE) values (#watcher#,#watchee#)
<selectKey resultClass="int" keyProperty="id">
select row_count() as ID from T_USER_RELATION limit 1
</selectKey>
</insert>
通过上面语句进行插入操作之后,可以通过如下方式在Java代码中获得insert真正影响到的行数:
-
Integer affectedRows = (Integer)sqlMapClient.insert("testInsertIgnore", param);
- 利用ibatis的update语句:上面之所以要费劲周折的修改insert语句,时因为ibatis本身的insert不是默认支持返回影响的行数的。但是update语句支持!于是,另外一个思路,就是利用update语句来完成这个insert操作。
-
<update id="testInsertIgnore">
insert ignore into T_USER_RELATION(WATCHER, WATCHEE) values (#watcher#,#watchee#)
<!--Without selectKey tag, it looks mush more concise-->
</update>
通过上面语句进行插入操作之后,可以通过如下方式在Java代码中获得insert真正影响到的行数(这里需要注意的是,Java代码中需要使用sqlMapClient的update的API哦):
-
Integer affectedRows = (Integer)sqlMapClient.update("testInsertIgnore", param);
分享到:
相关推荐
此外,还可以结合`IF NOT EXISTS`语句来避免插入重复数据,但MySQL不直接支持这个语法。不过,你可以通过查询先检查是否存在相同的记录,然后决定是否进行插入操作。这种方法在处理复杂逻辑时可能更为灵活,但它不是...
iBatis 提供了两种批处理的实现方法:在代码中直接进行循环操作和在配置文件中进行循环操作。 **1. 直接在代码中进行循环操作** 这种方法通常适用于简单的批处理需求,例如,你需要对一组数据执行相同的操作,如...
iBATIS支持基本的CRUD(创建、读取、更新、删除)操作,通过在映射文件中定义SQL语句来实现这些功能。 - **读取配置文件**:通过`SqlMapClientBuilder`类可以读取iBATIS的配置文件。 - **SqlMapClientAPI**:提供了...
通过 XML 或注解配置,iBatis 可以将 SQL 语句与 DAO(数据访问对象)层的接口绑定,从而实现数据查询、插入、更新和删除等操作。 Abator 的主要功能包括: 1. **代码生成**:Abator 可以根据数据库表结构自动生成...
逆向工程在MyBatis中的主要作用是通过读取数据库表结构,自动生成与之对应的Java类和Mapper文件,这样开发者就不需要手动编写这些基础代码,而是可以专注于业务逻辑的实现。本篇将探讨如何使用MyBatis逆向工程生成...
- MySQL:利用自增长特性,通过 SQL 语句 `SELECT LAST_INSERT_ID()` 获取最后插入行的 ID。 #### 7. 关联关系处理 - **处理方式**:支持多种关联查询方式,包括连接查询和两次查询方式。 - 一对多:使用连接...
- 日志配置:在`application.yml`中开启MyBatis-Plus的日志输出,通过配置`mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl`。 - SpringBoot禁用启动Banner:通过`spring: ...
示例如下: UserInfoBaseDao : 自动生成的代码, 不能手工修改,用于重复生成 UserInfoDao extends UserInfoBaseDao : 存放手工的代码,不能重复生成 页面的重复生成还没有啥好办法。 语法参考: ...
- **Set**:无序集合,元素不可重复。 - **Collections**:提供一系列静态方法来操作集合。 ##### java的基本数据类型 - 整型:byte、short、int、long - 浮点型:float、double - 字符型:char - 布尔型:boolean ...
Hibernate、Ibatis、Jdbc三者的区别:Hibernate和Ibatis都是JDBC的封装框架,但Hibernate是全自动的ORM映射,而Ibatis是半自动的。 Hibernate的运行原理:Hibernate通过映射关系将Java对象和数据库表进行映射。 ...
JBenchDB 利用 JDBC 提供的通用性,可以对任何兼容 JDBC 的数据库进行基准测试,包括但不限于 MySQL、Oracle、PostgreSQL 和 SQL Server 等。 **3. ORM 集成** Hibernate3 和 Ibatis 是两种广泛使用的 ORM 框架,...