与lucene亲密接触第二集,关于jdbc的一个疑惑

本文介绍如何利用Lucene和JDBC实现数据库内容的分批索引,解决了在内存限制条件下进行大规模数据索引的问题,并分享了解决Java内存溢出的经验。

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

继续咱们的lucene之旅,

今天结合jdbc把数据库中的内容建到倒排序索引文件去。使用jdbc的时候出现了一个疑惑,调了半天也没明白。

我有一个类 Db负责与数据库交互,在构造的时候建立数据库连接池,然后通过这个类的其他方法对数据库进行交互。

我有大概20万条表记录需要插到lucene的倒排序文件中,

然后思路很简单,我直接遍历数据库。

由于内存有限,我不可能直接读出整个数据库来索引,于是采取的分块进行。每次读出若干条,建索引,释放,然后读出下N条……

问题出现了,我发现不一会儿,java就内存溢出了!

仔细找了几遍代码,发现该释放的都释放了。。只是没有释放数据库连接池,于是我怀着很怀疑的态度,在每次处理一个块之后重建连接池,居然就没有溢出了!

按道理说数据库连接池不释放掉应该是不占查询内容的,只要将数据库查询的result释放就可以了,于是这个问题。。百思不得其解,先将代码贴上来,以后持续关注该问题。(这是每次释放,不会内存溢出的代码)

Db.class

import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import com.mysql.jdbc.*; //用于封装对数据库操作 public class Db { private Connection conn = null; private static String userName = "cg"; private static String password = "XXXXXX"; private static String databaseIP = "192.168.25.152"; private static String databaseName = "medias"; //数据库查询结果 //private ResultSet rset = null; PreparedStatement pstmt = null; ///初始化数据库链接 public Db() { this.Init(); } public void Init() { try{ String url = "jdbc:mysql://"+ databaseIP + "/" + databaseName; Class.forName ("com.mysql.jdbc.Driver").newInstance(); conn = DriverManager.getConnection (url, userName, password); System.out.println ("数据库初始化成功"); } catch( Exception e){ e.printStackTrace(); System.err.println(e.toString()); } } public ResultSet Begin( long start,long size ) { String exec = "select * from media limit " + String.valueOf(start) + "," + String.valueOf(size); ResultSet rset=null; try { pstmt = conn.prepareStatement(exec); rset=pstmt.executeQuery(); } catch( Exception e ){} return rset; } public Movie Next(ResultSet rset) throws SQLException{ Movie result = new Movie(); if( rset.next()) { result.title = rset.getString("title"); String id = rset.getString("media_id"); String exec = "select * from media_source where movie_id=" + id; try { PreparedStatement pstmt = conn.prepareStatement(exec); ResultSet rset2=pstmt.executeQuery(); //对media_source操作 while( rset2.next() ) { MovieTip tip = new MovieTip(); tip.url = rset2.getString("source_url"); result.AddTip(tip); } rset2.close(); } catch( Exception e ) { System.err.println(e.toString()); } return result; } else { pstmt.close(); result.isFinish = true; return result; } } //关闭数据库 public void Close() { if (conn != null) { try { conn.close (); System.out.println ("数据库关闭"); } catch (Exception e) { /* ignore close errors */ } } } }

调用相关代码

try { System.out.println("正在添加第"+start+"到"+(start+size)+"条记录"); indexWriter = new IndexWriter(indexDir, luceneAnalyzer, false, IndexWriter.MaxFieldLength.LIMITED); Db dbQueryer = new Db();//初始化数据库连接器 //dbQueryer.Init(); ResultSet rs=dbQueryer.Begin(start, size); while( true ) { Movie movie = dbQueryer.Next(rs); if( movie.isFinish == true ) break; else { Document document = new Document(); String urllist = ""; for(int i=0;i<movie.sources.size();i++) { MovieTip tip = (MovieTip)(movie.sources.get(i)); urllist += tip.url + "<br>"; } Field FieldTitle = new Field("title", movie.title, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); Field FieldUrl = new Field("url", urllist, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); //System.out.println(movie.title); document.add(FieldTitle); document.add(FieldUrl); indexWriter.addDocument(document); } } rs.close(); indexWriter.optimize(); indexWriter.close(); dbQueryer.Close(); System.out.println("添加成功");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值