【发布时间】:2018-04-24 07:34:09
【问题描述】:
我的应用程序有这个模型,我有一个 Element 抽象类和几个扩展它的类。这个元素有一个ElementType 并且可以有一个Owner。
现在我需要一个 REST 服务,它在多个字段上实现文本搜索:
@Entity
@Table(name = "elements")
@Inheritance(strategy=InheritanceType.JOINED)
@XmlRootElement
@AnalyzerDef(
name = "textanalyzer",
tokenizer = @TokenizerDef(factory = KeywordTokenizerFactory.class),
filters = {
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
@TokenFilterDef(factory = ASCIIFoldingFilterFactory.class)})
public abstract class Elements implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "elementid")
private Integer elementId;
@Basic(optional = false)
@Column(name = "code", unique = true)
@Field(index=Index.YES, analyzer = @Analyzer(definition = "textanalyzer"))
private String code;
@Basic(optional = false)
@Field(index=Index.YES)
@Column(name = "enabled")
private boolean enabled;
@IndexedEmbedded
@JoinColumn(name = "ownerid", referencedColumnName = "ownerid")
@ManyToOne(optional = true)
private Owners owner;
@IndexedEmbedded
@JoinColumn(name = "elementtypeid", referencedColumnName = "elementtypeid")
@ManyToOne(optional = false)
private ElementTypes elementType;
.
.
.
}
@Entity
@Table(name = "owners")
@XmlRootElement
public class Owners implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "ownerid")
private Integer ownerId;
@Basic(optional = false)
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO, analyzer = @Analyzer(definition = "textanalyzer"))
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "owner")
@ContainedIn
private Collection<Elements> elementsCollection;
.
.
.
}
@Entity
@Table(name = "elementtypes")
@XmlRootElement
public class ElementTypes implements Serializable {
@OneToMany(mappedBy = "elementType")
@ContainedIn
private Collection<Elements> elementsCollection;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "elementtypeid")
private Integer elementTypeId;
@Basic(optional = false)
@Column(name = "code", unique = true)
@Field(index = Index.YES)
private String code;
.
.
.
}
扩展Element的类示例:
@Entity
@Indexed
@Table(name = "digitalinputs")
@XmlRootElement
@PrimaryKeyJoinColumn(name="elementid")
public class DigitalInputs extends Elements {
@Basic(optional = false)
@Column(name = "position")
private int position;
@Basic(optional = true)
@Column(name = "state")
private boolean state;
.
.
.
}
服务代码(太长,这里显示简化):
@Path("/search")
public class SearchController {
@Context
ServletContext context;
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getElementsSearch(SearchRequestObject sro) {
Session session = SessionUtil.getSession();
FullTextSession fullTextSession = (FullTextSession)context.getAttribute("fullTextSession"); //indexes are rebuild at the beginning of execution, and the FullTextSession reference is stored in application context
try {
org.apache.lucene.search.Query query;
QueryBuilder qb = fullTextSession.getSearchFactory()
.buildQueryBuilder().forEntity(Elements.class).get();
if(sro.isDisabled() || sro.isEnabled() || sro.getType() != null) {
BooleanQuery.Builder builder = new Builder();
//form the query
.
.
.
}
// wrap Lucene query in a javax.persistence.Query
javax.persistence.Query jpaQuery =
fullTextSession.createFullTextQuery(query, Elements.class);
// execute search
List<Elements> result = jpaQuery.getResultList();
return Response.status(Response.Status.OK).entity(response).build();
}catch(Exception e) {
throw e;
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e).build();
}
}
}
此服务运行良好,但我有一个大问题:当在休眠状态下执行 update、merge 或 saveOrUpdate 时,索引似乎没有更新,并且搜索返回的旧值物体。 delete 或 save 操作不会发生这种情况,它们正在更新索引。
我见过一些人遇到同样的问题(lucene index not getting sync when any update occurs in DB through hibernate,merge not updating lucene index),但我没有得到实际的解决方案。 @ContainedIn 标签似乎没问题,我尝试在调用更新操作时同时刷新 Session 和索引:
@Override
public T editEntity(T bean) {
T t = null;
try {
this.createSession();
this.createTransaction();
//this.getSession().merge(bean);
this.getSession().update(bean);
this.getSession().flush();
FullTextSession fts = (FullTextSession)ApplicationUtil.getServletContext().getAttribute("fullTextSession");
fts.flushToIndexes();
this.getTransaction().commit();
}catch(Exception e) {
this.getTransaction().rollback();
throw e;
}finally {
this.closeSession();
}
return bean;
}
但它仍然无法正常工作。我想说我忽略了一些重要的事情,但我找不到对我的案例有用的信息,因此我们将非常感谢任何帮助。
【问题讨论】:
标签: java hibernate lucene hibernate-search