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
相关产品推荐
相关产品推荐

