关于mybatis的问题,大神帮帮忙!?

xingshen100 2014-03-27 12:18:07
@Test
public void batchInsert(){
SqlSession session=sqlSessionFactory.openSession();
Map<String, Object> map = new HashMap<String, Object>();
List<Person> pList = new ArrayList<Person>();
try {
for(int i=1;i<1000007;i++){
Person person=new Person();
person.setName("batName"+i);
pList.add(person);
System.out.println("object num:"+i);
if(i%1000==0){
map.put("personList",pList);
session.insert("cn.itcast.mapper.Person.insertBatch",map);
pList.clear();//清空集合中数据
}
}
map.put("personList",pList);//map中key值相同覆盖前面的,插入i>1000之后的
session.insert("cn.itcast.mapper.Person.insertBatch",map);

session.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
session.close();
}

}




上面这个图是我对内存结构的理解,下面是问题
适当的时候把集合中的数据清空,防止heap溢出,但是这session.insert()产生的数据具体跑哪里去了?在事务未提交之前,所有的sql语句数据应该都在session中,对吧?
Session对象和集合对象都在堆空间中,到头来集合中的数据还是在堆空间中,这样就和之前把数据全部存放到堆空间一样,但是这样为何就不会导致heap溢出呢?
...全文
173 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
xingshen100 2014-03-29
  • 打赏
  • 举报
回复
引用 1 楼 kky2010_110 的回复:
jvm的原理 年老代堆空间被占满(年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。) 异常: java.lang.OutOfMemoryError: Java heap space 持久代被占满 异常:java.lang.OutOfMemoryError: PermGen space 主要原因就是大量动态反射生成的类不断被加载,最终导致Perm区被占满。 堆栈溢出 异常:java.lang.StackOverflowError 说明:这个就不多说了,一般就是递归没返回,或者循环调用造成 线程堆栈满 异常:Fatal: Stack size too small 系统内存被占满 异常:java.lang.OutOfMemoryError: unable to create new native thread 这里看不到你的图,大胆推测一下,能提出这个问题的人肯定是对java的堆栈是有了解的并且是对的。所以我猜测session中的insert其实已经把数据放到事务中了,也就是已经交给数据库了,而commit只是让数据库执行一下而已。这个时候已经不再占用java内存了,所以不会报错。 我没看过mybatis源码,不过我依据hibernate冒昧猜测的。
多数人都说是在session.insert()批量插入大量数据的时候,已将数据写入数据库,推测来看,这样比较合理。但是怎么验证呢?我没找到办法。
xingshen100 2014-03-29
  • 打赏
  • 举报
回复
引用 4 楼 forgetsam 的回复:
别把你对Java内存的理解套到数据库上,除非你那数据库是Java自己的内存数据库。 在事务未提交之前,所有的sql语句数据应该都在session中,对吧? 扯淡。未提交之前数据已经写入了数据库的数据文件中,提交这个动作只不过是做个标记,标记这些块是“真正的数据块”,回滚这个动作只不过是告诉数据库这些块是“可以写入数据的空白块”
我猜想也是不会总在jvm内存空间中的,否则我的实验中早该溢出。那你知道未提交事务之前,这些数据具体跑到数据库哪里了吗?你说已经写到数据文件中,具体是值哪文件?我在进行大量的批量session.insert()过程中,检测过mysql中的与被插入数据的表同名的frm文件,发现大小并不发生变化。你说事务未提交之前就已经将数据写入数据库了,那么如果后续发生错误,事务如何回滚的,是将数据库状态恢复到之前的状态吗?如果真是这样,那么来回这么一折腾,数据库的效率岂不是太低了。如果你有耐心就讲细点,或者告诉到什么地方看针对性的资料也可,谢谢。
forgetsam 2014-03-28
  • 打赏
  • 举报
回复
别把你对Java内存的理解套到数据库上,除非你那数据库是Java自己的内存数据库。 在事务未提交之前,所有的sql语句数据应该都在session中,对吧? 扯淡。未提交之前数据已经写入了数据库的数据文件中,提交这个动作只不过是做个标记,标记这些块是“真正的数据块”,回滚这个动作只不过是告诉数据库这些块是“可以写入数据的空白块”
kky2010_110 2014-03-28
  • 打赏
  • 举报
回复
try {
for(int i=1;i<1000007;i++){
Person person=new Person();
person.setName("batName"+i);
pList.add(person);
}

改成:
try {
Person person=null;
for(int i=1;i<1000007;i++){
person=new Person();
person.setName("batName"+i);
pList.add(person);
}
哈哈,最近在研究java基础,确实收获不小啊与楼主共勉吧
kky2010_110 2014-03-28
  • 打赏
  • 举报
回复
应该说依据现象猜测,因为我也没有看过hibernate源码,没有用过mybatis,也是通过现象猜测
kky2010_110 2014-03-28
  • 打赏
  • 举报
回复
jvm的原理 年老代堆空间被占满(年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。) 异常: java.lang.OutOfMemoryError: Java heap space 持久代被占满 异常:java.lang.OutOfMemoryError: PermGen space 主要原因就是大量动态反射生成的类不断被加载,最终导致Perm区被占满。 堆栈溢出 异常:java.lang.StackOverflowError 说明:这个就不多说了,一般就是递归没返回,或者循环调用造成 线程堆栈满 异常:Fatal: Stack size too small 系统内存被占满 异常:java.lang.OutOfMemoryError: unable to create new native thread 这里看不到你的图,大胆推测一下,能提出这个问题的人肯定是对java的堆栈是有了解的并且是对的。所以我猜测session中的insert其实已经把数据放到事务中了,也就是已经交给数据库了,而commit只是让数据库执行一下而已。这个时候已经不再占用java内存了,所以不会报错。 我没看过mybatis源码,不过我依据hibernate冒昧猜测的。

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧