Spring 使用 Hibernate Search 启动 2,保存时不创建索引

Spring Boot 2 with Hibernate Search, indexes are not created on save

我有一个定义如下的实体。如果我使用 save() Hibernate 不会为新创建的实体创建新索引。 Updating/modifying 现有实体运作良好,符合预期。

我在 spring boot 2 中使用 kotling。

@Entity(name = "shipment")
@Indexed
data class Shipment(
        @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long = -1,
        @JoinColumn(name = "user") @ManyToOne() var user: User?,
        @IndexedEmbedded
        @JoinColumn(name = "sender") @ManyToOne(cascade = [CascadeType.ALL]) val sender: Contact,
        @IndexedEmbedded
        @JoinColumn(name = "sender_information") @ManyToOne(cascade = [CascadeType.ALL]) val senderInformation: ShipmentInformation,
) {}

保存功能,我正在使用相同的功能来更新我的实体,如果索引存在则更新索引。

    @Transactional
    fun save(user: User, shipment: Shipment): Shipment {
        shipment.user = user;
        return this.shipmentRepository.save(shipment)
    }

application.properties

spring.jpa.properties.hibernate.search.default.directory_provider=filesystem
spring.jpa.properties.hibernate.search.default.indexBase=./lucene/
spring.jpa.open-in-view=false

如果我重新启动服务器,手动索引也可以。

    @Transactional
    override fun onApplicationEvent(event: ApplicationReadyEvent) {
        val fullTextEntityManager: FullTextEntityManager = Search.getFullTextEntityManager(entityManager)
        fullTextEntityManager.createIndexer().purgeAllOnStart(true)
        fullTextEntityManager.createIndexer().optimizeAfterPurge(true)
        fullTextEntityManager.createIndexer().batchSizeToLoadObjects(15)
        fullTextEntityManager.createIndexer().cacheMode(CacheMode.IGNORE)
        fullTextEntityManager.createIndexer().threadsToLoadObjects(2)
        fullTextEntityManager.createIndexer().typesToIndexInParallel(2)
        fullTextEntityManager.createIndexer().startAndWait()
        return
    }

我试图强制使用 JPA 事务管理器,但它没有帮助我。

    @Bean(name = arrayOf("transactionManager"))
    @Primary
    fun transactionManager(@Autowired entityManagerFactory: EntityManagerFactory): org.springframework.orm.jpa.JpaTransactionManager {
        return JpaTransactionManager(entityManagerFactory)
    }

更新

我想我找到了为什么我没有得到新插入实体的结果。

我的搜索查询在声明的 "pid" 字段上有一个条件:

        @Field(index = Index.YES, analyze = Analyze.NO, store = Store.NO)
        @SortableField
        @Column(name = "id", updatable = false, insertable = false)
        @JsonIgnore
        @NumericField val pid: Long,

并查询:

query.must(queryBuilder.keyword().onField("customer.pid").matching(user.customer.id.toString()).createQuery())

pid 未存储,因此新插入的值不可见。这可能是原因吗?

顺便说一句:如何通过嵌套索引文档 ID query/search?在我的例子中,它是 customer.id,即 DocumentId。我试过如下更改查询但没有得到任何结果,我应该创建一个新字段来查询吗?

query.must(queryBuilder.keyword().onField("customer.id").matching(user.customer.id.toString()).createQuery())

更新 2

我找到了解决方案,现在也得到了新插入的数据。 "pid" 字段的定义有误,我已经如下定义了我的字段,它按预期工作。

        @Fields(
                Field(name = "pid", index = Index.YES, analyze = Analyze.YES, store = Store.NO)
        )
        @SortableField(forField = "pid")
        @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long?,

我们能否以一种简单的方式按 ID 进行搜索和排序,或者这是最佳做法吗?我知道我们应该使用本机 JPA 函数通过 id 获取结果,但在我的情况下,我需要通过嵌入式 id 进行搜索以限制搜索结果。 (取决于用户的角色)因此这不是我的选择。

而且我不明白为什么手动索引有效...

这看起来很奇怪:

        @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long = -1,

我期望一个可为 null 的 long,初始化为 null(或任何 Kotlin 等价物)。

我不确定这是不是问题所在,但我想这可能是因为非空 ID 通常只需要来自已经存在的实体。

除此之外,我认为您的方向是正确的:如果批量索引有效但自动索引无效,则可能与您的更改未在数据库事务中执行有关。

BTW: How can I query/search by nested indexed document id? In my case it is customer.id which is DocumentId. I've tried to change the query like below but don't get any result, should I create a new field to query?

通常情况下,如果您只想执行完全匹配,则不需要创建单独的字段。

Can we search and sort by id in an easy way

正在搜索,是的,至少在 Hibernate Search 5 中是这样。

排序,否:您需要一个专用字段。

or is it the best practice?

如果您需要比 ID 完全匹配更复杂的内容,最好在 @DocumentId 旁边声明一个字段。

I know that we should use native JPA functions to get results by id

我不确定我是否理解 "native JPA functions" 的意思。

but in my case I need to search by an embedded id to restrict search results. (depends on role of user)

是的,这应该有效。也就是说,如果正确填充了 id,它应该可以工作。

And I don't understand why manual indexing works...

我也不知道,但我想解释在于 "error in the definition of "pid" 字段"。也许在某些情况下 ID 未正确填充,导致实体被 Hibernate Search 视为已删除?

如果你需要我给你一个明确的答案,最好的办法就是创建一个复制器。您可以将其用作模板:https://github.com/hibernate/hibernate-test-case-templates/tree/master/search