Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate插入,延迟SQL错误(数据截断)_Java_Mysql_Hibernate - Fatal编程技术网

Java Hibernate插入,延迟SQL错误(数据截断)

Java Hibernate插入,延迟SQL错误(数据截断),java,mysql,hibernate,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

我的应用程序解析一个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();
     }
}
publicstaticvoidmain(字符串[]args){
试一试{
List rows=parseCSV();
事务t=openHibernateTransaction();
//doCrudStuff在数据库中插入一些记录
用于(r行:行)
doCrudStuff(r);
t、 提交();
}捕获(例外情况除外){
//日志错误
如果(t!=null)t.rollback();
}
}
当我正要在第78排
记录
时,我突然发现了这个错误:
数据截断:第1行的“某些列与第78行无关”列的数据太长

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

我检查了CSV文件,发现在第77行,某些字段对于数据库列来说确实太长了。但是Hibernate在第77行的
INSERT
过程中没有捕捉到错误,在我为第78行执行
SELECT
时抛出了错误。为什么推迟


Hibernate真的是这样吗?我只在最后提交一次,因为我想确保所有操作都成功,否则,请回滚。

如果考虑到hibernate在幕后为您所做的事情,实际上并不是这样

Hibernate直到需要时才真正执行您的write语句(update,insert),因此在您的情况下,我假设您的“doCrudStuff”执行select,然后执行update或insert,对吗

这就是正在发生的事情:

您告诉hibernate执行“更新我的表SET something=value”;这会导致hibernate在会话中缓存该值并立即返回

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

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

如果其中一次写入失败,当您查看堆栈跟踪时,实际上无法将其映射到您要求的确切位置(这是ORM和直接使用JDBC之间的一个重要区别)休眠以执行写入,而是在必须刷新会话(手动或自动)时失败

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

顺便说一句,如果您希望看到这是一种实践,您可以告诉hibernate记录查询

希望这有帮助

编辑:我明白这会有多混乱,让我通过强调事务和Hibernate会话之间的区别来补充我的答案

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

会话是由Hibernate在数据库之外管理的会话,主要是出于性能原因。Hibernate将尽可能对操作进行排队以提高性能,并且仅在认为必要时才转到数据库

假设你有50个不同颜色的弹珠,需要放在正确的桶里,但这些桶离你100英尺远,你需要有人在正确的桶里正确分类。你让你的朋友鲍勃先储存蓝色弹珠,然后储存红色弹珠,再储存绿色弹珠。你的朋友很聪明,预计你会让他多次往返,所以他会一直走到你最后一次要求他走100英尺,把它们放在合适的桶里,这比三次往返要快得多

现在想象一下,你让他储存黄色的弹珠,然后你问他你在所有的桶里总共有多少个弹珠。然后,他被迫走到桶前(因为他需要收集信息),储存黄色弹珠(这样他可以准确地计算所有桶),然后才能给你答案。这就是hibernate处理数据的本质

在你的情况下,想象没有黄色的桶。不幸的是,鲍勃在回答你关于你总共有多少颗弹珠的问题之前是不会发现的——因此,在事件发生的顺序中,他会回来告诉你,只有在他尝试数数弹珠之后,他才能完成你的请求(与您要求他存储黄色的文件时相反,这是他实际上无法做到的)


希望这有助于澄清一些问题!

Hibernate将开始执行我的写入操作,但它不会提交,除非1)Hibernate设置为auto commit=true或2)transaction.commit()被调用。。。我说得对吗?