簡體   English   中英

Hibernate Search不會索引/重新索引實體

[英]Hibernate Search doesn't index/reindex entities

我正在嘗試在我的項目中使用Hibernate Search(現在使用junit + dbunit編寫測試),但搜索查詢不會返回任何結果。 我昨天研究了這個問題並得出結論,問題是Hibernate Search與dbunit @DatabaseSetup不兼容(類似於這個未回答的問題中的類似問題: 鏈接 )。 我將提供更多細節,但首先是冷杉,有我的實體類:

@Entity
@Indexed
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "userId")
    private Long id;
    (...)
    @Column(nullable = false, unique = true)
    @Field(index = Index.YES, analyze=Analyze.YES, store=Store.NO)
    private String email;
    (...)
    @Column(nullable = false, unique = true)
    @Field(index = Index.YES, analyze=Analyze.YES, store=Store.NO)
    private String username;
    (...)
}

我通過我的DAO將它保存到db:

@Repository
public class UserDAOImpl implements UserDAO {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public long save(User toSave) {

        return (Long) this.sessionFactory.getCurrentSession().save(toSave);
    }
(...)
}

這是負責運行lucene查詢的代碼:

@Override
    public List<User> searchByEmail(String email) throws InterruptedException {

        return generateHibernateSearchQueryFor("email", email).list();
    }

    private org.hibernate.Query generateHibernateSearchQueryFor(String field, String searchParam) {

        FullTextSession fullTextSession = Search.getFullTextSession(sessionFactory.getCurrentSession());
        QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(User.class).get();

        org.apache.lucene.search.Query lQuery = queryBuilder.keyword().onFields(field).matching(searchParam).createQuery();
        org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery(lQuery, User.class);

        return fullTextQuery;
    }

這就是spring配置中的配置方式:

<bean id="hibernate4AnnotatedSessionFactory"
          class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="me.ksiazka.model" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>

                <prop key="hibernate.search.default.directory_provider">filesystem</prop>
                <prop key="hibernate.search.default.indexBase">src/searching_indexes</prop>
            </props>
        </property>
    </bean>

現在我是如何測試的。 我使用dbunit配置了測試數據集並創建了如下測試方法:

    @Test
    @DatabaseSetup("classpath:/testsDataset.xml")
    public void searchByEmailTest() {

        User u1 = new User("Maciej", "Adamowicz", "k2", "mac@gmial.com", "MacAda");
        userDAO.save(u1);

        List<User> u = null;
        try {
            //It worked at first - as new user was saved with hibernate he got his index in hibernate search indexes folder and searching found him.
            u = searchService.searchByEmail("mac@gmail.com");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //I know there should be asserts, its just for simplification for need of moment.
        System.out.println(":: " + u.size());
        System.out.println(":: " + u.get(0).getName());
    }


    List<User> u2 = null;
    try {
        //abc@gmial.com is in db - setted up by @DatabaseSetup
        u2 = searchService.searchByEmail("abc@gmail.com");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    //This didnt work, rows putted into db by dbunit doesn't have indexes in my indexing folder.
    System.out.println(":: " + u2.size());
    System.out.println(":: " + u2.get(0).getName());
}

在查看Hibernate Search文檔后,我發現了fullTextSession.createIndexer().startAndWait(); 方法。 我使用它但它仍然不適用於來自@DatabaseSetup的行。 無論如何,它使用了我在使用sql“手動”測試之前調試的行,因此我認為這只是dbunit的問題,只是用@Before編寫了設置:

@Before
    public void setupDatabase() {

        if(!doneBefore) {

            try {
                //It calls createIndexer().startAndWait() to make sure everything is indexed before test
                searchService.reindex();
            } catch (InterruptedException e) {    
                e.printStackTrace();
            }

            User u1 = new User("Maciej", "Adamowicz", "k2", "mac@gmial.com", "MacAda");
            userDAO.save(u1);

            doneBefore = true;
        }

    }

並運行此測試:

    @Test
    public void searchByEmailTest() {

        List<User> u = null;
        try {
            u = searchService.searchByEmail("mac@gmail.com");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //Also asserts here, I know.
        System.out.println(":: " + u.size());
        System.out.println(":: " + u.get(0).getName());
    }

雖然hibernate保存了數據,但它並不起作用。 我試圖找到bug並將我的代碼恢復到測試通過的eariel版本(帶有@DatabaseSetup的版本,但僅用於使用我的dao保存的行),現在這個版本也沒有通過。 我很困惑並且沒有想法為什么它沒有索引新對象,更不用說為什么它不會在調用大量索引器時重新索引所有數據庫。 任何幫助將不勝感激。

編輯:

在潛在的答案后,我做了一些更多的測試 關於搜索有時會產生雙倍或三倍行的事實我嘗試.purgeAll()並將索引提供程序更改為RAM以確保我的索引在開始測試時是干凈的。 它基本上沒有任何改變。 為了構建我的索引,我使用了前面提到的.startAndWait() 嘗試使用.index() “手動”構建它,但在嘗試使用fullTextSession時遇到了一些嵌套的事務問題。 顯式提交事務(或設置@Rollback(false) - 嘗試兩者)也不起作用。 我在Hibernate Search文檔中找到的所有嘗試 - 鏈接 索引和搜索工作正常,如果我在搜索它之前保存了一些東西,但做同樣的事情@Before然后搜索只是不起作用。

當我沒記錯的話,Hibernate Search會在你提交交易時更新索引。

這對於普通代碼來說沒有問題,但在測試中這種行為可能會導致問題,因為測試的常見模式是,當您開始測試時啟動事務,並且在測試結束時您將事務作用回來,但你永遠不會提交它們。

要驗證這是導致問題的原因,請創建一個測試,啟動明確的新事務,修改某些內容然后提交事務。 然后在提交后檢查你的hiberante搜索索引。

如本Hibernate Search中所述,不會索引/重新索引實體 ,您需要在保存數據后顯式提交事務以便進行索引。 索引發生在事務后同步(至少每個默認值)。

您可以嘗試使用手動索引API或質量索引器。 我不確定為什么這對你不起作用。 我也不確定@DatabaseSetup是如何工作的並且掛鈎到JUnit生命周期中。

關於三重結果。 您可能正在使用基於文件系統的索引(默認情況下使用),該索引會創建基於Lucene索引的索引,該索引在測試運行之間不會被清除。 使用RAM索引或確保清除基於文件的索引。

如果您共享Hibernate屬性配置,它可能會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM