使用Hibernate和Spring批量插入

我的应用程序基于Hibernate 3.2和Spring 2.5。 以下是应用程序上下文中与事务管理相关的代码段:

            

对于所有DAO,都有相关的Service类,并且在服务层中的每个方法上使用@Transactional处理事务。 但是现在有一种情况,即DAO中的方法说服务层调用“parse()”。 在服务层我指定了@Transactional(readOnly=false) 。 DAO中的这个解析方法在同一个DAO中调用另一个方法“save()”,它在数据库中存储了大量的行(大约5000个)。 现在,在解析函数的循环中调用save方法。 现在的问题是,在大约100次调用“保存”方法之后..我有时会得到OutOfMemoryexception或有时程序停止响应。

现在这些是我对save方法所做的更改:

 Session session = getHibernateTemplate().getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); int counter = 0; if(books!=null && !books.isEmpty()){ for (Iterator iterator = books.iterator(); iterator .hasNext();) { Book book = (Book) iterator.next(); session.save(book); counter++; if(counter % 20==0) { session.flush(); session.clear(); } } } tx.commit(); session.close(); 

这是我的应用程序中唯一的方法,我开始这样的事务并在方法结束时提交它。 否则我通常只调用getHibernateTemplate.save() 。 我不确定是否应该在DAO中单独执行此保存方法的事务管理,方法是在save()上放置@Transactional(readOnly=false, PROPOGATION=NEW) save() ,或者这种方法是否正常?

我还在hibernate.cfg配置文件中将hibernate.jdbc.batch_size更新为20。

有什么建议么?

对于使用hibernate进行批量插入,最好的做法是StatelessSession,它不会缓存你实体的任何状态,你不会遇到OutOfMemory,代码如下:

 if (books == null || books.isEmpty) { return; } StatelessSession session = getHibernateTemplate().getSessionFactory().openStatelessSession(); Transaction tx = session.beginTransaction(); for (Book each : books) { session.insert(book); } tx.commit(); session.close(); 

StatelessSession的Transaction与当前的事务上下文无关。

您只需要刷新并清除会话。 将事务管理留给Spring。 使用sessionFactory.getCurrentSession()来访问Spring已经为您打开的会话。 此外,Spring最近的建议是避免使用HibernateTemplate并直接使用Hibernate的API。 将SessionFactory注入你的dao-bean。

我会以不直接调用save的方式重构parse ,但从服务层获取一些回调。 服务层将使用save调用作为此回调传递其事务方法。

它可能无法完全按照您的情况描述,但从这个简短的描述,这将是我尝试的东西。