Java hibernate搜索+spring3+jpa
我正在尝试将hibernate搜索集成到我的项目中。我的模型已编制索引,但由于某些原因,我的搜索查询不会返回任何结果。我已经试着解决这个问题好几个小时了,但我所做的一切似乎都不管用 域对象:Java hibernate搜索+spring3+jpa,java,spring,jpa,hibernate-search,Java,Spring,Jpa,Hibernate Search,我正在尝试将hibernate搜索集成到我的项目中。我的模型已编制索引,但由于某些原因,我的搜索查询不会返回任何结果。我已经试着解决这个问题好几个小时了,但我所做的一切似乎都不管用 域对象: @Entity @Table(name = "roles") @Indexed public class Role implements GrantedAuthority { private static final long serialVersionUID = 8227887773948216849L;
@Entity
@Table(name = "roles")
@Indexed
public class Role implements GrantedAuthority {
private static final long serialVersionUID = 8227887773948216849L;
@Id @GeneratedValue
@DocumentId
private Long ID;
@Column(name = "authority", nullable = false)
@Field(index = Index.TOKENIZED, store = Store.YES)
private String authority;
@ManyToMany
@JoinTable(name = "user_roles", joinColumns = { @JoinColumn(name = "role_id") }, inverseJoinColumns = { @JoinColumn(name = "username") })
@ContainedIn
private List<User> users;
...
}
道:
服务:
@Service(value = "roleService")
public class RoleServiceImpl implements RoleService {
@Autowired
private RoleDao roleDAO;
...
@Override
@SuppressWarnings("unchecked")
public List<Role> searchRoles(String keyword) throws ParseException {
FullTextEntityManager manager = roleDAO.getSearchManager();
TermQuery tquery = new TermQuery(new Term("authority", keyword));
FullTextQuery query = manager.createFullTextQuery(tquery, Role.class);
return query.getResultList();
}
}
测试:
配置
<persistence-unit name="hibernatePersistence" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.search.default.directory_provider" value="org.hibernate.search.store.FSDirectoryProvider" />
<property name="hibernate.search.default.indexBase" value="indexes" />
</properties>
</persistence-unit>
<!-- Entity manager -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="hibernatePersistence" />
</bean>
<!-- Transaction manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- Enable the configuration of transaction behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="org.myproject" />
事实上,数据库中填充了与该权限字段值匹配的角色。实体管理器是有效的,因为我的所有常规CRUD测试都成功了。这意味着该错误完全与hibernate search3.1.1.GA相关,但哪里出了问题?最终设法使其正常工作。。显然,这些对象不会自动编入索引。。或者至少没有承诺。现在,我的实现如下所示:
public List<Role> searchRoles(String keyword) {
// Index domain object (works)
EntityManager manager = factory.createEntityManager();
FullTextEntityManager ftManager = Search.getFullTextEntityManager(manager);
ftManager.getTransaction().begin();
List<Role> roles = ftManager.createQuery("select e from " + Role.class.getName() + " e").getResultList();
for (Role role : roles) {
ftManager.index(role);
}
ftManager.getTransaction().commit();
// Retrieve element from search (works)
TermQuery tquery = new TermQuery(new Term("authority", keyword));
FullTextQuery query = ftManager.createFullTextQuery(tquery, Role.class);
return query.getResultList();
}
通过执行index和getTransactionCommit函数,索引将正确地存储在“我的索引”文件夹中。然而,这个实现非常不自然,因为我为文本搜索创建了一个替代实体管理器。是否有一种更干净的方法可以使用@Transactional annotations对记录进行索引和提交?理论上,这一切都是可行的,但可能存在一些问题: 您最初是否为现有对象编制索引?虽然Hibernate搜索索引所有新的更改,但它不知道预先存在的对象,因此您需要首先使用ftemindex对它们进行索引 默认情况下,HSearch挂接到Hibernate或JTA事务中,以在事务事件前后侦听。可能您的Spring tx配置绕过了这一点,因此HSearch不会被触发,因此无法索引。最好的方法是使用真正的JTA事务管理器并避免这些表面现象。 如果您谈论的是使用索引的初始索引,那么您也可以使用flushToIndexes强制索引,即使发送未提交。 最后但并非最不重要的一点是,您的最后一段代码可能会抛出OutOfMemoryException,因为您在索引对象之前加载了内存中的所有对象。查看Hibernate搜索参考文档,了解如何正确索引批量加载的对象。《Hibernate Search in Action by Manning I'm the author》也深入探讨了这一切。
最终,我的问题通过附加以下属性得到解决: hibernate.search.worker.batch\u size=1
现在,我不仅可以正确地进行查询,而且每当我持久化我的域对象时,索引也会自动更新。我现在唯一的问题是,通过import.sql插入的数据不会自动索引。是否有某种神奇的hibernate.search属性可用于此问题,或者我应该手动为它们编制索引?您确定您的数据库支持全文搜索吗?更正:域对象没有正确编制索引。@Roman:hibernate搜索的全部要点是它没有使用数据库的全文搜索功能,这是在应用层完成的。我知道这有点晚了,但我会发表评论,希望对互联网上的人有所帮助。我使用Spring在运行时加载的类,并在应用程序启动时使用我的方法上的@PostConstruct注释重新索引现有数据。
<persistence-unit name="hibernatePersistence" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.search.default.directory_provider" value="org.hibernate.search.store.FSDirectoryProvider" />
<property name="hibernate.search.default.indexBase" value="indexes" />
</properties>
</persistence-unit>
<!-- Entity manager -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="hibernatePersistence" />
</bean>
<!-- Transaction manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- Enable the configuration of transaction behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="org.myproject" />
public List<Role> searchRoles(String keyword) {
// Index domain object (works)
EntityManager manager = factory.createEntityManager();
FullTextEntityManager ftManager = Search.getFullTextEntityManager(manager);
ftManager.getTransaction().begin();
List<Role> roles = ftManager.createQuery("select e from " + Role.class.getName() + " e").getResultList();
for (Role role : roles) {
ftManager.index(role);
}
ftManager.getTransaction().commit();
// Retrieve element from search (works)
TermQuery tquery = new TermQuery(new Term("authority", keyword));
FullTextQuery query = ftManager.createFullTextQuery(tquery, Role.class);
return query.getResultList();
}