Hibernate INSERT,延迟SQL错误(DATA TRUNCATION)

时间:2017-01-13 19:17:56

标签: java mysql hibernate

我的应用程序解析一个CSV文件,每个文件大约有100到200条记录,执行数据库CRUD功能并最终将它们全部提交。

public static void main(String[] args) {
     try {
         List<Row> rows = parseCSV();

         Transaction t = openHibernateTransaction();

         //doCrudStuff INSERTS some records in the database
         for (Row r : rows)
             doCrudStuff(r);

         t.commit();

     } catch (Exception ex) {
           //log error
           if (t != null) t.rollback();
     }
}

当我在78 doCrudStuff即将Row时,我突然遇到了这个错误: Data truncation: Data too long for column 'SOME_COLUMN_UNRELATED_TO_78TH_ROW' at row 1

我读取了堆栈跟踪,错误是由SELECT语句触发到与第78行无关的表。嗯,奇怪吧?

我检查了CSV文件,发现在第77行,某些字段对于数据库列确实太长了。但是Hibernate在第77行的INSERT期间没有捕获到错误,并且当我在第78行执行SELECT时抛出了错误。为什么会延迟?

Hibernate真的像这样吗?我最后只提交一次,因为我想确保一切都成功,否则,回滚。

1 个答案:

答案 0 :(得分:1)

实际上并不是真的,如果你考虑到hibernate在幕后为你做了什么。

Hibernate实际上并不执行你的写语句(更新,插入)直到它需要,因此在你的情况下我假设你的&#34; doCrudStuff&#34;执行一个select然后执行更新或插入权限?

这就是发生的事情:

你告诉hibernate执行&#34; UPDATE my_table SET something = value;&#34;这导致hibernate在会话中缓存它并立即返回。

您可以执行更多写操作,Hibernate可能会继续在会话中缓存,直到1)您手动刷新会话或2)hibernate决定刷新会话的时间。

然后执行SELECT语句以从数据库中获取一些数据。此时,数据库的状态与会话状态不一致,因为有数据等待写入。然后,Hibernate将开始执行写入以将数据库状态赶上会话状态。

如果其中一个写入失败,当您查看堆栈跟踪时,您实际上无法将其映射到您要求的确切位置(这是ORM与使用之间的重要区别) JDBC直接)hibernate执行写操作,但是当必须刷新会话时(无论是手动还是自动),它都会失败。

以牺牲性能为代价,您可以随时告诉hibernate在写入后刷新会话。但只要您了解hibernate会话的生命周期以及它如何缓存这些查询,您就应该能够更轻松地调试这些查询。

顺便说一句,如果你想看到这是练习,你可以告诉hibernate记录查询。

希望这有帮助!

编辑:我理解这可能会让人感到困惑,让我尝试通过突出显示事务和Hibernate会话之间的区别来扩充我的答案。

transaction是在数据库上执行的一系列原子操作。在提交事务之前,通常数据库的其他客户端不会看到它。事务的状态由数据库完全管理 - 即您可以启动事务并将操作发送到数据库,这将确保事务中这些操作的一致性。

Hibernate Session是Hibernate在数据库外部管理的会话,主要是出于性能原因。 Hibernate会尽可能地对操作进行排队以提高性能,并且只在认为必要时才进入数据库。

想象一下,你有50个不同颜色的大理石,需要存放在正确的水桶中,但这些水桶距离100英尺,你需要有人在正确的水桶内正确分类。你问你的朋友鲍勃存储蓝色大理石,然后是红色大理石,然后是绿色大理石。你的朋友很聪明,并且预计你会要求他多次往返,所以直到你最后一次要求走100英尺将它们存放在适当的水桶中,这比进行3次往返要快得多。

现在想象一下,你要求他存放黄色大理石,然后你问他所有桶中有多少弹珠。然后他被迫去桶(因为他需要收集信息),存储黄色大理石(所以他可以准确计算所有桶),然后才能给你一个答案。这实质上就是hibernate对您的数据所做的事情。

在你的情况下,想象一下没有黄桶。不幸的是鲍勃不会发现这一点,直到他试图回答你有多少总弹珠的问题 - 因此在事件的顺序中,他会回到你的面前告诉你他不能完成你的请求在他试图计算大理石之后(而不是当你要求他存储黄色时,这是他实际上无法做到的)。

希望这有助于清除一些事情!