- 浏览: 213140 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
wuMing2014:
楼主,在ExtendServlet类中的Ioc ioc = n ...
freemarker 自定义标签 -
washingtonDC:
非常精彩!运行时异常(即非受控异常)自动强制执行整个逻辑工作单 ...
Spring事务的传播行为 @Transactional -
tom31203120:
freemarker 自定义标签 -
osacar:
tom31203120 写道oscar 不是 osacar还真 ...
freemarker 自定义标签 -
tom31203120:
oscar 不是 osacar
freemarker 自定义标签
前段时间已经写了一篇关于compass的文章,相信大家对compass也已经有了一定的了解
由于最近做的项目中涉及到了站内搜索,而且是基于JPA注解形式的,在网上找了好久,关于JPA集成compass的例子很少,有些也是基于 xml的,基于注解形式的甚是少,没有办法只有去compass的官网下载英文文档自己研究一下,花费了一下午时间调试出来,集成到项目中!
在这里给大家分享下,希望大家可以少走些弯路!
1.去官方网站下载compass的jar包,我用的的2.1版本
http://www.compass-project.org/
ProductInfo.java
ProductType.java
ProductStyle.java
这里要特别注意有集合类型要搜索或显示的时候,两边定义的@SearchableReference或 @SearchableComponent必须一致
2.再spring的配置文件中加入以下代码
3.自动建立索引的java bean
4.建立索引Service 层代码
控制层
junit测试
由于最近做的项目中涉及到了站内搜索,而且是基于JPA注解形式的,在网上找了好久,关于JPA集成compass的例子很少,有些也是基于 xml的,基于注解形式的甚是少,没有办法只有去compass的官网下载英文文档自己研究一下,花费了一下午时间调试出来,集成到项目中!
在这里给大家分享下,希望大家可以少走些弯路!
1.去官方网站下载compass的jar包,我用的的2.1版本
http://www.compass-project.org/
ProductInfo.java
@Entity @Searchable public class ProductInfo implements Serializable{ private static final long serialVersionUID = -8860864584425256200L; private Integer id; /** 货号 **/ private String code; /** 产品名称 **/ private String name; /** 产品类型 **/ private ProductType type; /** 产品样式 **/ private Set<ProductStyle> styles = new HashSet<ProductStyle>(); public ProductInfo() {} @OneToMany(cascade={CascadeType.REMOVE,CascadeType.PERSIST}, mappedBy="product",fetch=FetchType.EAGER) @OrderBy("visible desc, id asc") @SearchableReference public Set<ProductStyle> getStyles() { return styles; } public void setStyles(Set<ProductStyle> styles) { this.styles = styles; } @Id @GeneratedValue @SearchableId public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=30) @SearchableProperty(index = Index.TOKENIZED, store = Store.YES) public String getCode() { return code; } public void setCode(String code) { this.code = code; } @Column(length=50,nullable=false) @SearchableProperty(index = Index.TOKENIZED, store = Store.YES) public String getName() { return name; } public void setName(String name) { this.name = name; } @ManyToOne(cascade=CascadeType.REFRESH,optional=false) @JoinColumn(name="typeid") @SearchableReference public ProductType getType() { return type; } public void setType(ProductType type) { this.type = type; } @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; final ProductInfo other = (ProductInfo) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } }
ProductType.java
@Entity @Searchable public class ProductType implements Serializable{ private static final long serialVersionUID = 8106351120886053881L; /** 类别id **/ private Integer typeid; /** 类别名称 **/ private String name; /** 子类别 **/ private Set<ProductType> childtypes = new HashSet<ProductType>(); /** 所属父类 **/ private ProductType parent; private Set<ProductInfo> products = new HashSet<ProductInfo>(); @OneToMany(mappedBy="type", cascade=CascadeType.REMOVE) @SearchableReference public Set<ProductInfo> getProducts() { return products; } public void setProducts(Set<ProductInfo> products) { this.products = products; } public ProductType() {} @ManyToOne(cascade=CascadeType.REFRESH) @JoinColumn(name="parentid") public ProductType getParent() { return parent; } public void setParent(ProductType parent) { this.parent = parent; } @OneToMany(cascade={CascadeType.REFRESH,CascadeType.REMOVE},mappedBy="parent") public Set<ProductType> getChildtypes() { return childtypes; } public void setChildtypes(Set<ProductType> childtypes) { this.childtypes = childtypes; } @Column(length=36,nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } @Id @GeneratedValue(strategy=GenerationType.AUTO) @SearchableId public Integer getTypeid() { return typeid; } public void setTypeid(Integer typeid) { this.typeid = typeid; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((typeid == null) ? 0 : typeid.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; final ProductType other = (ProductType) obj; if (typeid == null) { if (other.typeid != null) return false; } else if (!typeid.equals(other.typeid)) return false; return true; } }
ProductStyle.java
@Entity @Searchable public class ProductStyle implements Serializable{ private static final long serialVersionUID = -4926119953511144279L; private Integer id; /** 样式的名称 **/ private String name; /** 图片 **/ private String imagename; private String image140FullPath; /** 是否可见 **/ private Boolean visible = true; private ProductInfo product; public ProductStyle() {} public ProductStyle(Integer id) { this.id = id; } public ProductStyle(String name, String imagename) { this.name = name; this.imagename = imagename; } @ManyToOne(cascade=CascadeType.REFRESH,optional=false) @JoinColumn(name="productid") @SearchableReference public ProductInfo getProduct() { return product; } public void setProduct(ProductInfo product) { this.product = product; } @Id @GeneratedValue @SearchableId public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=30,nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(length=40,nullable=false) @SearchableProperty(index = Index.UN_TOKENIZED, store = Store.YES) public String getImagename() { return imagename; } public void setImagename(String imagename) { this.imagename = imagename; } @Column(nullable=false) public Boolean getVisible() { return visible; } public void setVisible(Boolean visible) { this.visible = visible; } @Transient public String getImageFullPath(){ return "/images/product/"+ this.getProduct().getType().getTypeid()+ "/"+ this.getProduct().getId()+ "/prototype/"+ this.imagename; } @Transient public String getImage140FullPath(){ image140FullPath = "/images/product/"+ this.getProduct().getType().getTypeid()+ "/"+ this.getProduct().getId()+ "/140x/"+ this.imagename; return image140FullPath; } @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; final ProductStyle other = (ProductStyle) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } }
这里要特别注意有集合类型要搜索或显示的时候,两边定义的@SearchableReference或 @SearchableComponent必须一致
2.再spring的配置文件中加入以下代码
<bean id="annotationConfiguration" class="org.compass.annotations.config.CompassAnnotationsConfiguration"> </bean> <!-- compass Bean --> <bean id="compass" class="org.compass.spring.LocalCompassBean"> <property name="compassConfiguration" ref="annotationConfiguration" /> <property name="transactionManager" ref="txManager" /> <property name="compassSettings"> <props> <!-- 定义索引的存储位置 --> <prop key="compass.engine.connection">d:/compass</prop> <prop key="compass.transaction.factory"> org.compass.spring.transaction.SpringSyncTransactionFactory </prop> <!-- 定义分词器--> <prop key="compass.engine.analyzer.MMAnalyzer.CustomAnalyzer"> org.mira.lucene.analysis.IK_CAnalyzer </prop> </props> </property> <property name="resourceDirectoryLocations"> <list> <value>classpath:net/shopin/bean/product</value> </list> </property> </bean> <bean id="jpaGpsDevice" class="org.compass.gps.device.jpa.JpaGpsDevice"> <property name="name"> <value>JpaGpsDevice</value> </property> <property name="entityManagerFactory" ref="entityManagerFactory" /> <property name="mirrorDataChanges"> <value>true</value> </property> </bean> <!-- 数据库中的数据变化后同步更新索引 --> <bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps" init-method="start" destroy-method="stop"> <property name="compass" ref="compass" /> <property name="gpsDevices"> <list> <bean class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper"> <property name="gpsDevice" ref="jpaGpsDevice" /> </bean> </list> </property> </bean> <bean id="compassTemplate" class="org.compass.core.CompassTemplate"> <property name="compass" ref="compass" /> </bean> <!-- 定时重建索引(利用quartz)或随Spring ApplicationContext启动而重建索引 --> <bean id="compassIndexBuilder" class="net.shopin.service.search.impl.CompassIndexBuilder" lazy-init="false"> <property name="compassGps" ref="compassGps" /> <property name="buildIndex" value="true" /> <property name="lazyTime" value="5" /> </bean>
3.自动建立索引的java bean
/** * 通过quartz定时调度定时重建索引或自动随Spring ApplicationContext启动而重建索引的Builder. * 会启动后延时数秒新开线程调用compassGps.index()函数. * 默认会在Web应用每次启动时重建索引,可以设置buildIndex属性为false来禁止此功能. * 也可以不用本Builder, 编写手动调用compassGps.index()的代码. * */ public class CompassIndexBuilder implements InitializingBean { // 是否需要建立索引,可被设置为false使本Builder失效. private boolean buildIndex = false; // 索引操作线程延时启动的时间,单位为秒 private int lazyTime = 10; // Compass封装 private CompassGps compassGps; // 索引线程 private Thread indexThread = new Thread() { @Override public void run() { try { Thread.sleep(lazyTime * 1000); System.out.println("begin compass index..."); long beginTime = System.currentTimeMillis(); // 重建索引. // 如果compass实体中定义的索引文件已存在,索引过程中会建立临时索引, // 索引完成后再进行覆盖. compassGps.index(); long costTime = System.currentTimeMillis() - beginTime; System.out.println("compss index finished."); System.out.println("costed " + costTime + " milliseconds"); } catch (InterruptedException e) { e.printStackTrace(); } } }; /** * 实现<code>InitializingBean</code>接口,在完成注入后调用启动索引线程. * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ public void afterPropertiesSet() throws Exception { if (buildIndex) { indexThread.setDaemon(true); indexThread.setName("Compass Indexer"); indexThread.start(); } } public void setBuildIndex(boolean buildIndex) { this.buildIndex = buildIndex; } public void setLazyTime(int lazyTime) { this.lazyTime = lazyTime; } public void setCompassGps(CompassGps compassGps) { this.compassGps = compassGps; } }
4.建立索引Service 层代码
@Service @Transactional public class SearchServiceBean extends DaoSupport implements SearchService { @Resource(name = "compass") Compass compass; /** 创建索引 **/ public void index(ProductInfo p) { CompassSession session = compass.openSession(); CompassTransaction tx = null; try { tx = session.beginTransaction(); session.create(p); tx.commit(); } catch (Exception e) { if (tx != null) { tx.commit(); } throw new RuntimeException(e); } finally { if (session != null) { session.close(); } } } /** 删除一条索引 **/ public void delete(ProductInfo p) { CompassTemplate ct = new CompassTemplate(compass); ct.delete(p); } /** 更新(重新创建)一条索引 **/ public void update(final ProductInfo p) { CompassTemplate ct = new CompassTemplate(compass); CompassCallback<Object> action = new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.delete(p); session.create(p); return null; } }; ct.execute(action); } /** 索引查询 **/ public List<ProductInfo> find(final String keywords) { CompassTemplate ct = new CompassTemplate(compass); return ct.execute(new CompassCallback<List<ProductInfo>>() { public List<ProductInfo> doInCompass(CompassSession session) throws CompassException { List<ProductInfo> result = new ArrayList<ProductInfo>(); CompassQueryBuilder queryBuilder = session.queryBuilder(); CompassHits hits = null; // session.find(query); /** 在所有字段中查询 **/ CompassQuery allPropertyQuery = queryBuilder.queryString(keywords).toQuery(); hits = allPropertyQuery.hits(); /** 在指定字段中查询 **/ // CompassQuery query = queryBuilder.term("name", keywords); // hits = query.hits(); /** 指定范围查询 **/ // CompassQuery dateRangeQuery = // queryBuilder.between("postTime",startTime, endTime, true); // hits = queryBuilder.bool() // .addMust(allPropertyQuery) // .addMust(dateRangeQuery) // .toQuery() // .hits(); // System.out.println("---------"); for (int i = 0; i < hits.length(); i++) { ProductInfo p = (ProductInfo) hits.data(i); /** 如果进行高亮的属性中没有出现关键字, 则返回null **/ // String ht = hits.highlighter(i).fragment("name"); // if (ht != null) { // p.setName(ht); // } // String hc = hits.highlighter(i).fragment("code"); // if (hc != null) { // p.setCode(hc); // } result.add(p); } return result; } }); }
控制层
@Controller("/search/gosearch") public class SearchAction extends Action { @Resource(name = "searchServiceBean") private SearchService SearchService; @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String keywords=request.getParameter("word").trim(); if(keywords==null||"".equals(keywords)){ return mapping.findForward("noproduct"); } System.out.println("------"+keywords); List<ProductInfo> list = SearchService.find(keywords); request.setAttribute("word", keywords); request.setAttribute("product",list); if(list.isEmpty()){ return mapping.findForward("noproduct"); }else{ return mapping.findForward("list"); } } }
junit测试
public class SearchTest { private static AbstractApplicationContext context; @BeforeClass public static void setUpBeforeClass() throws Exception { try { context = new ClassPathXmlApplicationContext("beans.xml"); } catch (Exception e) { e.printStackTrace(); } } @Test public void testDelete() { SearchService searchService = (SearchService) context .getBean("searchServiceBean"); ProductInfo p = new ProductInfo(2); searchService.delete(p); } @Test public void createIndex(){ SearchService searchService = (SearchService) context .getBean("searchServiceBean"); ProductInfoService productInfoService = (ProductInfoService) context .getBean("productInfoServiceBean"); List<ProductInfo> list=productInfoService.getAllProduct(); for(ProductInfo productInfo:list){ // System.out.println("-------"+productInfo.getName()); searchService.index(productInfo); } } @Test public void testSearch() { SearchService searchService = (SearchService) context .getBean("searchServiceBean"); String query = "手机"; List<ProductInfo> ProductInfos; ProductInfos = searchService.find(query); for (ProductInfo p : ProductInfos) { System.out.println(p.getName()); } System.out.println("------------"); } }
发表评论
-
Compass将lucene、Spring、Hibernate三者结合
2011-05-20 01:31 43171.概述 Compass将lucene、Spring、Hib ... -
compass 使用详解
2011-05-20 01:21 6603我们在使用lucene管理document时,难免有些复杂,并 ... -
用compass快速给你的网站添加搜索功能<二>
2011-05-20 00:51 1333在上一篇文章中主要 ... -
用compass快速给你的网站添加搜索功能<一>
2011-05-20 00:48 1228如果你的网站架构采用的是spring+hibernate。用现 ... -
compass 分页查询
2011-05-20 00:43 1518有了配置文件之后,我们就可以写出相应的增删改查了 public ... -
Spring Compass (Lucene) 全文本搜索排序问题
2011-05-19 23:57 2397import org.compass.core.Com ...
相关推荐
标题 "Spring ,JPA,Compass使用注解开发的博客站内搜索" 涉及的是在Java开发环境中,利用Spring框架、Java Persistence API (JPA) 和 Compass搜索引擎来实现一个博客系统的站内搜索功能。这是一项关键的技术,因为...
标题中的"S2SH+compass"指的是一个基于Struts2(S),Spring(S)和Hibernate(H)这三种开源框架的Java Web应用,再加上Compass搜索引擎来实现站内全文检索的功能。这种组合常用于构建复杂的企业级应用,因为它提供...
通过以上步骤,你可以在SSH框架下成功集成Compass实现站内搜索分页。这一过程涉及到Java Web开发的多个层面,包括MVC架构、数据库操作、全文检索以及用户体验设计。熟练掌握这些技能将有助于构建高效且功能丰富的Web...
本文将介绍Compass,一个基于Lucene的全文搜索引擎库,为Java开发者提供了一种简单易用的方式来集成全文检索功能。Compass不仅提供了与ORM框架(如Hibernate、JPA等)的无缝集成,还支持动态索引更新,使得实时数据...
Compass 是一个搜索引擎框架,旨在提供高效、可扩展的搜索解决方案。以下是 Compass 入门指南,涵盖了 Compass 的核心概念、配置文件、注解方式、核心 API、与 Spring 集成等方面。 Compass 的配置文件 Compass 的...
在实际开发中,`compass-master`通常包含了Compass的完整代码库,包括示例、配置文件和文档,开发者可以借此学习和了解Compass的工作原理以及如何在项目中集成使用。 4. **使用Compass的步骤**: - 安装Sass和...
在Java应用中集成搜索引擎功能时,Compass提供了一种简化的方式来管理和操作Lucene索引。通过Compass,你可以将对象-关系映射(ORM)与全文检索完美结合,使得数据库中的数据能够被快速高效地搜索。 **Compass的...
Compass搜索引擎技术是一种基于Lucene的全文检索框架,它提供了更高级别的API和集成机制,使得在Java应用程序中实现搜索引擎功能变得更加便捷。Compass的主要目标是将全文索引能力无缝地融入到现有的业务应用程序中...
Compass不仅支持对关系数据库中的数据进行索引,还能与ORM框架如Hibernate、JPA等无缝集成,使得索引和搜索的数据可以与业务数据保持一致。 **二、Compass的核心特性** 1. **ORM集成**:Compass能够自动跟踪和更新...
### Java搜索 Compass 资料知识点 #### 一、Compass 概述 Compass 是一个为 Java 应用程序提供全文检索功能的框架。它能够帮助开发者在 Java 应用程序中轻松实现复杂的搜索需求,并且具有较高的性能。Compass 基于...
而Compass则在Lucene的基础上进行了封装,使得开发者可以更方便地在自己的应用程序中集成全文搜索功能。 Compass的核心特性包括: 1. **ORM集成**:Compass支持多种对象关系映射(ORM)框架,如Hibernate、JPA和...
Compass是一款基于Apache Lucene的全文搜索引擎框架,它为开发者提供了更高级别的抽象层,简化了搜索引擎的集成工作。在理解Compass之前,我们需要先了解全文检索的基本概念和原理。 全文检索是相对于传统的基于...
Compass是搜狗商业平台研发部开发的一套轻量级的分布式数据库访问框架,支持单库、主从库读写分离、分库、分库之后再分表、从库负载均衡和HA等使用场景,并且在框架层面提供了主从反延迟策略。Compass采用Spring配置...
maptalks.control.compass maptalks罗盘控件。 例子 安装 使用npm npm install maptalks.control.compass : npm install maptalks.control.compass 。 用纱安装: yarn add maptalks.control.compass 。 从下载...
【compass完整可用项目】是一个基于特定技术栈的软件开发项目,该项目的核心是Compass库,一个与Lucene紧密集成的全文搜索引擎工具。Compass提供了一种简单的方式来在Java应用程序中集成全文搜索功能,使得开发者...
Compass对象搜索引擎是一款基于Lucene的全文搜索引擎框架,它为Java开发者提供了高级的搜索功能,使得在应用程序中集成全文检索变得更加便捷。Compass的核心理念是将数据库中的对象与Lucene索引之间建立映射...
该项目是Compass-CI开源持续集成软件的设计源码,集成了Ruby、Shell、Python、HTML、Lua和JavaScript等多种编程语言。源码总量达到950个文件,包括124个Ruby源文件、114个Markdown文件、106个C++源文件、53个Shell...