当通过@NoRepositoryBean Jpa方法删除对象时,Hibernate搜索不会从lucene索引中删除旧值



我有一个NoRepositoryBeanJpa接口,它有一个名为deleteAllByIdIn(...)的自定义Jpa方法,它由一些具体的Jpa存储库继承。由于某些原因,Hibernate Search忽略了此自定义删除方法。每当通过此自定义方法删除实体时,在删除完成后,其值不会从lucene索引中删除。我将在这篇文章中进一步解释这个问题;但首先是代码

@NoRepositoryBean
public interface NameTranslationDao<T extends NameTranslation> extends JpaRepository<T, Long> {
@Modifying
@Transactional
@Query(value = "DELETE FROM #{#entityName} c WHERE c.id IN :translationsToDelete")
public void deleteAllByIdIn(@Param("translationsToDelete") Set<Long> translationsToDelete);
}

这里有一个扩展此接口的JpaRepository子类:

@Repository
@Transactional(readOnly = true)
public interface LifeStageCommonNameTranslationDao extends CommonNameTranslationDao<LifeStageCommonNameTranslation> {
}

在具体的JpaRepository和NameTranslationDao NoRepositoryBean之间还有另一个@NoRepositoryBean接口。这个方法被称为CommonNameTranslationDao,但它不会以任何方式覆盖自定义方法,所以它不太可能是问题的原因,不过这里有该存储库的代码:

@NoRepositoryBean
public interface CommonNameTranslationDao<T extends NameTranslation> extends NameTranslationDao<T> {
@Deprecated
@Transactional(readOnly = true)
@Query("SELECT new DTOs.AutoCompleteSuggestion(u.parent.id, u.autoCompleteSuggestion) FROM #{#entityName} u WHERE u.autoCompleteSuggestion LIKE :searchString% AND deleted = false  AND (u.language.id = :preferredLanguage OR u.language.id = :defaultLanguage)")
List<AutoCompleteSuggestion> findAllBySearchStringAndDeletedIsFalse(@Param("searchString") String searchString, @Param("preferredLanguage") Long preferredLanguage, @Param("defaultLanguage") Long defaultLanguage);
@Transactional(readOnly = true)
@Query(nativeQuery = true, value = "SELECT s.translatedName FROM #{#entityName} s WHERE s.language_id = :preferredLanguage AND s.parent_id = :parentId LIMIT 1")
public String findTranslatedNameByParentAndLanguage(@Param("preferredLanguage") Long languageId, @Param("parentId") Long parentId);
@Modifying
@Transactional
@Query(nativeQuery = true, value = "DELETE FROM #{#entityName} WHERE id = :id")
void hardDeleteById(@Param("id") Long id);
@Modifying
@Transactional
@Query(nativeQuery = true, value = "UPDATE #{#entityName} c SET c.deleted = TRUE WHERE c.id = :id")
void softDeleteById(@Param("id") Long id);
}

此外,这里还有LifeStageCommonNameTranslation实体类的代码:

@Entity
@Indexed
@Table(
uniqueConstraints = {
@UniqueConstraint(name = "UC_life_cycle_type_language_id_translatedName", columnNames = {"translatedName", "parent_id", "language_id"})
},
indexes = {
@Index(name = "IDX_lifestage", columnList = "parent_id"),
@Index(name = "IDX_translator", columnList = "user_id"),
@Index(name = "IDX_species_language", columnList = "language_id, parent_id, deleted"),
@Index(name = "IDX_autoCompleteSuggestion_language", columnList = "autoCompleteSuggestion, language_id, deleted")})
public class LifeStageCommonNameTranslation extends NameTranslation<LifeStage> implements AuthorizationSubject {

@Id @DocumentId
@GenericGenerator(
name = "sequenceGeneratorLifeStageCommonNameTranslation",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
@org.hibernate.annotations.Parameter(name = "sequence_name", value = "_lifestagecommonnametranslation_hibernate_sequence"),
@org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled"),
@org.hibernate.annotations.Parameter(name = "initial_value", value = "1"),
@org.hibernate.annotations.Parameter(name = "increment_size", value = "25"),
@org.hibernate.annotations.Parameter(name = "prefer_sequence_per_entity", value = "true")
}
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "sequenceGeneratorLifeStageCommonNameTranslation"
)
@Field(analyze = Analyze.NO, store = Store.YES, name = "parentId")
private Long id;

@IndexedEmbedded(includeEmbeddedObjectId = true)
@ManyToOne(fetch = FetchType.LAZY)
private LifeStage parent;

@Field(index = NO, store = Store.YES)
private String autoCompleteSuggestion;
//Getters and setters ommitted

问题如下:每当我在LifeStageCommonNameTranslationDao上使用继承的deleteAllByIdIn()方法时,在删除实体后,Hibernate Search将不会从lucene index中删除autoCompleteSuggestion字段值。但是,如果我使用标准deleteById()JpaRepository方法删除实体,则字段值将从lucene index中删除

自定义和标准删除方法都是在@Transactional注释的方法中调用的,之后我还调用了flush()jpaRepository方法。我这样做是因为我读到这有时可以帮助更新lucene指数。但在deleteAllByIdIn()的情况下,随后呼叫flush()根本没有帮助。

我已经排除了问题是由SQL查询中的spEL表达式引起的可能性。我通过用LifeStageCommonTranslation这样的具体实体名称替换#{#entityName},然后调用deleteAllByIdIn()delete方法来测试这一点。但问题仍然存在。lucene索引在删除后仍然没有删除autoSuggestionText字段值。

我可以简单地使用标准的jpa方法deleteById()来解决这个问题,但我想知道为什么定制的jpa方式deleteAllByIdIn()不会导致Hibernate搜索更新lucene索引。

Hibernate Search检测在Hibernate ORMSession/EntityManager中发生的实体更改事件。这不包括您在JPQL或本机SQL查询中自己编写的insert/update/delete语句。

此处记录了限制:https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#limitations-会话中的更改

解决方法也记录在那里:

一种解决方法是在运行JPQL/SQL查询后显式重新索引,可以使用MassIndexer或手动重新索引。

EDIT:当然,如果deleteById在删除实体之前在会话中加载实体,那么您的变通方法也可能有效(我对Spring Data JPA的内部结构不太熟悉):

我只需使用标准的jpa方法deleteById()就可以很容易地解决这个问题,但我想知道为什么自定义的jpa方式deleteAllByIdIn()不会导致Hibernate搜索更新lucene索引。

相关内容

  • 没有找到相关文章

最新更新