You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate批量插入仅最后一行生效问题求助

排查Hibernate批量插入仅最后一行生效的问题

先来说最可能的原因,也是这类问题里最常见的坑:你在读取CSV数据的时候,可能重复使用了同一个Attendence对象实例。

举个例子,如果你的读取逻辑是这样的:

Attendence attendence = new Attendence();
List<Attendence> list = new ArrayList<>();
// 循环读取CSV每一行
while (读取行) {
    attendence.setEmployee_id(...);
    attendence.setInTime(...);
    // 设置其他属性
    list.add(attendence);
}

这种情况下,List里的所有元素其实都是同一个Attendence对象的引用。Hibernate的Session会缓存实体对象,当你循环调用session.save(obj)时,Session只会记录这个对象的最后一次状态修改,所以最终只会插入最后一行数据。

验证方法

在添加到List之后,打印每个元素的hashCode():

for (Attendence obj : collection) {
    System.out.println(obj.hashCode());
}

如果所有输出的hashCode都一样,那就能确认是对象复用的问题。

解决方案

每次读取一行CSV数据时,新建一个Attendence对象,而不是重复修改同一个实例:

List<Attendence> list = new ArrayList<>();
// 循环读取CSV每一行
while (读取行) {
    Attendence attendence = new Attendence(); // 每次循环都新建对象
    attendence.setEmployee_id(...);
    attendence.setInTime(...);
    // 设置其他属性
    list.add(attendence);
}

其他可能的排查点

  • 异常被静默吞掉:检查你的CSV读取或插入逻辑中有没有捕获异常但没有打印的情况。比如前面的行插入时因为日期格式不匹配(数据库attend_date是date类型,但实体类用String存储,可能格式转换失败)抛出异常,导致循环提前终止,只有最后一行成功插入。建议在hibernateInsertAttendenceSession方法的循环里添加异常捕获:
for (Attendence obj : collection) {
    try {
        session.save(obj);
        System.out.println("Object Added: " + obj.getEmployee_id() + " " + obj.getDate());
    } catch (Exception e) {
        System.err.println("插入失败:" + obj.toString());
        e.printStackTrace();
    }
}

这样能看到具体哪一行出了问题。

  • 事务提交不规范:虽然你的代码里调用了session.getTransaction().commit(),但如果循环中出现异常,事务可能会被标记为回滚状态,而且原代码没有处理资源泄漏的情况。建议改成更规范的事务写法:
private static SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
public static void hibernateInsertAttendenceSession(List<Attendence> collection) {
    Session session = null;
    Transaction tx = null;
    try {
        session = sessionFactory.openSession();
        tx = session.beginTransaction();
        for (Attendence obj : collection) {
            session.save(obj);
            System.out.println("Object Added");
        }
        tx.commit();
    } catch (Exception e) {
        if (tx != null) {
            tx.rollback();
        }
        e.printStackTrace();
    } finally {
        if (session != null) {
            session.close();
        }
    }
}
  • 实体类与数据库字段类型不匹配:你的实体类中attend_date字段是String类型,但数据库里是date类型,这可能导致插入时日期格式不兼容。建议把实体类的date字段改成java.util.Date或java.time.LocalDate,并添加日期格式化注解:
@Column(name = "attend_date")
@Temporal(TemporalType.DATE)
private Date date;

或者用Java 8的日期类型:

@Column(name = "attend_date")
private LocalDate date;

这样Hibernate能正确处理日期类型的转换,避免因为格式问题导致插入失败。


先从对象复用这个点排查,这是最容易犯的错误,大概率能解决你的问题。如果不是这个原因,再依次检查其他排查点。

内容的提问来源于stack exchange,提问作者Rashedur Rahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:39:50