清明节放假期间,就一直在思考着Lucene增量索引问题,通过google我了解到了Zoie的存在,于是就开始2天的学习Zoie之旅,对Zoie的原理以及使用基本掌握,还特地使用Zoie实现了Lucene索引增量索引。不过Zoie已经好久没更新了,Zoie目前版本只支持到Lucene4.3.0,为此我花了2个多小时,修改了Zoie的源码将它升级使其支持Lucene5.0,我修改过的Zoie最新源码我已经上传到我的百度网盘,下载地址如下:
如果你使用Maven的话,那依赖的Zoie相关jar你需要手动install到你本地的仓库里,特此提醒。Zoie5.0相关jar包上面提供的3个下载地址中最后一个是我打包好的jar,你引入一个zoie-core即可。
先来说说Zoie的增量索引原理吧,摘自Zoie的官方Wiki:
利用两个内存索引一个硬盘索引实现实时搜索的原理
(1) 当系统启动的时候,索引处在Sleeping状态,这时Mem结构中,只有索引A,索引B为null,索引A为_currentWritable,_currentReadOnly为null,_diskIndexReader为硬盘索引的IndexReader。由于内存中索引的IndexReader是每添加完文档后立刻更新的,而且速度很快,而硬盘上的索引一旦打开,在下次合并之前,一直使用,可以保证新添加的文档能够马上被搜索到。
(2) 当A中的文档数量达到一定的数量的时候,需要同硬盘上的索引进行合并,因此要进入Working状态。合并是一个相对比较长的过程,这时候会创建内存索引B,在合并过程中新添加的文档全部索引到B中。此时的Mem结构中,有内存索引A,内存索引B,索引A为currentReadOnly,索引B为currentWritable,diskIndexReader为硬盘索引的IndexReader。此时要获得ZoieSystem的IndexReader,则三个IndexReader全都返回,由于索引B的IndexReader是添加文档后立刻更新的,因而能够保证新添加的文档能够马上被搜索到,这个时候虽然索引A已经在同硬盘索引进行合并,然而由于硬盘索引的IndexReader还没有重新打开,因而索引A中的数据不会被重复搜到。
(3) 当索引A中的数据已经完全合并到硬盘上之后,则要重新打开硬盘索引的IndexReader,打开完毕后,创建一个新的Mem结构,原来的索引B作为索引A,为currentWritable,原来的索引A被抛弃,设为null,currentReadOnly也设为null,diskIndexReader为新打开的硬盘索引的IndexReader。然后通过无缝切换用新的Mem结构替代旧的Mem结构,然后索引进入Sleeping状态。
上面的文字说的不够通俗易懂,我用更直白的话再解释一下:Zoie的增量索引原理是这样的,首先你可能会有一个定时器去不断检索是否有新增数据,发现了新数据,那首先会把新增的数据索引到内存目录A(RAMDirectory-A)中,当总不能一直让内存目录A中写索引啊,毕竟你占用的是内存,所以为内存目录A设定一个阀值,超过这个限定阀值就触发内存目录A中索引flush到硬盘索引目录C中,当内存目录A中索引还没有完全写入到硬盘索引目录C中且硬盘索引目录C的IndexReader还没有重新open的话,你通过IndexSearcher是查询不到的,这时就设计了一个内存索引目录B,即在内存索引目录A在往硬盘索引目录C中写索引的同时,也往内存索引目录B中写做个备份,这时使用Lucene中的MultiReader把B和C作为一个索引目录进行查询,之所以不包括A是因为A还没写完,前面博客我已经将过了Lucene的多目录搜索,你应该懂的,所以你新增数据之所以能几乎近实时的被你搜索到,是因为写入到了一个备份的索引目录B中,然后联合硬盘索引目录C(因为硬盘索引目录C在内存索引目录A里的索引合并到C过程还没完成之前,新增的索引在C中是搜索不到),当A和C的合并过程完成后,硬盘索引目录C的IndexReasder重新打开,保证新增的索引能被IndexSearcher搜索到,同时把B作为A,废弃A,再进入下一个循环.......
核心就是利用两个内存目录,一个内存目录用来联合硬盘索引目录进行多目录查询,另一个目录只管进行索引合并到硬盘索引目录操作即可。
放假花了2天使用Zoie写了一个增量索引的Demo,示例程序就是模拟数据库表数据动态插入新数据后,能立马被准实时被索引到,且被搜索到。下面就直接上代码了:
- package com.yida.framework.lucene5.incrementindex;
- import java.io.File;
- import java.util.ArrayList;
- import java.util.List;
- import org.ansj.lucene5.AnsjAnalyzer;
- import org.apache.lucene.analysis.Analyzer;
- import org.apache.lucene.search.similarities.DefaultSimilarity;
- import proj.zoie.api.DataConsumer.DataEvent;
- import proj.zoie.api.ZoieException;
- import proj.zoie.api.indexing.ZoieIndexableInterpreter;
- import proj.zoie.impl.indexing.DefaultIndexReaderDecorator;
- import proj.zoie.impl.indexing.ZoieConfig;
- import proj.zoie.impl.indexing.ZoieSystem;
- /**
- * Zoie增量索引测试
- * @author Lanxiaowei
- *
- */
- @SuppressWarnings({"unchecked","rawtypes"})
- public class ZoieIndex {
- /**最大增量索引数量*/
- public static final long MAX_INCREMENT_INDEX_NUMBER = Long.MAX_VALUE;
- /**索引目录*/
- public String userIndexPath;
- public ZoieSystem zoieSystem;
- /**队列中放入多少项才触发索引*/
- private int zoieBatchSize;
- /**等待多长时间才触发索引*/
- private int zoieBatchDelay;
- /**分词器*/
- private Analyzer analyzer;
- private PersonDao personDao;
- public ZoieIndex(String userIndexPath, Analyzer analyzer,
- PersonDao personDao) {
- super();
- this.userIndexPath = userIndexPath;
- this.analyzer = analyzer;
- this.personDao = personDao;
- }
- public ZoieIndex(String userIndexPath, Analyzer analyzer,
- PersonDao personDao, int zoieBatchSize, int zoieBatchDelay) {
- super();
- this.userIndexPath = userIndexPath;
- this.analyzer = analyzer;
- this.personDao = personDao;
- this.zoieBatchSize = zoieBatchSize;
- this.zoieBatchDelay = zoieBatchDelay;
- }
- public void init() throws ZoieException {
- //如果索引目录不存在则新建
- File idxDir = new File(userIndexPath);
- if(!idxDir.exists()){
- idxDir.mkdir();
- }
- //分词器设置为ansj-seg分词器
- analyzer = new AnsjAnalyzer();
- //数据转换器[JavaBea-->Document]
- ZoieIndexableInterpreter interpreter = new CustomPersonZoieIndexableInterpreter(analyzer);
- //Lucene的IndexReader装饰者,包装成zoie的IndexReader
- DefaultIndexReaderDecorator readerDecorator = new DefaultIndexReaderDecorator();
- //Zoie初始化相关配置
- ZoieConfig zoieConfig = new ZoieConfig();
- zoieConfig.setBatchDelay(zoieBatchDelay);
- zoieConfig.setBatchSize(zoieBatchSize);
- //设置分词器
- zoieConfig.setAnalyzer(analyzer);
- //设置相似性评分器
- zoieConfig.setSimilarity(new DefaultSimilarity());
- // 开启NRT索引
- zoieConfig.setRtIndexing(true);
- zoieSystem = new ZoieSystem(idxDir, interpreter, readerDecorator, zoieConfig);
- zoieSystem.start();
- zoieSystem.getAdminMBean().flushToDiskIndex();
- }
- /**
- * 更新索引数据
- * @throws ZoieException
- */
- public void updateIndexData() throws ZoieException {
- //先从数据库查出新增加的数据
- List<Person> persons = personDao.findPersonBefore3S();
- if(persons == null || persons.size() == 0) {
- System.out.println("No increment data right now.please wait a while.");
- return;
- }
- List<DataEvent<Person>> dataEventList = new ArrayList<DataEvent<Person>>();
- for(Person person : persons) {
- dataEventList.add(new DataEvent<Person>(person, "1.0", person.isDeleteFlag()));
- }
- //消费数据
- zoieSystem.consume(dataEventList);
- }
- public void destroy(){
- // 将内存索引刷新到磁盘索引中
- zoieSystem.shutdown();
- System.out.println(".........将内存索引刷新到磁盘索引中.........");
- }
- public String getUserIndexPath() {
- return userIndexPath;
- }
- public void setUserIndexPath(String userIndexPath) {
- this.userIndexPath = userIndexPath;
- }
- public int getZoieBatchSize() {
- return zoieBatchSize;
- }
- public void setZoieBatchSize(int zoieBatchSize) {
- this.zoieBatchSize = zoieBatchSize;
- }
- public int getZoieBatchDelay() {
- return zoieBatchDelay;
- }
- public void setZoieBatchDelay(int zoieBatchDelay) {
- this.zoieBatchDelay = zoieBatchDelay;
- }
- public Analyzer getAnalyzer() {
- return analyzer;
- }
- public void setAnalyzer(Analyzer analyzer) {
- this.analyzer = analyzer;
- }
- public PersonDao getPersonDao() {
- return personDao;
- }
- public void setPersonDao(PersonDao personDao) {
- this.personDao = personDao;
- }
- }
- package com.yida.framework.lucene5.incrementindex;
- import java.util.TimerTask;
- import proj.zoie.api.ZoieException;
- /**
- * Zoie定时增量索引任务
- * @author LANXIAOWEI
- *
- */
- public class ZoieIndexTimerTask extends TimerTask {
- private ZoieIndex zoieIndex;
- @Override
- public void run() {
- try {
- zoieIndex.init();
- zoieIndex.updateIndexData();
- } catch (ZoieException e) {
- e.printStackTrace();
- }
- }
- public ZoieIndexTimerTask(ZoieIndex zoieIndex) {
- super();
- this.zoieIndex = zoieIndex;
- }
- public ZoieIndex getZoieIndex() {
- return zoieIndex;
- }
- public void setZoieIndex(ZoieIndex zoieIndex) {
- this.zoieIndex = zoieIndex;
- }
- }
- package com.yida.framework.lucene5.incrementindex;
- import java.io.IOException;
- import java.nio.file.Paths;
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.lucene.document.Document;
- import org.apache.lucene.index.DirectoryReader;
- import org.apache.lucene.index.IndexReader;
- import org.apache.lucene.index.Term;
- import org.apache.lucene.search.IndexSearcher;
- import org.apache.lucene.search.Query;
- import org.apache.lucene.search.ScoreDoc;
- import org.apache.lucene.search.TermQuery;
- import org.apache.lucene.search.TopDocs;
- import org.apache.lucene.search.WildcardQuery;
- import org.apache.lucene.store.FSDirectory;
- /**
- * Zoie查询测试
- *
- * @author Lanxiaowei
- *
- */
- public class ZoieSearchTest {
- public static void main(String[] args) throws IOException {
- // 参数定义
- String directoryPath = "C:/zoieindex";
- String fieldName = "nativePlace";
- String queryString = "*香港*";
- Query query = new WildcardQuery(new Term(fieldName,queryString));
- List<Document> list = query(directoryPath,query);
- if (list == null || list.size() == 0) {
- System.out.println("No results found.");
- return;
- }
- for (Document doc : list) {
- String personName = doc.get("personName");
- String nativePlace = doc.get("nativePlace");
- String hobby = doc.get("hobby");
- System.out.println("personName:" + personName);
- System.out.println("nativePlace:" + nativePlace);
- System.out.println("hobby:" + hobby);
- }
- }
- /**
- * 创建索引阅读器
- * @param directoryPath 索引目录
- * @return
- * @throws IOException 可能会抛出IO异常
- */
- public static IndexReader createIndexReader(String directoryPath) throws IOException {
- return DirectoryReader.open(FSDirectory.open(Paths.get(directoryPath, new String[0])));
- }
- /**
- * 创建索引查询器
- * @param directoryPath 索引目录
- * @return
- * @throws IOException
- */
- public static IndexSearcher createIndexSearcher(String directoryPath) throws IOException {
- return new IndexSearcher(createIndexReader(directoryPath));
- }
- /**
- * 创建索引查询器
- * @param reader
- * @return
- */
- public static IndexSearcher createIndexSearcher(IndexReader reader) {
- return new IndexSearcher(reader);
- }
- public static List<Document> query(String directoryPath,Query query) throws IOException {
- IndexSearcher searcher = createIndexSearcher(directoryPath);
- TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);
- List<Document> docList = new ArrayList<Document>();
- ScoreDoc[] docs = topDocs.scoreDocs;
- for (ScoreDoc scoreDoc : docs) {
- int docID = scoreDoc.doc;
- Document document = searcher.doc(docID);
- docList.add(document);
- }
- searcher.getIndexReader().close();
- return docList;
- }
- }
- package com.yida.framework.lucene5.incrementindex;
- import java.util.Timer;
- import org.ansj.lucene5.AnsjAnalyzer;
- import org.apache.lucene.analysis.Analyzer;
- /**
- * 增量索引测试
- * @author Lanxiaowei
- *
- */
- public class ZoieTest {
- public static void main(String[] args) throws Exception {
- String userIndexPath = "C:/zoieindex";
- Analyzer analyzer = new AnsjAnalyzer();
- PersonDao personDao = new PersonDaoImpl();
- int zoieBatchSize = 10;
- int zoieBatchDelay = 1000;
- //先读取数据库表中已有数据创建索引
- CreateIndexTest createIndexTest = new CreateIndexTest(personDao, userIndexPath);
- createIndexTest.index();
- //再往数据库表中插入一条数据,模拟数据动态变化
- PersonDaoTest.addPerson();
- ZoieIndex zoindex = new ZoieIndex(userIndexPath, analyzer, personDao,
- zoieBatchSize, zoieBatchDelay);
- Timer timer = new Timer("myTimer",false);
- timer.scheduleAtFixedRate(new ZoieIndexTimerTask(zoindex),10L,3000L);
- //睡眠2分钟
- Thread.sleep(2*60*1000L);
- //2分钟后定时器取消
- timer.cancel();
- System.out.println("Timer cancled.");
- /**把索引flush到硬盘*/
- zoindex.destroy();
- System.out.println("finished.");
- }
- }
- package com.yida.framework.lucene5.incrementindex;
- import java.io.IOException;
- import java.nio.file.Paths;
- import java.util.List;
- import org.ansj.lucene5.AnsjAnalyzer;
- import org.apache.lucene.analysis.Analyzer;
- import org.apache.lucene.document.Document;
- import org.apache.lucene.document.Field;
- import org.apache.lucene.document.IntField;
- import org.apache.lucene.document.LongField;
- import org.apache.lucene.document.NumericDocValuesField;
- import org.apache.lucene.document.StringField;
- import org.apache.lucene.document.TextField;
- import org.apache.lucene.index.IndexWriter;
- import org.apache.lucene.index.IndexWriterConfig;
- import org.apache.lucene.index.IndexWriterConfig.OpenMode;
- import org.apache.lucene.store.Directory;
- import org.apache.lucene.store.FSDirectory;
- import com.yida.framework.lucene5.util.LuceneUtils;
- /**
- * 读取数据库表中数据创建索引
- * @author Lanxiaowei
- *
- */
- public class CreateIndexTest {
- private PersonDao personDao;
- /**索引目录*/
- private String indexDir;
- public static void main(String[] args) throws IOException {
- String userIndexPath = "C:/zoieindex";
- PersonDao personDao = new PersonDaoImpl();
- //先读取数据库表中已有数据创建索引
- CreateIndexTest createIndexTest = new CreateIndexTest(personDao, userIndexPath);
- createIndexTest.index();
- }
- public CreateIndexTest(PersonDao personDao, String indexDir) {
- super();
- this.personDao = personDao;
- this.indexDir = indexDir;
- }
- public void index() throws IOException {
- List<Person> persons = personDao.findAll();
- if(null == persons || persons.size() == 0) {
- return;
- }
- Directory dir = FSDirectory.open(Paths.get(indexDir));
- Analyzer analyzer = new AnsjAnalyzer();
- IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
- indexWriterConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);
- IndexWriter writer = new IndexWriter(dir, indexWriterConfig);
- for(Person person : persons) {
- Document document = new Document();
- document.add(new Field("id",person.getId().toString(),Field.Store.YES,
- Field.Index.NOT_ANALYZED,Field.TermVector.NO));
- document.add(new StringField("personName", person.getPersonName(), Field.Store.YES));
- document.add(new StringField("sex", person.getSex(), Field.Store.YES));
- document.add(new LongField("birth", person.getBirth().getTime(), Field.Store.YES));
- document.add(new TextField("nativePlace", person.getNativePlace(), Field.Store.YES));
- document.add(new StringField("job", person.getJob(), Field.Store.YES));
- document.add(new IntField("salary", person.getSalary(), Field.Store.YES));
- document.add(new StringField("hobby", person.getHobby(), Field.Store.YES));
- document.add(new StringField("deleteFlag", person.isDeleteFlag() + "", Field.Store.YES));
- //Zoie需要的UID[注意:这个域必须加,且必须是NumericDocValuesField类型,至于UID的域值是什么没关系,只要保证它是唯一的即可]
- document.add(new NumericDocValuesField("_ID", person.getId()));
- LuceneUtils.addIndex(writer, document);
- }
- writer.close();
- dir.close();
- }
- }
- package com.yida.framework.lucene5.incrementindex;
- import javax.sql.DataSource;
- import org.apache.commons.dbcp.BasicDataSource;
- import org.apache.commons.dbutils.QueryRunner;
- public class DBHelper {
- private static DataSource dataSource;
- public static QueryRunner getQueryRunner(){
- if(DBHelper.dataSource == null){
- BasicDataSource dbcpDataSource = new BasicDataSource();
- dbcpDataSource.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8");
- dbcpDataSource.setDriverClassName("com.mysql.jdbc.Driver");
- dbcpDataSource.setUsername("root");
- dbcpDataSource.setPassword("123");
- dbcpDataSource.setDefaultAutoCommit(true);
- dbcpDataSource.setMaxActive(100);
- dbcpDataSource.setMaxIdle(30);
- dbcpDataSource.setMaxWait(500);
- DBHelper.dataSource = (DataSource)dbcpDataSource;
- }
- return new QueryRunner(DBHelper.dataSource);
- }
- }
- package com.yida.framework.lucene5.incrementindex;
- import org.apache.lucene.analysis.Analyzer;
- import proj.zoie.api.indexing.AbstractZoieIndexableInterpreter;
- import proj.zoie.api.indexing.ZoieIndexable;
- /**
- * 自定义Person-->Document的数据转换器的生产者
- * @author Lanxiaowei
- *
- */
- public class CustomPersonZoieIndexableInterpreter extends AbstractZoieIndexableInterpreter<Person>{
- private Analyzer analyzer;
- @Override
- public ZoieIndexable convertAndInterpret(Person person) {
- return new PersonZoieIndexable(person, analyzer);
- }
- public CustomPersonZoieIndexableInterpreter() {}
- public CustomPersonZoieIndexableInterpreter(Analyzer analyzer) {
- super();
- this.analyzer = analyzer;
- }
- public Analyzer getAnalyzer() {
- return analyzer;
- }
- public void setAnalyzer(Analyzer analyzer) {
- this.analyzer = analyzer;
- }
- }
- package com.yida.framework.lucene5.incrementindex;
- import org.apache.lucene.analysis.Analyzer;
- import org.apache.lucene.document.Document;
- import org.apache.lucene.document.Field;
- import org.apache.lucene.document.IntField;
- import org.apache.lucene.document.LongField;
- import org.apache.lucene.document.StringField;
- import org.apache.lucene.document.TextField;
- import proj.zoie.api.indexing.AbstractZoieIndexable;
- /**
- * JavaBean与Document的转换器
- * @author Lanxiaowei
- *
- */
- public class PersonZoieIndexable extends AbstractZoieIndexable {
- private Person person;
- private Analyzer analyzer;
- public PersonZoieIndexable(Person person) {
- super();
- this.person = person;
- }
- public PersonZoieIndexable(Person person, Analyzer analyzer) {
- super();
- this.person = person;
- this.analyzer = analyzer;
- }
- public Document buildDocument() {
- System.out.println("Person --> Document begining.");
- Document document = new Document();
- document.add(new Field("id",person.getId().toString(),Field.Store.YES,
- Field.Index.NOT_ANALYZED,Field.TermVector.NO));
- document.add(new StringField("personName", person.getPersonName(), Field.Store.YES));
- document.add(new StringField("sex", person.getSex(), Field.Store.YES));
- document.add(new LongField("birth", person.getBirth().getTime(), Field.Store.YES));
- document.add(new TextField("nativePlace", person.getNativePlace(), Field.Store.YES));
- document.add(new StringField("job", person.getJob(), Field.Store.YES));
- document.add(new IntField("salary", person.getSalary(), Field.Store.YES));
- document.add(new StringField("hobby", person.getHobby(), Field.Store.YES));
- document.add(new StringField("deleteFlag", person.isDeleteFlag() + "", Field.Store.YES));
- return document;
- }
- @Override
- public IndexingReq[] buildIndexingReqs() {
- return new IndexingReq[] {new IndexingReq(buildDocument(), analyzer)};
- }
- @Override
- public long getUID() {
- return person.getId();
- }
- @Override
- public boolean isDeleted() {
- return person.isDeleteFlag();
- }
- public Analyzer getAnalyzer() {
- return analyzer;
- }
- public void setAnalyzer(Analyzer analyzer) {
- this.analyzer = analyzer;
- }
- }
- package com.yida.framework.lucene5.incrementindex;
- import java.util.Date;
- public class Person {
- private Long id;
- private String personName;
- /**性别:1(男)/0(女)*/
- private String sex;
- private Date birth;
- /**籍贯*/
- private String nativePlace;
- private String job;
- private Integer salary;
- /**兴趣爱好*/
- private String hobby;
- /**删除标记: true已删除/false未删除*/
- private boolean deleteFlag;
- /**最后一次更新时间*/
- private Date updatedTime;
- public Person() {}
- public Person(String personName, String sex, Date birth,
- String nativePlace, String job, Integer salary, String hobby) {
- super();
- this.personName = personName;
- this.sex = sex;
- this.birth = birth;
- this.nativePlace = nativePlace;
- this.job = job;
- this.salary = salary;
- this.hobby = hobby;
- }
- public Person(String personName, String sex, Date birth,
- String nativePlace, String job, Integer salary, String hobby,boolean deleteFlag) {
- super();
- this.personName = personName;
- this.sex = sex;
- this.birth = birth;
- this.nativePlace = nativePlace;
- this.job = job;
- this.salary = salary;
- this.hobby = hobby;
- this.deleteFlag = deleteFlag;
- }
- public Person(String personName, String sex, Date birth,
- String nativePlace, String job, Integer salary, String hobby,
- boolean deleteFlag, Date updatedTime) {
- super();
- this.personName = personName;
- this.sex = sex;
- this.birth = birth;
- this.nativePlace = nativePlace;
- this.job = job;
- this.salary = salary;
- this.hobby = hobby;
- this.deleteFlag = deleteFlag;
- this.updatedTime = updatedTime;
- }
- public Long getId() {
- return id;
- }
- public void setId(Long id) {
- this.id = id;
- }
- public String getPersonName() {
- return personName;
- }
- public void setPersonName(String personName) {
- this.personName = personName;
- }
- public String getSex() {
- return sex;
- }
- public void setSex(String sex) {
- this.sex = sex;
- }
- public Date getBirth() {
- return birth;
- }
- public void setBirth(Date birth) {
- this.birth = birth;
- }
- public String getNativePlace() {
- return nativePlace;
- }
- public void setNativePlace(String nativePlace) {
- this.nativePlace = nativePlace;
- }
- public String getJob() {
- return job;
- }
- public void setJob(String job) {
- this.job = job;
- }
- public Integer getSalary() {
- return salary;
- }
- public void setSalary(Integer salary) {
- this.salary = salary;
- }
- public String getHobby() {
- return hobby;
- }
- public void setHobby(String hobby) {
- this.hobby = hobby;
- }
- public boolean isDeleteFlag() {
- return deleteFlag;
- }
- public void setDeleteFlag(boolean deleteFlag) {
- this.deleteFlag = deleteFlag;
- }
- public Date getUpdatedTime() {
- return updatedTime;
- }
- public void setUpdatedTime(Date updatedTime) {
- this.updatedTime = updatedTime;
- }
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((id == null) ? 0 : id.hashCode());
- return result;
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Person other = (Person) obj;
- if (id == null) {
- if (other.id != null)
- return false;
- } else if (!id.equals(other.id))
- return false;
- return true;
- }
- }
- package com.yida.framework.lucene5.incrementindex;
- import java.util.List;
- public interface PersonDao {
- /**
- * 新增
- * @return
- */
- public boolean save(Person person);
- /**
- * 更新
- * @param person
- * @return
- */
- public boolean update(Person person);
- /**
- * 根据ID删除
- * @param id
- * @return
- */
- public boolean delete(Long id);
- /**
- * 根据ID查询
- * @param id
- * @return
- */
- public Person findById(Long id);
- /**
- * 查询所有
- * @return
- */
- public List<Person> findAll();
- /**
- * 查询3秒之前的数据,用于测试
- * @return
- */
- public List<Person> findPersonBefore3S();
- }
- package com.yida.framework.lucene5.incrementindex;
- import java.sql.SQLException;
- import java.util.Date;
- import java.util.List;
- import org.apache.commons.dbutils.QueryRunner;
- import org.apache.commons.dbutils.handlers.BeanHandler;
- import org.apache.commons.dbutils.handlers.BeanListHandler;
- public class PersonDaoImpl implements PersonDao {
- private QueryRunner queryRunner = DBHelper.getQueryRunner();
- /**
- * 新增
- * @return
- */
- public boolean save(Person person) {
- int result = 0;
- try {
- result = queryRunner.update("insert into person(personName,sex,birth,nativePlace,job,salary,hobby,deleteFlag,updatedTime) " +
- "values(?,?,?,?,?,?,?,?,?)" , new Object[] {
- person.getPersonName(),
- person.getSex(),
- person.getBirth(),
- person.getNativePlace(),
- person.getJob(),
- person.getSalary(),
- person.getHobby(),
- person.isDeleteFlag(),
- new Date()
- });
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return result == 1;
- }
- /**
- * 根据ID更新
- * @param person
- * @return
- */
- public boolean update(Person person) {
- int result = 0;
- try {
- result = queryRunner.update(
- "update person set personName = ?, sex = ?, birth = ?, " +
- "nativePlace = ?, job = ?, salary = ?, hobby = ?,deleteFlag = ?, " +
- "updatedTime = ? where id = ?"
- , new Object[] {
- person.getPersonName(),
- person.getSex(),
- person.getBirth(),
- person.getNativePlace(),
- person.getJob(),
- person.getSalary(),
- person.getHobby(),
- person.isDeleteFlag(),
- new Date(),
- person.getId()
- });
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return result == 1;
- }
- /**
- * 根据ID删除
- * @param id
- * @return
- */
- public boolean delete(Long id) {
- int result = 0;
- try {
- result = queryRunner.update("delete from person where id = ?", id);
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return result == 1;
- }
- /**
- * 根据ID查询
- * @param id
- * @return
- */
- public Person findById(Long id) {
- Person person = null;
- try {
- person = queryRunner.query("select * from person where id = ?", new BeanHandler<Person>(Person.class),id);
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return person;
- }
- /**
- * 查询所有
- * @return
- */
- public List<Person> findAll() {
- List<Person> persons = null;
- try {
- persons = queryRunner.query("select * from person", new BeanListHandler<Person>(Person.class));
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return persons;
- }
- /**
- * 查询3秒之前的数据,用于测试
- * @return
- */
- public List<Person> findPersonBefore3S() {
- List<Person> persons = null;
- try {
- persons = queryRunner.query("select * from person where updatedTime >= DATE_SUB(NOW(),INTERVAL 3 SECOND)", new BeanListHandler<Person>(Person.class));
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return persons;
- }
- }
- package com.yida.framework.lucene5.incrementindex;
- import java.text.DateFormat;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- /**
- * PersonDao测试
- * @author Lanxiaowei
- *
- */
- public class PersonDaoTest {
- private static final DateFormat dateFormate = new SimpleDateFormat("yyyy-MM-dd");
- public static void main(String[] args) throws Exception {
- addPerson();
- }
- /**
- * 添加一个Person测试
- * @throws ParseException
- */
- public static void addPerson() throws ParseException {
- PersonDao personDao = new PersonDaoImpl();
- String personName = "张国荣";
- String sex = "1";
- String birthString = "1956-09-12";
- Date birth = dateFormate.parse(birthString);
- String nativePlace = "中国香港九龙";
- String job = "歌手";
- Integer salary = 16000;
- String hobby = "演员&音乐";
- boolean deleteFlag = false;
- Person person = new Person(personName, sex, birth, nativePlace, job, salary, hobby, deleteFlag);
- boolean success = personDao.save(person);
- System.out.println(success ? "Person save successful." : "Person save fauilure.");
- }
- }
数据库建表SQL:
- CREATE TABLE `person` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT,
- `personName` varchar(60) DEFAULT NULL,
- `sex` char(1) DEFAULT NULL,
- `birth` datetime DEFAULT NULL,
- `nativePlace` varchar(200) DEFAULT NULL,
- `job` varchar(60) DEFAULT NULL,
- `salary` int(11) DEFAULT NULL,
- `hobby` varchar(200) DEFAULT NULL,
- `deleteFlag` bit(1) DEFAULT NULL,
- `updatedTime` datetime DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
- INSERT INTO `person` VALUES (1, '兰小伟', '1', '1987-6-5 00:00:00', '湖北省武穴市', '码农', 16000, '看书写代码听歌看电影玩玩CS看看斯诺克比赛', '', '2015-4-6 18:01:30');
- INSERT INTO `person` VALUES (2, '李小龙', '1', '1940-2-26 00:00:00', '中国广东顺德均安镇', '武术大师', 16000, '武术&音乐', '', '2015-4-6 18:14:04');
建表SQL文件和demo源码我会在底下的附件里上传,自己去下载。SQL文件怎么导入到MySQL我就不多说了哈,如果这个你不会,请自己Google。运行ZoieTest类进行测试,在运行之前,请先打开DBHelper工具类,修改里面的MySQL数据库的帐号密码,因为你的MySQL登录帐号密码可能跟我的不一样,还有记得把Zoie-core的jar包install到本地仓库,否则你maven的pom.xml会报错。运行ZoieTest测试类之后,你就可以不断运行ZoieSearchTest测试来查询数据,来查看新增的数据是否已经被索引且能被搜索到。
如果你还有什么问题请加我Q-Q:7-3-6-0-3-1-3-0-5,
或者加裙
一起交流学习!
转载:http://iamyida.iteye.com/blog/2199848