Java中用Mybatis插入mysql报主键重复问题的解决方法

当尝试插入主键已存在的数据时,通过查询判断数据是否存在。如果存在则更新,否则插入。测试显示,此方法能有效避免主键重复错误,提供了一种实用的解决方案。

首先思路是这样的,先去数据表里面去找有没有这个主键的数据(如果有会有返回值,如果没有则返回null),如果有则对该条数据进行更新操作,如果没有,则对数据表进行插入操作。

原来数据表中有这些数据。


数据表对应的bean的结构如下:

public class DataBean {
    String key;
    String value;

    public DataBean() {

    }
    public DataBean(String key, String value) {
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "DataBean{" +
                "key='" + key + '\'' +
                ", value='" + value + '\'' +
                '}';
    }
}

下面是我Mapper内的内容:

    <insert id="InsertDataToTestTable" parameterType="test.bean.DataBean">
        insert into testtable values(#{key},#{value})
    </insert>

    <update id="UpdateDataToTestTable" parameterType="test.bean.DataBean">
        UPDATE testtable SET value=#{value} WHERE `key`=#{key}
    </update>

    <select id="SelectDataToTestTable" parameterType="int" resultType="test.bean.DataBean">
        SELECT * from testtable where `key`=#{key}
    </select>

首先通过SqlSession.selectOne去查,看我此次想要插入的bean是否存在于表里面(表的主键为key),如果存在,那么select语句会返回Databean对象,此时就可以去对表中数据进行相应的value更新操作了。

如果不存在的话,那么select语句返回的是null,此时就可以进行相应的插入操作,将数据插入到表中。

下面是测试代码:

    public static void main(String[] args) {
        SqlSession session = SqlSessionFactoryUtil.getSqlSession();
         DataBean dataBean=new DataBean();
         dataBean.setKey("123");
         dataBean.setValue("1111");


         if(session.selectOne("DataMapper.SelectDataToTestTable",Integer.valueOf(dataBean.getKey()))!=null){
             //查看select语句输出结果
             System.out.println(session.selectOne("DataMapper.SelectDataToTestTable",Integer.valueOf(dataBean.getKey())));
             session.update("DataMapper.UpdateDataToTestTable",dataBean);
         }else {
             session.insert("DataMapper.InsertDataToTestTable", dataBean);
         }
            session.commit();
    }
现在我的表里面是有key=123,value=111的记录,那么我这次执行程序会将其value更新为1111。下面请看输出结果以及表中数据更改。


select操作在查询key为123的时候返回的值。


并且数据库的记录已经做了对应的更改。


下面我进行插入记录key:123333 value:123123,我们知道表中是没有key为123333的记录的,所以select操作会返回null,然后执行insert操作而不是update操作。

    public static void main(String[] args) {
        SqlSession session = SqlSessionFactoryUtil.getSqlSession();
         DataBean dataBean=new DataBean();
         dataBean.setKey("123333");
         dataBean.setValue("123123");



         if(session.selectOne("DataMapper.SelectDataToTestTable",Integer.valueOf(dataBean.getKey()))!=null){
             //查看select语句输出结果
             System.out.println(session.selectOne("DataMapper.SelectDataToTestTable",Integer.valueOf(dataBean.getKey())));
             session.update("DataMapper.UpdateDataToTestTable",dataBean);
         }else {
             session.insert("DataMapper.InsertDataToTestTable", dataBean);
         }
            session.commit();
    }



至此,当数据库插入数据的时候遇到主键重复的错误问题已经解决,我这里只是提供一种思路和一些简单的实现,希望能对你们有帮助~

你提供了以下字段,其中 `test_time` 和 `test_place` 是**联合主键**: ``` test_time test_place pm2_5 pm10 tsp noise temperature humidity ``` 你的需求是:使用 **MyBatis 实现批量插入或更新(Upsert)**,即: - 如果 `(test_time, test_place)` 已存在,则执行 **UPDATE**; - 如果不存在,则执行 **INSERT**。 这在 MySQL 中可以通过 `ON DUPLICATE KEY UPDATE` 实现,在 PostgreSQL 中用 `ON CONFLICT DO UPDATE`。下面以 **MySQL** 为例进行说明。 --- ### ✅ 第一步:数据库表结构(MySQL) 确保你的表有联合主键: ```sql CREATE TABLE environmental_data ( test_time DATETIME NOT NULL, test_place VARCHAR(255) NOT NULL, pm2_5 DECIMAL(6,2), pm10 DECIMAL(6,2), tsp DECIMAL(8,2), noise DECIMAL(6,2), temperature DECIMAL(5,2), humidity DECIMAL(5,2), PRIMARY KEY (test_time, test_place) ); ``` --- ### ✅ 第二步:Java 实体类 ```java public class EnvironmentalData { private LocalDateTime testTime; private String testPlace; private BigDecimal pm25; private BigDecimal pm10; private BigDecimal tsp; private BigDecimal noise; private BigDecimal temperature; private BigDecimal humidity; // Getters and Setters } ``` --- ### ✅ 第三步:MyBatis Mapper 接口 ```java import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper public interface EnvironmentalDataMapper { void batchInsertOrUpdate(@Param("list") List<EnvironmentalData> dataList); } ``` --- ### ✅ 第四步:MyBatis XML 映射文件(SQL) 创建 `EnvironmentalDataMapper.xml` 文件: ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mapper.EnvironmentalDataMapper"> <insert id="batchInsertOrUpdate"> INSERT INTO environmental_data ( test_time, test_place, pm2_5, pm10, tsp, noise, temperature, humidity ) VALUES <foreach collection="list" item="item" separator=","> ( #{item.testTime}, #{item.testPlace}, #{item.pm25}, #{item.pm10}, #{item.tsp}, #{item.noise}, #{item.temperature}, #{item.humidity} ) </foreach> ON DUPLICATE KEY UPDATE pm2_5 = VALUES(pm2_5), pm10 = VALUES(pm10), tsp = VALUES(tsp), noise = VALUES(noise), temperature = VALUES(temperature), humidity = VALUES(humidity) </insert> </mapper> ``` --- ### ✅ 代码解释 | 部分 | 说明 | |------|------| | `<foreach>` | 循环输入的 `List<EnvironmentalData>`,生成多行 `VALUES` | | `VALUES(...)` | 使用 `VALUES(column)` 获取本次插入的值,用于 `ON DUPLICATE KEY UPDATE` | | `ON DUPLICATE KEY UPDATE` | 当 `(test_time, test_place)` 冲突时,用新值更新其余字段 | --- ### ✅ 调用示例(Service 层) ```java @Service public class EnvironmentalDataService { @Autowired private EnvironmentalDataMapper mapper; public void saveBatch(List<EnvironmentalData> dataList) { if (dataList != null && !dataList.isEmpty()) { mapper.batchInsertOrUpdate(dataList); } } } ``` --- ### ✅ 注意事项 1. **联合主键必须有唯一约束或主键定义**,否则 `ON DUPLICATE KEY UPDATE` 不生效。 2. 字段名与数据库一致(如 `pm2_5` 对应 `pm25` 在 Java 中需用 `@Results` 或命名匹配)。 3. 时间类型建议使用 `LocalDateTime`,数据库对应 `DATETIME`。 4. 若使用 Lombok 可简化 getter/setter: ```java @Data @NoArgsConstructor @AllArgsConstructor public class EnvironmentalData { ... } ``` --- ### ✅ 其他数据库支持 #### PostgreSQL(使用 `ON CONFLICT`) ```xml INSERT INTO environmental_data (...) VALUES <foreach collection="list" item="item" separator=","> (...) </foreach> ON CONFLICT (test_time, test_place) DO UPDATE SET pm2_5 = EXCLUDED.pm2_5, pm10 = EXCLUDED.pm10, ... ``` #### Oracle(可用 MERGE 语句,较复杂) --- ###
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值