Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java hibernate搜索+spring3+jpa_Java_Spring_Jpa_Hibernate Search - Fatal编程技术网

Java hibernate搜索+spring3+jpa

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;

我正在尝试将hibernate搜索集成到我的项目中。我的模型已编制索引,但由于某些原因,我的搜索查询不会返回任何结果。我已经试着解决这个问题好几个小时了,但我所做的一切似乎都不管用

域对象:

@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();
}