Hibernate搜索-自定义网桥值未更新
发件人: 我有:Hibernate搜索-自定义网桥值未更新,hibernate,lucene,hibernate-search,Hibernate,Lucene,Hibernate Search,发件人: 我有: @Indexed @Entity public class TParent implements java.io.Serializable { ..... private Set<TChild> TChildSet = new HashSet<TChild>(0); @ContainedIn @FieldBridge(impl = CollectionCountBridge.class) @Field(analyze = Analyze.NO) @
@Indexed
@Entity
public class TParent implements java.io.Serializable {
.....
private Set<TChild> TChildSet = new HashSet<TChild>(0);
@ContainedIn
@FieldBridge(impl = CollectionCountBridge.class)
@Field(analyze = Analyze.NO)
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="TParent")
public Set<TChild> getTChildSet() {
return this.TChildSet;
}
多亏了唐·罗比,我申请了这座桥
public class CollectionCountBridge extends IntegerBridge {
@Override
public String objectToString(Object object) {
if (object == null || (!(object instanceof Collection))) {
return null;
}
Collection<?> coll = (Collection<?>) object;
int size = coll.size();
System.out.println("col.size(): " + size);
return super.objectToString(size);
}
}
现在
当我添加一个新的TChild时,将执行CustomBridge代码。我希望在添加TChild时看到订单的变化
我可以看到TChild计数增加了(根据CustomBridge代码中的System.out.println()
但是,查询没有对它们进行正确排序。索引第一次构建时的原始排序顺序保持不变。添加新的TChild对排序顺序没有影响。
我想索引没有更新,但我不确定
任何帮助或指点都会很好
非常感谢
约翰
编辑
直接的问题是索引中的值没有更新。这可以通过Luke看到。我认为您的问题是,您将数字(整数)索引为字符串,但您希望进行数字排序 你有两个选择。如果您坚持使用字符串方法,则需要创建填充字符串(例如,如果您知道您的元素从未超过100个,那么您将填充所有数字,如003等)。这样一来,词法顺序将表现为数字顺序 可能更好的选择是将计数作为数字字段进行索引。这样,排序将自动为数字。类似于(未经测试):
公共类集合CountFieldBridge{
无效集(字符串名称、对象值、文档、LuceneOptions LuceneOptions){
if(object==null | |(!(集合的对象实例))){
返回null;
}
Collection coll=(Collection)对象;
int size=coll.size();
luceneOptions.addNumericFieldToDocument(名称、值、文档);;
}
}
我认为您的问题在于您将数字(整数)索引为字符串,但您希望进行数字排序
你有两个选择。如果您坚持使用字符串方法,则需要创建填充字符串(例如,如果您知道您的元素从未超过100个,那么您将填充所有数字,如003等)。这样一来,词法顺序将表现为数字顺序
可能更好的选择是将计数作为数字字段进行索引。这样,排序将自动为数字。类似于(未经测试):
公共类集合CountFieldBridge{
无效集(字符串名称、对象值、文档、LuceneOptions LuceneOptions){
if(object==null | |(!(集合的对象实例))){
返回null;
}
Collection coll=(Collection)对象;
int size=coll.size();
luceneOptions.addNumericFieldToDocument(名称、值、文档);;
}
}
问题
在实体中,对不是DB表字段的索引字段执行更新,然后保存实体不会导致索引更新。(保存实体并更新为DB表字段的索引字段将导致索引自动更新)
解决方案
(简单地)手动更新索引
public static void addTChild() {
Session session = null;
try {
session = HibernateUtil.getSession();
session.beginTransaction();
TParent tParent = (TParent)session.get(TParent.class, 6L);
TChild tChild = new TChild(tParent, "Auto added " + new Date().toString(), 'y');
Long id = (Long)session.save(tChild);
tChild = (TChild)session.get(TChild.class, id);
tParent.getTChildSet().add(tChild);
session.save(tParent);
/*
* Manually update the index.
* Necessary due to fact that the index field updated
* is not a DB table field and hence will not cause an index update
*/
FullTextSession fullTextSession = Search.getFullTextSession(session);
fullTextSession.index(tParent);
session.getTransaction().commit();
} catch (Exception ex) {
session.getTransaction().rollback();
ex.printStackTrace();
} finally{
if(session != null) {
session.close();
}
}
}
实体:
/*
* TParent
*/
@ContainedIn
@FieldBridge(impl = CollectionCountBridge.class)
@Field(analyze = Analyze.NO, store = Store.YES, name = "cCount")
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="TParent")
public List<TChild> getTChildSet() {
return this.TChildSet;
}
这就是我所能确定的。问题所在 在实体中,对不是DB表字段的索引字段执行更新,然后保存实体不会导致索引更新。(保存实体并更新为DB表字段的索引字段将导致索引自动更新) 解决方案 (简单地)手动更新索引
public static void addTChild() {
Session session = null;
try {
session = HibernateUtil.getSession();
session.beginTransaction();
TParent tParent = (TParent)session.get(TParent.class, 6L);
TChild tChild = new TChild(tParent, "Auto added " + new Date().toString(), 'y');
Long id = (Long)session.save(tChild);
tChild = (TChild)session.get(TChild.class, id);
tParent.getTChildSet().add(tChild);
session.save(tParent);
/*
* Manually update the index.
* Necessary due to fact that the index field updated
* is not a DB table field and hence will not cause an index update
*/
FullTextSession fullTextSession = Search.getFullTextSession(session);
fullTextSession.index(tParent);
session.getTransaction().commit();
} catch (Exception ex) {
session.getTransaction().rollback();
ex.printStackTrace();
} finally{
if(session != null) {
session.close();
}
}
}
实体:
/*
* TParent
*/
@ContainedIn
@FieldBridge(impl = CollectionCountBridge.class)
@Field(analyze = Analyze.NO, store = Store.YES, name = "cCount")
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="TParent")
public List<TChild> getTChildSet() {
return this.TChildSet;
}
这就是我所能确定的。Hmmm。。谢谢,我试过了,但还是不高兴。同样的问题。无论如何,我的测试用例只有不到10个项,所以即使整数是字符串,它们也会继续以单位数正确排序。我分析了卢克的索引。我可以看到,在添加新的TChild时,没有更新子计数。我已经完成了session.save(tChild)和session.update(tParent),将新的tChild添加到列表中。嗯,我认为您确实应该创建子实例,将其添加到父实例中,在子实例中设置父实例,然后在父实例中调用session.save。由于级联保存,所有内容都将被保存。使用当前的方法,我认为您不会因为重新索引父对象而得到回调。可能会发布关于如何更新和持久化实体的代码。非常感谢您的输入。你说得对,TParent确实需要更新。但是我发现(这就是问题所在)在保存TParent之前,仅仅将TChild添加到TChildSet是不够的。TParent的一些其他属性,在保存TParent之前,也需要更新用字段注释的属性。也就是说,TParent有一个“title”(字符串)成员,用字段注释。如果我将“title”设置为某物并保存,则TChildSet计数将在索引中更新。如果我没有更改“title”,则索引中的TChildSet计数值不会更新。Hmmm。。谢谢,我试过了,但还是不高兴。同样的问题。无论如何,我的测试用例只有不到10个项,所以即使整数是字符串,它们也会继续以单位数正确排序。我分析了卢克的索引。我可以看到,在添加新的TChild时,没有更新子计数。我已经完成了session.save(tChild)和session.update(tParent),将新的tChild添加到列表中。嗯,我认为您确实应该创建子实例,将其添加到父实例中,在子实例中设置父实例,然后在父实例中调用session.save。由于级联保存,所有内容都将被保存。使用当前的方法,我认为您不会因为重新索引父对象而得到回调。可能会发布关于如何更新和持久化实体的代码。非常感谢您的输入。你说得对,TParent确实需要更新。但是我发现(这就是问题所在)在保存TParent之前,仅仅将TChild添加到TChildSet是不够的。TParent的一些其他属性,用需要upda的字段注释
/*
* TParent
*/
@ContainedIn
@FieldBridge(impl = CollectionCountBridge.class)
@Field(analyze = Analyze.NO, store = Store.YES, name = "cCount")
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="TParent")
public List<TChild> getTChildSet() {
return this.TChildSet;
}
/*
* TChild
*/
@IndexedEmbedded
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="parent_id", nullable=false)
public TParent getTParent() {
return this.TParent;
}