继续咱们的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("添加成功");