插入1000条数据正常运行
但是插入100000条数据就报outOfMemoryError错误
Eclipse3.1 , Resin, 512M内存
请问是什么缘故? 应该不会存在死循环, 仅仅是因为数据量大的缘故还是 程序有问题?
63 个解决方案
#1
是不是记数的变量类型有问题?
#2
batch处理?
你每 1000 条提交一次试试。
你每 1000 条提交一次试试。
#3
改大JVM
java -Xmx256M
java -Xmx256M
#4
没有记数变量,循环时用的是
while(rs.next()){
}
请问以下三种情况
A
PurchaseOrderHdTran record = null;
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
B
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
while (resultSet.next()) {
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
C
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
上面ABC三种情况,哪一种是正确的?
while(rs.next()){
}
请问以下三种情况
A
PurchaseOrderHdTran record = null;
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
B
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
while (resultSet.next()) {
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
C
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
上面ABC三种情况,哪一种是正确的?
#5
你是想问 PurchaseOrderHdTran record 变量声明的位置吧?
A 和 C 效果一样,都是对的;B 不对,那样 result 里 add 的总是同一个 record 对象,只是每次 record 对象的值被修改了,到最后 result 里也只有一个对象。
这下知道你的程序为什么 OutOfMemortError 了。你把所有的数据对象都一股脑加到 result 里了(result 应该是个 List 之类的什么东西吧?),那还不溢出了?!
BTW: 你原来说的是“插入数据库”啊,怎么现在看起来是“读数据库”呢?
A 和 C 效果一样,都是对的;B 不对,那样 result 里 add 的总是同一个 record 对象,只是每次 record 对象的值被修改了,到最后 result 里也只有一个对象。
这下知道你的程序为什么 OutOfMemortError 了。你把所有的数据对象都一股脑加到 result 里了(result 应该是个 List 之类的什么东西吧?),那还不溢出了?!
BTW: 你原来说的是“插入数据库”啊,怎么现在看起来是“读数据库”呢?
#6
顶
#7
maquan(ma:kju)
这下知道你的程序为什么 OutOfMemortError 了。你把所有的数据对象都一股脑加到 result 里了(result 应该是个 List 之类的什么东西吧?),那还不溢出了?!
请教一下,为什么都加到result会溢出? result的确是一个List
请问怎样才不会溢出?
我现在用AC两种情况,都是溢出,但是B可以正常取得数据.插入到数据库是后面一步,目前正在插入,都运行15分钟还在跑,受不了了
这下知道你的程序为什么 OutOfMemortError 了。你把所有的数据对象都一股脑加到 result 里了(result 应该是个 List 之类的什么东西吧?),那还不溢出了?!
请教一下,为什么都加到result会溢出? result的确是一个List
请问怎样才不会溢出?
我现在用AC两种情况,都是溢出,但是B可以正常取得数据.插入到数据库是后面一步,目前正在插入,都运行15分钟还在跑,受不了了
#8
Rs如果记录太多,也是有可能会Out Of Memory Error,这我遇上过.
后来我都是用将记录数控制在1000条才搞定.
不知道楼主用什么数据库?
后来我都是用将记录数控制在1000条才搞定.
不知道楼主用什么数据库?
#9
数据库是ORACLE9
上述B这种情况
我10万条记录, result里add了10万次的同一个record对象,就是说record里有10万个相同的record对象.
比如: 我result.add("1")
我再 result.add("1")
这样 result了两次, result的长度是2了吧.
同样, result里add了10万个record对象,它的长度应该是10万吧?
这样理解有什么错吗?
上述B这种情况
我10万条记录, result里add了10万次的同一个record对象,就是说record里有10万个相同的record对象.
比如: 我result.add("1")
我再 result.add("1")
这样 result了两次, result的长度是2了吧.
同样, result里add了10万个record对象,它的长度应该是10万吧?
这样理解有什么错吗?
#10
对于AC 这种情况
C
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
//这里加上一句
record = null;
}
这样是否可以释放内存,避免出现OutOfMemory?
C
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
//这里加上一句
record = null;
}
这样是否可以释放内存,避免出现OutOfMemory?
#11
上次我用mysql也出现这问题.
没想到Oracle也会这样.
没想到Oracle也会这样.
#12
经过试验,只有B 是可行的
AC都会内存溢出
AC都会内存溢出
#13
B 不会出现内存溢出,但程序逻辑是错误的,result 里永远只有一个 record 对象(如果你检查 result.size(),也许是 10 万,好像 list 里保存了 10 万个对象,实际上这只是 10 万个引用,引用的是同一个对象,就是一开始你 new 出来的那个 PurchaseOrderHdTran 对象,而这个对象的值是你从 resultSet 里面取出的最后一条记录)。
A 和 C 会出现内存溢出,是因为你试图创建 10 万个 PurchaseOrderHdTran 对象。程序一般不应该写成这个样子,这种程序运行时的内存开销是没有限制的,即使你把虚拟机的内存开到 1G,那么,当数据库里有 800 万条记录又怎么样?!
正确的做法应该是分批处理,读出一定数量的记录,在 result 里积攒了一定数量的对象后,就要对他们做进一步的处理,处理完成后释放它们,然后再继续处理 resultSet 里面后继的记录。
A 和 C 会出现内存溢出,是因为你试图创建 10 万个 PurchaseOrderHdTran 对象。程序一般不应该写成这个样子,这种程序运行时的内存开销是没有限制的,即使你把虚拟机的内存开到 1G,那么,当数据库里有 800 万条记录又怎么样?!
正确的做法应该是分批处理,读出一定数量的记录,在 result 里积攒了一定数量的对象后,就要对他们做进一步的处理,处理完成后释放它们,然后再继续处理 resultSet 里面后继的记录。
#14
验证以后,B的确是只有一条记录,就是最后一条.
#15
对于C
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
这种情况,具体的控制应该怎么写呢?如果我1000条记录作为一批,该如何来写相关的程序?
谢谢各位大侠帮忙了
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
这种情况,具体的控制应该怎么写呢?如果我1000条记录作为一批,该如何来写相关的程序?
谢谢各位大侠帮忙了
#16
假设你原来的程序是:
List result = new ArrayList();
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
processResult(result);
那就改成:
List result = new ArrayList();
int counter = 0;
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
if ((++counter) > 1000) {
processResult(result);
result.clear(); // 或者是 result = new ArrayList(); 也行
counter = 0;
}
}
processResult(result);
List result = new ArrayList();
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
processResult(result);
那就改成:
List result = new ArrayList();
int counter = 0;
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
if ((++counter) > 1000) {
processResult(result);
result.clear(); // 或者是 result = new ArrayList(); 也行
counter = 0;
}
}
processResult(result);
#17
加大一个内存的数量,
之后每次500条一提交,不要太大。
之后每次500条一提交,不要太大。
#18
明白了,谢谢.
不过现在情况是
我在A类里调用B类的这个select()方法
B类里
public List select() {
List result = new ArrayList();
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
return result;
}
照前面大哥写的, processResult(result)应该是自定义的一个方法吧?
当我取满1000条的时候, return result肯定是不可以的.
这样的话,A类里的逻辑要调整不少啊.改动大了.
其实做的是外包项目,老外说,他们用512M的内存可以10分钟之内跑完10万条记录.我们这里就是不行,连1个G的内存也不行. JVM的内存已经改到900M内存了,也还是不行
不过现在情况是
我在A类里调用B类的这个select()方法
B类里
public List select() {
List result = new ArrayList();
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
return result;
}
照前面大哥写的, processResult(result)应该是自定义的一个方法吧?
当我取满1000条的时候, return result肯定是不可以的.
这样的话,A类里的逻辑要调整不少啊.改动大了.
其实做的是外包项目,老外说,他们用512M的内存可以10分钟之内跑完10万条记录.我们这里就是不行,连1个G的内存也不行. JVM的内存已经改到900M内存了,也还是不行
#19
前面说的只能当个思路,程序还要你自己写。
“分批处理”是必须的,除非你能肯定数据量永远是在一个可以承受的范围之内。不知道你 A 类里的程序逻辑是什么样,一般来说,改成“分批处理”不会太麻烦。“改动大了”也得改,不改会死! :D
说实话,我的感觉,10 分钟跑完 10 万条记录还算比较保守的。不用那么大的内存,扩内存意义也不大,关键是要优化程序逻辑、优化对数据库的访问。
“分批处理”是必须的,除非你能肯定数据量永远是在一个可以承受的范围之内。不知道你 A 类里的程序逻辑是什么样,一般来说,改成“分批处理”不会太麻烦。“改动大了”也得改,不改会死! :D
说实话,我的感觉,10 分钟跑完 10 万条记录还算比较保守的。不用那么大的内存,扩内存意义也不大,关键是要优化程序逻辑、优化对数据库的访问。
#20
谢谢maquan
懂了不少啊
懂了不少啊
#21
mark!
#22
B完全是错误的,当然不会溢出
#23
我认为内存溢出是jvm的事情,和oracle库是没有关系的
你可以加大分配给jvm的内存。
或者控制你的程序占用内存的数量
你可以加大分配给jvm的内存。
或者控制你的程序占用内存的数量
#24
http://blog.sina.com.cn/u/1244756857 :
在嵌入式“武林”中,流传着几本人人都想偷学几招的C语言的武功秘籍。这些秘籍都是旷世武学奇才耗尽毕生精力所著,部分秘籍流经数十载仍经久不衰,让它的无数实习者受益匪浅。 今天,承蒙武林大会所拖,在这公布这几本关于C的“经书”,让更多人实习之,练就一身绝世的嵌入式C语言好功夫。 武功秘籍排行榜:
1. The C programming language 《C程序设计语言》
2. Pointers on C 《C和指针》
3. C traps and pitfalls 《C陷阱与缺陷》
4. Expert C Lanuage 《专家C编程》
5. Writing Clean Code -----Microsoft Techiniques for Developing Bug-free C Programs 《编程精粹--Microsoft 编写优质无错C程序秘诀》
6. Programming Embedded Systems in C and C 《嵌入式系统编程》
7.《C语言嵌入式系统编程修炼》
8.《高质量C /C编程指南》林锐
在嵌入式“武林”中,流传着几本人人都想偷学几招的C语言的武功秘籍。这些秘籍都是旷世武学奇才耗尽毕生精力所著,部分秘籍流经数十载仍经久不衰,让它的无数实习者受益匪浅。 今天,承蒙武林大会所拖,在这公布这几本关于C的“经书”,让更多人实习之,练就一身绝世的嵌入式C语言好功夫。 武功秘籍排行榜:
1. The C programming language 《C程序设计语言》
2. Pointers on C 《C和指针》
3. C traps and pitfalls 《C陷阱与缺陷》
4. Expert C Lanuage 《专家C编程》
5. Writing Clean Code -----Microsoft Techiniques for Developing Bug-free C Programs 《编程精粹--Microsoft 编写优质无错C程序秘诀》
6. Programming Embedded Systems in C and C 《嵌入式系统编程》
7.《C语言嵌入式系统编程修炼》
8.《高质量C /C编程指南》林锐
#25
你也真够狠的
不管有多少条
一次性读完
再插入数据库……
再多内存也会被耗尽的
不管有多少条
一次性读完
再插入数据库……
再多内存也会被耗尽的
#26
默认分配给JVM的是64M内存,不管你用什么方式,当你使用的内存空间大于JVM的内存空间就会
outOfMemoryError,
就好比的一个512M的计算机,非要干 1G的东西到内存中是不可能的,windows处理这个文件是建立
缓存文件。你如果有更多的数据就考虑设计上了。
outOfMemoryError,
就好比的一个512M的计算机,非要干 1G的东西到内存中是不可能的,windows处理这个文件是建立
缓存文件。你如果有更多的数据就考虑设计上了。
#27
Good!
#28
网络连接速度,数据库服务器性能,客户端性能是三个影响你的更新速度的主要因素,
你的最终处理速度取决于这三项的瓶颈
你的最终处理速度取决于这三项的瓶颈
#29
不管多大的内cun,都不应该这么写吧,分批处理,就像要读入或者写入一个特别大的文件一样都是分批处理的。
#30
不要试图一口吃个胖子,即使,你可以。
#31
ArrayList执行add操作的纪录数是有一个限度数的,超过了就会outofmemory.
如果数据量很大,尽量不要一次性把数据库所有数据读出来。最好分批读。
如果数据量很大,尽量不要一次性把数据库所有数据读出来。最好分批读。
#32
唉,,,,
数据库表建一下索引啦。
数据库表建一下索引啦。
#33
如果就是为了把数据库里的数据取出来又插入到其他的表的话,写个存储过程好了,
#34
用性能插件看看究竟是哪里消耗了内存,再对症下药。
#35
如果你不想分批处理的话,建议你使用ArrayList的trimToSize(),因为ArrayList达到容量是否每次都是50%的扩大(不过大数据量还是分批吧)
#36
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
while (resultSet.next()) {
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
B是适当的选择,AC在循环里new对象,会大量消耗内存。
while (resultSet.next()) {
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
B是适当的选择,AC在循环里new对象,会大量消耗内存。
#37
使用 -X参数,我的程序读写百万条记录都没有问题!
#38
A\C顶多就是OutOfMemory,只要优化/改进下就行了
B根本就是设计错误......连List的概念都不清楚.和我当初刚摸Java的时候一样,哈
10分钟10万条的性能不过分啊,蛮简单的.
我记得ResultSet内记录过多的话,也会内存溢出的.大数据量的程序必须对ResultSet进行优化/减肥的.
List同理.
好久没上CSDN了,感叹下
B根本就是设计错误......连List的概念都不清楚.和我当初刚摸Java的时候一样,哈
10分钟10万条的性能不过分啊,蛮简单的.
我记得ResultSet内记录过多的话,也会内存溢出的.大数据量的程序必须对ResultSet进行优化/减肥的.
List同理.
好久没上CSDN了,感叹下
#39
> 我记得ResultSet内记录过多的话,也会内存溢出的.大数据量的程序必须对ResultSet进行优化/减肥的.
haha,这个问题我遇到过。MySQL 的 Connector/J 缺省的实现方式是,不管你用不用,先把所有记录从服务器上传过来,全部保存在客户端的内存中!好家伙,那还不撑暴了!
要改变它的这种工作方式,就要
PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
这样查询出来的 ResultSet 就是“用一条才从服务器上抓一条过来”。
其实,更好的办法也许是修改查询语句(比如加上 LIMIT),不要让 ResultSet 里有那么多的记录,因为绝大多数情况下并不是真的要查出那么多记录来。就像 junyi2003(超级菜鸟) 说的那样,对ResultSet进行优化/减肥。
【以上描述仅限于 MySQL & Connector/J,其它的数据库/驱动就不清楚了。】
haha,这个问题我遇到过。MySQL 的 Connector/J 缺省的实现方式是,不管你用不用,先把所有记录从服务器上传过来,全部保存在客户端的内存中!好家伙,那还不撑暴了!
要改变它的这种工作方式,就要
PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
这样查询出来的 ResultSet 就是“用一条才从服务器上抓一条过来”。
其实,更好的办法也许是修改查询语句(比如加上 LIMIT),不要让 ResultSet 里有那么多的记录,因为绝大多数情况下并不是真的要查出那么多记录来。就像 junyi2003(超级菜鸟) 说的那样,对ResultSet进行优化/减肥。
【以上描述仅限于 MySQL & Connector/J,其它的数据库/驱动就不清楚了。】
#40
抱歉,上面说的不全,应该是:
PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ps.setFetchSize(Integer.MIN_VALUE);
这样才能有效改变它的工作方式。
PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ps.setFetchSize(Integer.MIN_VALUE);
这样才能有效改变它的工作方式。
#41
100000条记录说大不大,说小也不小了!
应该避免这种操作
应该避免这种操作
#42
String str = "select max(oraID) as MaxID from oraTable";
...
str = "select * from oraTable where rownum<=1000 order by oraID";
...
List result = new ArrayList();
PurchaseOrderHdTran record;
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
while(CurID>=MaxID)
{
str = "select * from oraTable where oraID>=CurID and rownum<=1000 order by oraID";
...
result = new ArrayList();
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
}
...
str = "select * from oraTable where rownum<=1000 order by oraID";
...
List result = new ArrayList();
PurchaseOrderHdTran record;
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
while(CurID>=MaxID)
{
str = "select * from oraTable where oraID>=CurID and rownum<=1000 order by oraID";
...
result = new ArrayList();
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
}
#43
str = "select * from oraTable where oraID>CurID and rownum<=1000 order by oraID";
#44
ResultSet最多只能存4万左右的记录,解决只能是分批分段处理,用数据库本身技术写存储过程可以解决,另外不知道你们的项目是用什么框架和技术,HIBERNATE里有分段取值(试一下,有个最优值),用着还行,我导出16万条数据,花了10几分钟,哈哈
#45
upmark
#46
while(CurID<=MaxID)
{
str = "select * from oraTable where oraID>=CurID and rownum<=1000 order by oraID";
...
result = new ArrayList();
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
}
{
str = "select * from oraTable where oraID>=CurID and rownum<=1000 order by oraID";
...
result = new ArrayList();
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
}
#47
典型的java内存泄漏.
如果result始终这样,GC无法回收.
所以应当每批数据就将result置为null以断绝result里对象的引用,从而让GC回收.
如果result始终这样,GC无法回收.
所以应当每批数据就将result置为null以断绝result里对象的引用,从而让GC回收.
#48
mark
#49
/**
* 测试成批插入数据的事务处理,返回是否成功
*
* @param objPO Object
* @return boolean
*/
public boolean insertBatch(final Object objPO)
{
boolean isSuccess = false;
Transaction transaction = null;
try
{
transaction = session.beginTransaction();
for(int i = 0;i < 100000;i++)
{
session.save(objPO);
if(i % 20 == 0)
{
// flush a batch of inserts and release memory
session.flush();
session.clear();
}
}
transaction.commit();
logger.info("transaction.wasCommitted:" + transaction.wasCommitted());
isSuccess = true;
}
catch(HibernateException ex)
{
if(transaction != null)
{
try
{
transaction.rollback();
logger.error("transaction.wasRolledBack:" + transaction.wasRolledBack());
}
catch(HibernateException ex1)
{
logger.error(ex1.getMessage());
ex1.printStackTrace();
}
}
logger.error("Insert Batch PO Error:" + ex.getMessage());
ex.printStackTrace();
}
finally
{
if(transaction != null)
{
transaction = null;
}
}
return isSuccess;
}
/**
* 成批插入或更新数据,默认20条时就写入数据库,并释放内存出来,返回是否成功
*
* @param list List
* @return boolean
*/
public boolean saveOrUpdateBatch(final List list)
{
return saveOrUpdateBatch(list,20);
}
/**
* 成批插入或更新数据,设置每多少条时就写入数据库,并释放内存出来,返回是否成功
*
* @param list List
* @param iBatch int
* @return boolean
*/
public boolean saveOrUpdateBatch(final List list,final int iBatch)
{
boolean isSuccess = false;
Transaction transaction = null;
int iCount = 0;
try
{
transaction = session.beginTransaction();
session.clear();
for(final Iterator it = list.iterator();it.hasNext();)
{
logger.info("iCount:" + iCount);
session.saveOrUpdate(it.next()); // saveOrUpdate
iCount++;
logger.info("iCount:" + iCount);
if(iCount % iBatch == 0)
{
session.flush();
session.clear();
}
}
transaction.commit();
logger.info("transaction.wasCommitted:" + transaction.wasCommitted());
isSuccess = true;
}
catch(HibernateException ex)
{
if(transaction != null)
{
try
{
transaction.rollback();
logger.error("transaction.wasRolledBack:" + transaction.wasRolledBack());
}
catch(HibernateException ex1)
{
logger.error(ex1.getMessage());
ex1.printStackTrace();
}
}
logger.error("Save Or Update Batch PO Error:" + ex.getMessage());
ex.printStackTrace();
}
finally
{
if(transaction != null)
{
transaction = null;
}
}
return isSuccess;
}
* 测试成批插入数据的事务处理,返回是否成功
*
* @param objPO Object
* @return boolean
*/
public boolean insertBatch(final Object objPO)
{
boolean isSuccess = false;
Transaction transaction = null;
try
{
transaction = session.beginTransaction();
for(int i = 0;i < 100000;i++)
{
session.save(objPO);
if(i % 20 == 0)
{
// flush a batch of inserts and release memory
session.flush();
session.clear();
}
}
transaction.commit();
logger.info("transaction.wasCommitted:" + transaction.wasCommitted());
isSuccess = true;
}
catch(HibernateException ex)
{
if(transaction != null)
{
try
{
transaction.rollback();
logger.error("transaction.wasRolledBack:" + transaction.wasRolledBack());
}
catch(HibernateException ex1)
{
logger.error(ex1.getMessage());
ex1.printStackTrace();
}
}
logger.error("Insert Batch PO Error:" + ex.getMessage());
ex.printStackTrace();
}
finally
{
if(transaction != null)
{
transaction = null;
}
}
return isSuccess;
}
/**
* 成批插入或更新数据,默认20条时就写入数据库,并释放内存出来,返回是否成功
*
* @param list List
* @return boolean
*/
public boolean saveOrUpdateBatch(final List list)
{
return saveOrUpdateBatch(list,20);
}
/**
* 成批插入或更新数据,设置每多少条时就写入数据库,并释放内存出来,返回是否成功
*
* @param list List
* @param iBatch int
* @return boolean
*/
public boolean saveOrUpdateBatch(final List list,final int iBatch)
{
boolean isSuccess = false;
Transaction transaction = null;
int iCount = 0;
try
{
transaction = session.beginTransaction();
session.clear();
for(final Iterator it = list.iterator();it.hasNext();)
{
logger.info("iCount:" + iCount);
session.saveOrUpdate(it.next()); // saveOrUpdate
iCount++;
logger.info("iCount:" + iCount);
if(iCount % iBatch == 0)
{
session.flush();
session.clear();
}
}
transaction.commit();
logger.info("transaction.wasCommitted:" + transaction.wasCommitted());
isSuccess = true;
}
catch(HibernateException ex)
{
if(transaction != null)
{
try
{
transaction.rollback();
logger.error("transaction.wasRolledBack:" + transaction.wasRolledBack());
}
catch(HibernateException ex1)
{
logger.error(ex1.getMessage());
ex1.printStackTrace();
}
}
logger.error("Save Or Update Batch PO Error:" + ex.getMessage());
ex.printStackTrace();
}
finally
{
if(transaction != null)
{
transaction = null;
}
}
return isSuccess;
}
#50
ABC都是正确的;
但是对于大数据量是不合理的;
add应该有个度,只取本次需要看到的
但是对于大数据量是不合理的;
add应该有个度,只取本次需要看到的
#1
是不是记数的变量类型有问题?
#2
batch处理?
你每 1000 条提交一次试试。
你每 1000 条提交一次试试。
#3
改大JVM
java -Xmx256M
java -Xmx256M
#4
没有记数变量,循环时用的是
while(rs.next()){
}
请问以下三种情况
A
PurchaseOrderHdTran record = null;
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
B
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
while (resultSet.next()) {
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
C
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
上面ABC三种情况,哪一种是正确的?
while(rs.next()){
}
请问以下三种情况
A
PurchaseOrderHdTran record = null;
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
B
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
while (resultSet.next()) {
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
C
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
上面ABC三种情况,哪一种是正确的?
#5
你是想问 PurchaseOrderHdTran record 变量声明的位置吧?
A 和 C 效果一样,都是对的;B 不对,那样 result 里 add 的总是同一个 record 对象,只是每次 record 对象的值被修改了,到最后 result 里也只有一个对象。
这下知道你的程序为什么 OutOfMemortError 了。你把所有的数据对象都一股脑加到 result 里了(result 应该是个 List 之类的什么东西吧?),那还不溢出了?!
BTW: 你原来说的是“插入数据库”啊,怎么现在看起来是“读数据库”呢?
A 和 C 效果一样,都是对的;B 不对,那样 result 里 add 的总是同一个 record 对象,只是每次 record 对象的值被修改了,到最后 result 里也只有一个对象。
这下知道你的程序为什么 OutOfMemortError 了。你把所有的数据对象都一股脑加到 result 里了(result 应该是个 List 之类的什么东西吧?),那还不溢出了?!
BTW: 你原来说的是“插入数据库”啊,怎么现在看起来是“读数据库”呢?
#6
顶
#7
maquan(ma:kju)
这下知道你的程序为什么 OutOfMemortError 了。你把所有的数据对象都一股脑加到 result 里了(result 应该是个 List 之类的什么东西吧?),那还不溢出了?!
请教一下,为什么都加到result会溢出? result的确是一个List
请问怎样才不会溢出?
我现在用AC两种情况,都是溢出,但是B可以正常取得数据.插入到数据库是后面一步,目前正在插入,都运行15分钟还在跑,受不了了
这下知道你的程序为什么 OutOfMemortError 了。你把所有的数据对象都一股脑加到 result 里了(result 应该是个 List 之类的什么东西吧?),那还不溢出了?!
请教一下,为什么都加到result会溢出? result的确是一个List
请问怎样才不会溢出?
我现在用AC两种情况,都是溢出,但是B可以正常取得数据.插入到数据库是后面一步,目前正在插入,都运行15分钟还在跑,受不了了
#8
Rs如果记录太多,也是有可能会Out Of Memory Error,这我遇上过.
后来我都是用将记录数控制在1000条才搞定.
不知道楼主用什么数据库?
后来我都是用将记录数控制在1000条才搞定.
不知道楼主用什么数据库?
#9
数据库是ORACLE9
上述B这种情况
我10万条记录, result里add了10万次的同一个record对象,就是说record里有10万个相同的record对象.
比如: 我result.add("1")
我再 result.add("1")
这样 result了两次, result的长度是2了吧.
同样, result里add了10万个record对象,它的长度应该是10万吧?
这样理解有什么错吗?
上述B这种情况
我10万条记录, result里add了10万次的同一个record对象,就是说record里有10万个相同的record对象.
比如: 我result.add("1")
我再 result.add("1")
这样 result了两次, result的长度是2了吧.
同样, result里add了10万个record对象,它的长度应该是10万吧?
这样理解有什么错吗?
#10
对于AC 这种情况
C
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
//这里加上一句
record = null;
}
这样是否可以释放内存,避免出现OutOfMemory?
C
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
//这里加上一句
record = null;
}
这样是否可以释放内存,避免出现OutOfMemory?
#11
上次我用mysql也出现这问题.
没想到Oracle也会这样.
没想到Oracle也会这样.
#12
经过试验,只有B 是可行的
AC都会内存溢出
AC都会内存溢出
#13
B 不会出现内存溢出,但程序逻辑是错误的,result 里永远只有一个 record 对象(如果你检查 result.size(),也许是 10 万,好像 list 里保存了 10 万个对象,实际上这只是 10 万个引用,引用的是同一个对象,就是一开始你 new 出来的那个 PurchaseOrderHdTran 对象,而这个对象的值是你从 resultSet 里面取出的最后一条记录)。
A 和 C 会出现内存溢出,是因为你试图创建 10 万个 PurchaseOrderHdTran 对象。程序一般不应该写成这个样子,这种程序运行时的内存开销是没有限制的,即使你把虚拟机的内存开到 1G,那么,当数据库里有 800 万条记录又怎么样?!
正确的做法应该是分批处理,读出一定数量的记录,在 result 里积攒了一定数量的对象后,就要对他们做进一步的处理,处理完成后释放它们,然后再继续处理 resultSet 里面后继的记录。
A 和 C 会出现内存溢出,是因为你试图创建 10 万个 PurchaseOrderHdTran 对象。程序一般不应该写成这个样子,这种程序运行时的内存开销是没有限制的,即使你把虚拟机的内存开到 1G,那么,当数据库里有 800 万条记录又怎么样?!
正确的做法应该是分批处理,读出一定数量的记录,在 result 里积攒了一定数量的对象后,就要对他们做进一步的处理,处理完成后释放它们,然后再继续处理 resultSet 里面后继的记录。
#14
验证以后,B的确是只有一条记录,就是最后一条.
#15
对于C
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
这种情况,具体的控制应该怎么写呢?如果我1000条记录作为一批,该如何来写相关的程序?
谢谢各位大侠帮忙了
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
这种情况,具体的控制应该怎么写呢?如果我1000条记录作为一批,该如何来写相关的程序?
谢谢各位大侠帮忙了
#16
假设你原来的程序是:
List result = new ArrayList();
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
processResult(result);
那就改成:
List result = new ArrayList();
int counter = 0;
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
if ((++counter) > 1000) {
processResult(result);
result.clear(); // 或者是 result = new ArrayList(); 也行
counter = 0;
}
}
processResult(result);
List result = new ArrayList();
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
processResult(result);
那就改成:
List result = new ArrayList();
int counter = 0;
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
if ((++counter) > 1000) {
processResult(result);
result.clear(); // 或者是 result = new ArrayList(); 也行
counter = 0;
}
}
processResult(result);
#17
加大一个内存的数量,
之后每次500条一提交,不要太大。
之后每次500条一提交,不要太大。
#18
明白了,谢谢.
不过现在情况是
我在A类里调用B类的这个select()方法
B类里
public List select() {
List result = new ArrayList();
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
return result;
}
照前面大哥写的, processResult(result)应该是自定义的一个方法吧?
当我取满1000条的时候, return result肯定是不可以的.
这样的话,A类里的逻辑要调整不少啊.改动大了.
其实做的是外包项目,老外说,他们用512M的内存可以10分钟之内跑完10万条记录.我们这里就是不行,连1个G的内存也不行. JVM的内存已经改到900M内存了,也还是不行
不过现在情况是
我在A类里调用B类的这个select()方法
B类里
public List select() {
List result = new ArrayList();
while (resultSet.next()) {
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
return result;
}
照前面大哥写的, processResult(result)应该是自定义的一个方法吧?
当我取满1000条的时候, return result肯定是不可以的.
这样的话,A类里的逻辑要调整不少啊.改动大了.
其实做的是外包项目,老外说,他们用512M的内存可以10分钟之内跑完10万条记录.我们这里就是不行,连1个G的内存也不行. JVM的内存已经改到900M内存了,也还是不行
#19
前面说的只能当个思路,程序还要你自己写。
“分批处理”是必须的,除非你能肯定数据量永远是在一个可以承受的范围之内。不知道你 A 类里的程序逻辑是什么样,一般来说,改成“分批处理”不会太麻烦。“改动大了”也得改,不改会死! :D
说实话,我的感觉,10 分钟跑完 10 万条记录还算比较保守的。不用那么大的内存,扩内存意义也不大,关键是要优化程序逻辑、优化对数据库的访问。
“分批处理”是必须的,除非你能肯定数据量永远是在一个可以承受的范围之内。不知道你 A 类里的程序逻辑是什么样,一般来说,改成“分批处理”不会太麻烦。“改动大了”也得改,不改会死! :D
说实话,我的感觉,10 分钟跑完 10 万条记录还算比较保守的。不用那么大的内存,扩内存意义也不大,关键是要优化程序逻辑、优化对数据库的访问。
#20
谢谢maquan
懂了不少啊
懂了不少啊
#21
mark!
#22
B完全是错误的,当然不会溢出
#23
我认为内存溢出是jvm的事情,和oracle库是没有关系的
你可以加大分配给jvm的内存。
或者控制你的程序占用内存的数量
你可以加大分配给jvm的内存。
或者控制你的程序占用内存的数量
#24
http://blog.sina.com.cn/u/1244756857 :
在嵌入式“武林”中,流传着几本人人都想偷学几招的C语言的武功秘籍。这些秘籍都是旷世武学奇才耗尽毕生精力所著,部分秘籍流经数十载仍经久不衰,让它的无数实习者受益匪浅。 今天,承蒙武林大会所拖,在这公布这几本关于C的“经书”,让更多人实习之,练就一身绝世的嵌入式C语言好功夫。 武功秘籍排行榜:
1. The C programming language 《C程序设计语言》
2. Pointers on C 《C和指针》
3. C traps and pitfalls 《C陷阱与缺陷》
4. Expert C Lanuage 《专家C编程》
5. Writing Clean Code -----Microsoft Techiniques for Developing Bug-free C Programs 《编程精粹--Microsoft 编写优质无错C程序秘诀》
6. Programming Embedded Systems in C and C 《嵌入式系统编程》
7.《C语言嵌入式系统编程修炼》
8.《高质量C /C编程指南》林锐
在嵌入式“武林”中,流传着几本人人都想偷学几招的C语言的武功秘籍。这些秘籍都是旷世武学奇才耗尽毕生精力所著,部分秘籍流经数十载仍经久不衰,让它的无数实习者受益匪浅。 今天,承蒙武林大会所拖,在这公布这几本关于C的“经书”,让更多人实习之,练就一身绝世的嵌入式C语言好功夫。 武功秘籍排行榜:
1. The C programming language 《C程序设计语言》
2. Pointers on C 《C和指针》
3. C traps and pitfalls 《C陷阱与缺陷》
4. Expert C Lanuage 《专家C编程》
5. Writing Clean Code -----Microsoft Techiniques for Developing Bug-free C Programs 《编程精粹--Microsoft 编写优质无错C程序秘诀》
6. Programming Embedded Systems in C and C 《嵌入式系统编程》
7.《C语言嵌入式系统编程修炼》
8.《高质量C /C编程指南》林锐
#25
你也真够狠的
不管有多少条
一次性读完
再插入数据库……
再多内存也会被耗尽的
不管有多少条
一次性读完
再插入数据库……
再多内存也会被耗尽的
#26
默认分配给JVM的是64M内存,不管你用什么方式,当你使用的内存空间大于JVM的内存空间就会
outOfMemoryError,
就好比的一个512M的计算机,非要干 1G的东西到内存中是不可能的,windows处理这个文件是建立
缓存文件。你如果有更多的数据就考虑设计上了。
outOfMemoryError,
就好比的一个512M的计算机,非要干 1G的东西到内存中是不可能的,windows处理这个文件是建立
缓存文件。你如果有更多的数据就考虑设计上了。
#27
Good!
#28
网络连接速度,数据库服务器性能,客户端性能是三个影响你的更新速度的主要因素,
你的最终处理速度取决于这三项的瓶颈
你的最终处理速度取决于这三项的瓶颈
#29
不管多大的内cun,都不应该这么写吧,分批处理,就像要读入或者写入一个特别大的文件一样都是分批处理的。
#30
不要试图一口吃个胖子,即使,你可以。
#31
ArrayList执行add操作的纪录数是有一个限度数的,超过了就会outofmemory.
如果数据量很大,尽量不要一次性把数据库所有数据读出来。最好分批读。
如果数据量很大,尽量不要一次性把数据库所有数据读出来。最好分批读。
#32
唉,,,,
数据库表建一下索引啦。
数据库表建一下索引啦。
#33
如果就是为了把数据库里的数据取出来又插入到其他的表的话,写个存储过程好了,
#34
用性能插件看看究竟是哪里消耗了内存,再对症下药。
#35
如果你不想分批处理的话,建议你使用ArrayList的trimToSize(),因为ArrayList达到容量是否每次都是50%的扩大(不过大数据量还是分批吧)
#36
PurchaseOrderHdTran record = new PurchaseOrderHdTran();
while (resultSet.next()) {
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
B是适当的选择,AC在循环里new对象,会大量消耗内存。
while (resultSet.next()) {
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
B是适当的选择,AC在循环里new对象,会大量消耗内存。
#37
使用 -X参数,我的程序读写百万条记录都没有问题!
#38
A\C顶多就是OutOfMemory,只要优化/改进下就行了
B根本就是设计错误......连List的概念都不清楚.和我当初刚摸Java的时候一样,哈
10分钟10万条的性能不过分啊,蛮简单的.
我记得ResultSet内记录过多的话,也会内存溢出的.大数据量的程序必须对ResultSet进行优化/减肥的.
List同理.
好久没上CSDN了,感叹下
B根本就是设计错误......连List的概念都不清楚.和我当初刚摸Java的时候一样,哈
10分钟10万条的性能不过分啊,蛮简单的.
我记得ResultSet内记录过多的话,也会内存溢出的.大数据量的程序必须对ResultSet进行优化/减肥的.
List同理.
好久没上CSDN了,感叹下
#39
> 我记得ResultSet内记录过多的话,也会内存溢出的.大数据量的程序必须对ResultSet进行优化/减肥的.
haha,这个问题我遇到过。MySQL 的 Connector/J 缺省的实现方式是,不管你用不用,先把所有记录从服务器上传过来,全部保存在客户端的内存中!好家伙,那还不撑暴了!
要改变它的这种工作方式,就要
PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
这样查询出来的 ResultSet 就是“用一条才从服务器上抓一条过来”。
其实,更好的办法也许是修改查询语句(比如加上 LIMIT),不要让 ResultSet 里有那么多的记录,因为绝大多数情况下并不是真的要查出那么多记录来。就像 junyi2003(超级菜鸟) 说的那样,对ResultSet进行优化/减肥。
【以上描述仅限于 MySQL & Connector/J,其它的数据库/驱动就不清楚了。】
haha,这个问题我遇到过。MySQL 的 Connector/J 缺省的实现方式是,不管你用不用,先把所有记录从服务器上传过来,全部保存在客户端的内存中!好家伙,那还不撑暴了!
要改变它的这种工作方式,就要
PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
这样查询出来的 ResultSet 就是“用一条才从服务器上抓一条过来”。
其实,更好的办法也许是修改查询语句(比如加上 LIMIT),不要让 ResultSet 里有那么多的记录,因为绝大多数情况下并不是真的要查出那么多记录来。就像 junyi2003(超级菜鸟) 说的那样,对ResultSet进行优化/减肥。
【以上描述仅限于 MySQL & Connector/J,其它的数据库/驱动就不清楚了。】
#40
抱歉,上面说的不全,应该是:
PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ps.setFetchSize(Integer.MIN_VALUE);
这样才能有效改变它的工作方式。
PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ps.setFetchSize(Integer.MIN_VALUE);
这样才能有效改变它的工作方式。
#41
100000条记录说大不大,说小也不小了!
应该避免这种操作
应该避免这种操作
#42
String str = "select max(oraID) as MaxID from oraTable";
...
str = "select * from oraTable where rownum<=1000 order by oraID";
...
List result = new ArrayList();
PurchaseOrderHdTran record;
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
while(CurID>=MaxID)
{
str = "select * from oraTable where oraID>=CurID and rownum<=1000 order by oraID";
...
result = new ArrayList();
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
}
...
str = "select * from oraTable where rownum<=1000 order by oraID";
...
List result = new ArrayList();
PurchaseOrderHdTran record;
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
while(CurID>=MaxID)
{
str = "select * from oraTable where oraID>=CurID and rownum<=1000 order by oraID";
...
result = new ArrayList();
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
}
#43
str = "select * from oraTable where oraID>CurID and rownum<=1000 order by oraID";
#44
ResultSet最多只能存4万左右的记录,解决只能是分批分段处理,用数据库本身技术写存储过程可以解决,另外不知道你们的项目是用什么框架和技术,HIBERNATE里有分段取值(试一下,有个最优值),用着还行,我导出16万条数据,花了10几分钟,哈哈
#45
upmark
#46
while(CurID<=MaxID)
{
str = "select * from oraTable where oraID>=CurID and rownum<=1000 order by oraID";
...
result = new ArrayList();
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
}
{
str = "select * from oraTable where oraID>=CurID and rownum<=1000 order by oraID";
...
result = new ArrayList();
while (resultSet.next()) {
record = new PurchaseOrderHdTran();
setPurchaseOrderHdInterfaceValue(resultSet, record);
result.add(record);
}
int CurID = resultSet.getInt("oraID");
}
#47
典型的java内存泄漏.
如果result始终这样,GC无法回收.
所以应当每批数据就将result置为null以断绝result里对象的引用,从而让GC回收.
如果result始终这样,GC无法回收.
所以应当每批数据就将result置为null以断绝result里对象的引用,从而让GC回收.
#48
mark
#49
/**
* 测试成批插入数据的事务处理,返回是否成功
*
* @param objPO Object
* @return boolean
*/
public boolean insertBatch(final Object objPO)
{
boolean isSuccess = false;
Transaction transaction = null;
try
{
transaction = session.beginTransaction();
for(int i = 0;i < 100000;i++)
{
session.save(objPO);
if(i % 20 == 0)
{
// flush a batch of inserts and release memory
session.flush();
session.clear();
}
}
transaction.commit();
logger.info("transaction.wasCommitted:" + transaction.wasCommitted());
isSuccess = true;
}
catch(HibernateException ex)
{
if(transaction != null)
{
try
{
transaction.rollback();
logger.error("transaction.wasRolledBack:" + transaction.wasRolledBack());
}
catch(HibernateException ex1)
{
logger.error(ex1.getMessage());
ex1.printStackTrace();
}
}
logger.error("Insert Batch PO Error:" + ex.getMessage());
ex.printStackTrace();
}
finally
{
if(transaction != null)
{
transaction = null;
}
}
return isSuccess;
}
/**
* 成批插入或更新数据,默认20条时就写入数据库,并释放内存出来,返回是否成功
*
* @param list List
* @return boolean
*/
public boolean saveOrUpdateBatch(final List list)
{
return saveOrUpdateBatch(list,20);
}
/**
* 成批插入或更新数据,设置每多少条时就写入数据库,并释放内存出来,返回是否成功
*
* @param list List
* @param iBatch int
* @return boolean
*/
public boolean saveOrUpdateBatch(final List list,final int iBatch)
{
boolean isSuccess = false;
Transaction transaction = null;
int iCount = 0;
try
{
transaction = session.beginTransaction();
session.clear();
for(final Iterator it = list.iterator();it.hasNext();)
{
logger.info("iCount:" + iCount);
session.saveOrUpdate(it.next()); // saveOrUpdate
iCount++;
logger.info("iCount:" + iCount);
if(iCount % iBatch == 0)
{
session.flush();
session.clear();
}
}
transaction.commit();
logger.info("transaction.wasCommitted:" + transaction.wasCommitted());
isSuccess = true;
}
catch(HibernateException ex)
{
if(transaction != null)
{
try
{
transaction.rollback();
logger.error("transaction.wasRolledBack:" + transaction.wasRolledBack());
}
catch(HibernateException ex1)
{
logger.error(ex1.getMessage());
ex1.printStackTrace();
}
}
logger.error("Save Or Update Batch PO Error:" + ex.getMessage());
ex.printStackTrace();
}
finally
{
if(transaction != null)
{
transaction = null;
}
}
return isSuccess;
}
* 测试成批插入数据的事务处理,返回是否成功
*
* @param objPO Object
* @return boolean
*/
public boolean insertBatch(final Object objPO)
{
boolean isSuccess = false;
Transaction transaction = null;
try
{
transaction = session.beginTransaction();
for(int i = 0;i < 100000;i++)
{
session.save(objPO);
if(i % 20 == 0)
{
// flush a batch of inserts and release memory
session.flush();
session.clear();
}
}
transaction.commit();
logger.info("transaction.wasCommitted:" + transaction.wasCommitted());
isSuccess = true;
}
catch(HibernateException ex)
{
if(transaction != null)
{
try
{
transaction.rollback();
logger.error("transaction.wasRolledBack:" + transaction.wasRolledBack());
}
catch(HibernateException ex1)
{
logger.error(ex1.getMessage());
ex1.printStackTrace();
}
}
logger.error("Insert Batch PO Error:" + ex.getMessage());
ex.printStackTrace();
}
finally
{
if(transaction != null)
{
transaction = null;
}
}
return isSuccess;
}
/**
* 成批插入或更新数据,默认20条时就写入数据库,并释放内存出来,返回是否成功
*
* @param list List
* @return boolean
*/
public boolean saveOrUpdateBatch(final List list)
{
return saveOrUpdateBatch(list,20);
}
/**
* 成批插入或更新数据,设置每多少条时就写入数据库,并释放内存出来,返回是否成功
*
* @param list List
* @param iBatch int
* @return boolean
*/
public boolean saveOrUpdateBatch(final List list,final int iBatch)
{
boolean isSuccess = false;
Transaction transaction = null;
int iCount = 0;
try
{
transaction = session.beginTransaction();
session.clear();
for(final Iterator it = list.iterator();it.hasNext();)
{
logger.info("iCount:" + iCount);
session.saveOrUpdate(it.next()); // saveOrUpdate
iCount++;
logger.info("iCount:" + iCount);
if(iCount % iBatch == 0)
{
session.flush();
session.clear();
}
}
transaction.commit();
logger.info("transaction.wasCommitted:" + transaction.wasCommitted());
isSuccess = true;
}
catch(HibernateException ex)
{
if(transaction != null)
{
try
{
transaction.rollback();
logger.error("transaction.wasRolledBack:" + transaction.wasRolledBack());
}
catch(HibernateException ex1)
{
logger.error(ex1.getMessage());
ex1.printStackTrace();
}
}
logger.error("Save Or Update Batch PO Error:" + ex.getMessage());
ex.printStackTrace();
}
finally
{
if(transaction != null)
{
transaction = null;
}
}
return isSuccess;
}
#50
ABC都是正确的;
但是对于大数据量是不合理的;
add应该有个度,只取本次需要看到的
但是对于大数据量是不合理的;
add应该有个度,只取本次需要看到的