Hibernate Search大数据量手动建立索引

本文介绍了一种使用HibernateSearch进行批量数据索引的方法,通过分页和适时提交来避免出现内存溢出错误。文中提供了一个具体的代码示例,并分析了导致内存溢出的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

刚刚看了Hibernate Search,想要写个程序试着使用JPA建立一个索引,由于数据量比较大,所以是用分页来取得数据,但是老是报outOfMemory错误,最后解决了,所以把关键的代码贴出来和大家分享:

 

Java代码  收藏代码
  1. public void index(){  
  2.         EntityManager em = EntityManagerHolder.getEntityManager();  
  3.         //wrap a EntityManager object  
  4.           
  5.         Query query = em.createQuery(" from A").setMaxResults(1000);  
  6.         for(int i=0, j=0; i < 1000; i++, j+=1000){  
  7.             FullTextEntityManager ftem =   
  8.                         org.hibernate.search.jpa.Search.getFullTextEntityManager(em);  
  9.               
  10.             ftem.getTransaction().begin();  
  11.               
  12.               
  13.             @SuppressWarnings("unchecked")  
  14.             List<Item> items = query.setFirstResult(j).getResultList();  
  15.               
  16.             for (Item item : items) {  
  17.                 ftem.index(item);  //manually index an item instance  
  18.             }  
  19.             ftem.flush();  
  20.             //ftem.clear();  
  21.               
  22.             /*必须每次都commit一次,否则会内存溢出*/  
  23.             ftem.getTransaction().commit(); //index are written at commit time  
  24.               
  25.             /* 1. EntityManager.clear()必须在ftem.index之后调用, 
  26.              * 否则ftem无法再context中找不到相应的对象。 
  27.              *  
  28.              * 2. 因为EntityManager中有个Context用于缓存事务中query到 
  29.              * 以及update,insert到数据库的对象,这样可以减少数据库的读写 
  30.              * 次数,所以web应用的时候每个请求的线程一个EntityManager 
  31.              * 对象。如果要用同一个EntityManager分页获得大数据量的数据, 
  32.              * 就必须定期clear 一次。否则缓存写满了就会报outOfMemery错误。 
  33.              * */  
  34.             em.clear();  
  35.         }  
  36.     }  

 EntityManagerHolder:

Java代码  收藏代码
  1. public class EntityManagerHolder {  
  2.     private static ThreadLocal<EntityManager> entityManagerHolder =   
  3.                                         new ThreadLocal<EntityManager>();  
  4.       
  5.     public static EntityManager getEntityManager() {  
  6.         return entityManagerHolder.get();  
  7.     }  
  8.       
  9.     public static void setEntityManager(EntityManager session) {  
  10.         entityManagerHolder.set(session);  
  11.     }  
  12. }  

 初始化EntityManagerHolder:

Java代码  收藏代码
  1. public class TestCase {  
  2.   
  3.     protected EntityManagerFactory factory;  
  4.       
  5.     @Before  
  6.     public void setUp() throws Exception {  
  7.         factory = Persistence.createEntityManagerFactory("test");  
  8.         EntityManagerHolder.setEntityManager(factory.createEntityManager());  
  9.     }  
  10.   
  11.     @After  
  12.     public void tearDown() throws Exception {  
  13.         EntityManagerHolder.getEntityManager().close();  
  14.         EntityManagerHolder.setEntityManager(null);  
  15.         factory.close();  
  16.     }  
  17.   
  18. }  
 

下面是我之前碰到的outOfMemory错误的详细信息:

Java代码  收藏代码
  1. java.lang.OutOfMemoryError: Java heap space  
  2.     at org.hibernate.util.IdentityMap.entryArray(IdentityMap.java:224)  
  3.     at org.hibernate.util.IdentityMap.concurrentEntries(IdentityMap.java:89)  
  4.     at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:136)  
  5.     at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)  
  6.     at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:49)  
  7.     at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)  
  8.     at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)  
  9.     at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)  
  10.     at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)  
  11.     at com.chaizj.search.proptotype.ManuallyIndex.index(ManuallyIndex.java:26)  
  12.     at com.chaizj.search.proptotype.test.MannuallyIndexTest.postSetUp(MannuallyIndexTest.java:12)  
  13.     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
  14.     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)  
  15.     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)  
  16.     at java.lang.reflect.Method.invoke(Method.java:585)  
  17.     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)  
  18.     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)  
  19.     at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)  
  20.     at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)  
  21.     at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)  
  22.     at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)  
  23.     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)  
  24.     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)  
  25.     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)  
  26.     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)  
  27.     at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)  
  28.     at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)  
  29.     at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)  
  30.     at org.junit.runners.ParentRunner.run(ParentRunner.java:220)  
  31.     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)  
  32.     at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)  
  33.     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)  
  34.       
  35. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>      
  36. java.lang.OutOfMemoryError: Java heap space  
  37.     at java.util.HashMap.addEntry(HashMap.java:797)  
  38.     at java.util.HashMap.put(HashMap.java:431)  
  39.     at org.hibernate.engine.StatefulPersistenceContext.addEntity(StatefulPersistenceContext.java:336)  
  40.     at org.hibernate.engine.StatefulPersistenceContext.addEntity(StatefulPersistenceContext.java:431)  
  41.     at org.hibernate.engine.TwoPhaseLoad.addUninitializedEntity(TwoPhaseLoad.java:260)  
  42.     at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1390)  
  43.     at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1332)  
  44.     at org.hibernate.loader.Loader.getRow(Loader.java:1230)  
  45.     at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:603)  
  46.     at org.hibernate.loader.Loader.doQuery(Loader.java:724)  
  47.     at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)  
  48.     at org.hibernate.loader.Loader.doList(Loader.java:2228)  
  49.     at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)  
  50.     at org.hibernate.loader.Loader.list(Loader.java:2120)  
  51.     at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401)  
  52.     at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:361)  
  53.     at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)  
  54.     at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1148)  
  55.     at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)  
  56.     at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:67)  
  57.     at com.chaizj.search.proptotype.ManuallyIndex.index(ManuallyIndex.java:21)  
  58.     at com.chaizj.search.proptotype.test.MannuallyIndexTest.postSetUp(MannuallyIndexTest.java:12)  
  59.     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
  60.     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)  
  61.     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)  
  62.     at java.lang.reflect.Method.invoke(Method.java:585)  
  63.     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)  
  64.     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)  
  65.     at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)  
  66.     at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)  
  67.     at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)  
  68.     at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值