Hibernate批处理问题

本文探讨了在使用Hibernate框架时如何高效地批量保存大量数据至数据库,避免内存溢出的问题。提出了两种解决方案:一是通过定期flush和clear缓存,二是利用StatelessSession接口直接与数据库交互。
问题的产生:假设一次性需要向数据库中保存一百万条数据1000000,则常规的保存方式为
Session session=null;
Transaction tx=null;
try{
session=this.getHibernateTemplate().getSessionFactory().openSession();
tx=session.beginTransaction();
for(int i=0;i<1000000;i++){
s.save(user);
}
tx.commit();
}finally{
if(session!=null)
session.close();
}
上面的保存方式,会出现问题,因为session在调用save方法的时候不会立即将数据保存到数据库,而是先缓存到session范围的一级缓存中,session关闭时,一级缓存也就消失,会将session中的对象清除,一级缓存需要占用内存,而session不能具体控制自己能够保存多少数据,换句话说,只要session不关闭,那么不管你往session里save多少对象session都不管,这就是说session在没关闭前可以拼命缓存对象,当然缓存对象是要消耗内存的,这样一来,当数据量很大的时候内存就会被消耗完,产生内存溢出,上面的代码就会出现这样的问题,当然也许你机子内存很大很大,运行上面代码没有内存溢出,那么你可以将保存数据的条数增加到千万或者十亿,相信你机子这时候会内存溢出,问题出现了,那么怎样来解决,可以有两种方法:
第一种:代码如下
Session session=null;
Transaction tx=null;
try{
session=this.getHibernateTemplate().getSessionFactory().openSession();
tx=session.beginTransaction();
for(int i=0;i<1000000;i++){
s.save(user);
if(i%50==0){
s.flush();
s.clear();
}
}
tx.commit();
}finally{
if(session!=null)
session.close();
}
相信你发现了这段代码与前面那段代码的不同之处,是多了 if(i%50==0){
s.flush();
s.clear();
}那么接下来就说说加这段代码的作用if(i%50==0)判断每次循环后session是否达到50个对象,这个设置可根据需要自己设定,设置的数字越小则与数据库的交互次数就越多,设置得越大,与数据库的交互次数越少,但是消耗的内存就更多,如果太大同样会内存溢出,因此设置一个合理的大小很重要,当session中达到了设置的对象个数后,调用s.flush();方法,该方法的作用是让session中的对象与数据库同步,也就是说让session数据与数据库中一致,会调用操作数据库的方法,简单地说会执行sql语句,在上例中就是会将50个对象批量插入到数据库来达到一致,数据库插入之后调用s.clear(); 方法,这个方法会清除掉session中的缓存对象,在上面来说就是会清除掉50个对象,将内存释放,因此上面的代码是每到50个对象的时候将数据插入到数据库并将session中的缓存对象清除,所以不会有内存溢出
第二种:
用StatelesssSession接口,它不和一级缓存,二级缓存交互,也不触发任何时间,监听器,拦截器,通过该接口会立刻发送到数据库
StatelessSession session = sessionFactory.openStatelessSession();
Transaction tx = session.beginTransaction();

ScrollableResults customers = session.getNamedQuery("GetCustomers")
.scroll(ScrollMode.FORWARD_ONLY);
while ( customers.next() ) {
Customer customer = (Customer) customers.get(0);
customer.updateStuff(...);
session.update(customer);
}

tx.commit();
session.close();
注意在上面的例子中,查询返回的Customer实例立即被脱管(detach)。它们与任何持久化上下文都没有关系。

StatelessSession 接口定义的insert(), update() 和 delete()操作是直接的数据库行级别操作,其结果是立刻执行一条INSERT, UPDATE 或 DELETE 语句。因此,它们的语义和Session 接口定义的save(), saveOrUpdate() 和delete() 操作有很大的不同。
源码地址: https://pan.quark.cn/s/3916362e5d0a 在C#编程平台下,构建一个曲线编辑器是一项融合了图形用户界面(GUI)构建、数据管理及数学运算的应用开发任务。 接下来将系统性地介绍这个曲线编辑器开发过程中的核心知识点:1. **定制曲线面板展示数据曲线**: - 控件选用:在C#的Windows Forms或WPF框架中,有多种控件可用于曲线呈现,例如PictureBox或用户自定义的UserControl。 通过处理重绘事件,借助Graphics对象执行绘图动作,如运用DrawCurve方法。 - 数据图形化:通过线性或贝塞尔曲线连接数据点,以呈现数据演变态势。 这要求掌握直线与曲线的数学描述,例如两点间的直线公式、三次贝塞尔曲线等。 - 坐标系统与缩放比例:构建X轴和Y轴,设定坐标标记,并开发缩放功能,使用户可察看不同区间内的数据。 2. **在时间轴上配置多个关键帧数据**: - 时间轴构建:开发一个时间轴组件,显示时间单位刻度,并允许用户在特定时间点设置关键帧。 时间可表现为连续形式或离散形式,关键帧对应于时间轴上的标识。 - 关键帧维护:利用数据结构(例如List或Dictionary)保存关键帧,涵盖时间戳和关联值。 需考虑关键帧的添加、移除及调整位置功能。 3. **调整关键帧数据,通过插值方法获得曲线**: - 插值方法:依据关键帧信息,选用插值方法(如线性插值、样条插值,特别是Catmull-Rom样条)生成平滑曲线。 这涉及数学运算,确保曲线在关键帧之间无缝衔接。 - 即时反馈:在编辑关键帧时,即时刷新曲线显示,优化用户体验。 4. **曲线数据的输出**: - 文件类型:挑选适宜的文件格式存储数据,例如XML、JSON或...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值