Introduction
The aim of this guide is to assist you migrating
an existing application using any version 6.1.x
of Hibernate Search
to the latest of the 6.2.x
series.
If you think something is missing or something does not work, please contact us. |
If you’re looking to migrate from an earlier version, you should migrate step-by-step, from one minor version to the next, following the migration guide of each version.
To Hibernate Search 5 users Be aware that a lot of APIs have changed since Hibernate Search 5, some only because of a package change, others because of more fundamental changes (like moving away from using Lucene types in Hibernate Search APIs). When migrating from Hibernate Search 5, you are encouraged to migrate first to Hibernate Search 6.0 using the 6.0 migration guide, and only then to later versions (which will be significantly easier). |
Data format and schema changes
Indexes created with Hibernate Search 6.1 can be read from and written to with Hibernate Search 6.2.0.Alpha2.
If your Hibernate Search mapping includes GeoPoint
fields that are using the default value for the projectable
option,
and are using either the default value or Sortable.NO
for the sortable
option, Elasticsearch schema validation
will fail on startup because of missing docvalues on those fields.
To address that, either:
-
Revert to the previous defaults by adding
projectable = Projectable.NO
to the mapping annotation of relevantGeoPoint
fields. -
Or recreate your Elasticsearch indexes and reindex your database. The easiest way to do so is to use the the
MassIndexer
withdropAndCreateSchemaOnStart(true)
.
Outbox polling system tables
If you use the incubating outbox-polling
coordination strategy,
you will be impacted by changes to the entities that represents the outbox event and agent,
requiring database schema changes.
For the outbox event table the column processAfter
is now non-nullable, the id
column changes its type from integer to varchar,
except MSSQL where the id
type becomes binary.
For the agent table id
column changes its type from integer to varchar,
except MSSQL where the id
type becomes binary.
You can find suggested migration scripts for the tested databases below:
-- adjust `processAfter` values for existing events so that older events (i.e. ones with smaller ID) will have older timestamp:
update hsearch_outbox_event
set processAfter = now() - make_interval(secs => (select max(id) from hsearch_outbox_event) - id)
where processAfter is null;
alter table hsearch_outbox_event
alter column processAfter set not null;
-- change outbox event `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_outbox_event
alter column id TYPE varchar(36) USING gen_random_uuid();
-- change agent `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_agent
alter column id TYPE varchar(36) USING gen_random_uuid();
-- adjust `processAfter` values for existing events so that older events (i.e. ones with smaller ID) will have older timestamp:
update hsearch_outbox_event
set processAfter = now() - cast(((select max(id) from hsearch_outbox_event) - id) || ' SECOND' as interval)
where processAfter is null;
alter table hsearch_outbox_event
alter column processAfter set not null;
-- change outbox event `id` column type to varchar and generate uuids to replace previous int values:
-- altering type directly is not supported: https://go.crdb.dev/issue-v/47636/v22.1
alter table hsearch_outbox_event
add tmp varchar(36) default cast(gen_random_uuid() as varchar) not null;
alter table hsearch_outbox_event
alter primary key using columns (tmp);
alter table hsearch_outbox_event
drop column id;
alter table hsearch_outbox_event
rename column tmp to id;
-- change agent `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_agent
add tmp varchar(36) default cast(gen_random_uuid() as varchar) not null;
alter table hsearch_agent
alter primary key using columns (tmp);
alter table hsearch_agent
drop column id;
alter table hsearch_agent
rename column tmp to id;
-- adjust `processAfter` values for existing events so that older events (i.e. ones with smaller ID) will have older timestamp:
with max_id as (
select max(id) as id from hsearch_outbox_event
)
update hsearch_outbox_event
set created = subtime(now(), sec_to_time((select id from max_id) - id))
where processAfter is null;
alter table hsearch_outbox_event
modify column processAfter datetime not null;
-- change outbox event `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_outbox_event
modify column id varchar(36);
update hsearch_outbox_event
set id = uuid()
where 1 = 1;
-- change agent `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_agent
modify column id varchar(36);
update hsearch_agent
set id = uuid()
where 1 = 1;
-- adjust `processAfter` values for existing events so that older events (i.e. ones with smaller ID) will have older timestamp:
update hsearch_outbox_event
set processAfter = subtime(now(), sec_to_time((select max(id) as id from hsearch_outbox_event) - id))
where processAfter is null;
alter table hsearch_outbox_event
modify column processAfter datetime not null;
-- change outbox event `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_outbox_event
modify column id varchar(36);
update hsearch_outbox_event
set id = uuid()
where 1 = 1;
-- change agent `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_agent
modify column id varchar(36);
update hsearch_agent
set id = uuid()
where 1 = 1;
-- adjust `processAfter` values for existing events so that older events (i.e. ones with smaller ID) will have older timestamp:
update hsearch_outbox_event
set processAfter = current_timestamp - ((select max(id) from hsearch_outbox_event) - id) seconds
where processAfter is null;
alter table hsearch_outbox_event
alter column processAfter set not null;
-- change outbox event `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_outbox_event
drop primary key;
alter table hsearch_outbox_event
alter column id set data type varchar(36);
-- make this call if the adding constraint fails:
call sysproc.admin_cmd('reorg table hsearch_outbox_event');
alter table hsearch_outbox_event
add constraint hsearch_outbox_event_pkey primary key (id);
update hsearch_outbox_event
set id = regexp_replace(concat(rawtohex(generate_unique()), 'AAAAAA'), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\1-\2-\3-\4-\5')
where 1 = 1;
-- change agent `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_agent
drop primary key;
alter table hsearch_agent
alter column id set data type varchar(36);
-- make this call if the adding constraint fails:
call sysproc.admin_cmd('reorg table hsearch_agent');
alter table hsearch_agent
add constraint hsearch_agent_pkey primary key (id);
update hsearch_agent
set id = regexp_replace(concat(rawtohex(generate_unique()), 'AAAAAA'), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\1-\2-\3-\4-\5')
where 1 = 1;
-- adjust `processAfter` values for existing events so that older events (i.e. ones with smaller ID) will have older timestamp:
update hsearch_outbox_event
set processAfter = current_timestamp - numToDSInterval( (select max(id) from hsearch_outbox_event) - id, 'second' )
where processAfter is null;
alter table hsearch_outbox_event
modify (processAfter not null);
-- change outbox event `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_outbox_event
add tmp varchar(36) default REGEXP_REPLACE(RAWTOHEX(SYS_GUID()), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\1-\2-\3-\4-\5') not null;
alter table hsearch_outbox_event
drop column id;
alter table hsearch_outbox_event
rename column tmp to id;
alter table hsearch_outbox_event
add constraint hsearch_outbox_event_pkey primary key (id);
-- change agent `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_agent
add tmp varchar(36) default REGEXP_REPLACE(RAWTOHEX(SYS_GUID()), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\1-\2-\3-\4-\5') not null;
alter table hsearch_agent
drop column id;
alter table hsearch_agent
rename column tmp to id;
alter table hsearch_agent
add constraint hsearch_agent_pkey primary key (id);
-- adjust `processAfter` values for existing events so that older events (i.e. ones with smaller ID) will have older timestamp:
update hsearch_outbox_event
set processAfter = dateadd(ss, -(select max(id) from hsearch_outbox_event) + id, current_timestamp)
where processAfter is null;
alter table hsearch_outbox_event
alter column processAfter datetime not null;
-- change publox event `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_outbox_event
drop constraint if exists hsearch_outbox_event_pkey;
alter table hsearch_outbox_event
alter column id binary(255) not null;
alter table hsearch_outbox_event
add constraint hsearch_outbox_event_pkey primary key (id);
update hsearch_outbox_event
set id = convert(binary, newid())
where 1 = 1;
-- change agent `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_agent
drop constraint if exists hsearch_agent_pkey;
alter table hsearch_agent
alter column id binary(255) not null;
alter table hsearch_agent
add constraint hsearch_agent_pkey primary key (id);
update hsearch_agent
set id = convert(binary, newid())
where 1 = 1;
-- adjust `processAfter` values for existing events so that older events (i.e. ones with smaller ID) will have older timestamp:
update hsearch_outbox_event
set processAfter = dateadd(ss, -(select max(id) from hsearch_outbox_event) + id, current_timestamp)
where processAfter is null;
alter table hsearch_outbox_event
alter column processAfter set not null;
-- change outbox event `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_outbox_event
alter column id varchar(36) not null;
update hsearch_outbox_event
set id = random_uuid()
where 1 = 1;
-- change agent `id` column type to varchar and generate uuids to replace previous int values:
alter table hsearch_agent
alter column id varchar(36) not null;
update hsearch_agent
set id = random_uuid()
where 1 = 1;
Configuration changes
The configuration properties are for the most part backward-compatible with Hibernate Search 6.1.
However, some changes may have an impact on exotic configuration:
-
Configuration properties expecting references to "configurer" beans now accept multiple references, separated by commas. If your bean reference contains a comma, it may no longer be interpreted correctly.
The suggested workaround is to avoid using commas in bean names.
This affects the following configuration properties:
hibernate.search.backend.analysis.configurer
hibernate.search.backend.query.caching.configurer
**hibernate.search.mapping.configurer
API changes
The API is backward-compatible with Hibernate Search 6.1.
Some incubating API changed:
-
org.hibernate.search.engine.search.predicate.factories.NamedPredicateProvider` is now
org.hibernate.search.engine.search.predicate.definition.PredicateDefinition
. -
org.hibernate.search.engine.search.predicate.factories.NamedPredicateProviderContext` is now
org.hibernate.search.engine.search.predicate.definition.PredicateDefinitionContext
.
Parts of the API have been deprecated, and may be removed in the next major version:
-
SearchPredicateFactory#bool(Consumer)
, which enables the syntaxf.bool(b → { b.must(…); b.must(…); }
: use the syntaxf.bool().with(b → { b.must(…); b.must(…); })
instead, or (if possible) take advantage of the new.where(BiConsumer)
method in the Search Query DSL:.where((f, b) → { b.must(…); b.must(…); })
. -
SearchPredicateFactory#nested()
, which enables the syntaxf.nested().objectFieldPath("someField").nest(f.bool().must(…).must(…))
: use the syntaxf.nested("someField").must(…).must(…)
instead. -
SearchProjectionFactory#composite((Function, SearchProjection …)
/SearchProjectionFactory#composite((Function, ProjectionFinalStep …)
which enable the syntaxf.composite(list → …, <some projection>, <some projection>, …)
: use the (more flexible) syntaxf.composite().from(<some projection>, <some projection>, …).asList(list → …)
instead. -
SearchProjectionFactory#composite((Function, SearchProjection)
/SearchProjectionFactory#composite((Function, ProjectionFinalStep)
which enable the syntaxf.composite(p1 → …, <some projection>)
: use the (more flexible) syntaxf.composite().from(<some projection>).as(p1 → …)
instead. -
SearchProjectionFactory#composite((BiFunction, SearchProjection, SearchProjection)
/SearchProjectionFactory#composite((BiFunction, ProjectionFinalStep, ProjectionFinalStep)
which enable the syntaxf.composite((p1, p2) → …, <some projection>, <some projection>)
: use the (more flexible) syntaxf.composite().from(<some projection>, <some projection>).as((p1, p2) → …)
instead. -
SearchProjectionFactory#composite((TriFunction, SearchProjection, SearchProjection, SearchProjection)
/SearchProjectionFactory#composite((TriFunction, ProjectionFinalStep, ProjectionFinalStep, ProjectionFinalStep)
which enable the syntaxf.composite((p1, p2, p3) → …, <some projection>, <some projection>, <some projection>)
: use the (more flexible) syntaxf.composite().from(<some projection>, <some projection>, <some projection>).as((p1, p2, p3) → …)
instead. -
SearchSession#automaticIndexingSynchronizationStrategy(..)
and relatedAutomaticIndexingSynchronizationStrategy
/AutomaticIndexingSynchronizationConfigurationContext
/AutomaticIndexingSynchronizationStrategyNames
: useSearchSession#indexingPlanSynchronizationStrategy(..)
andIndexingPlanSynchronizationStrategy
/IndexingPlanSynchronizationStrategyConfigurationContext
/IndexingPlanSynchronizationStrategyNames
instead. Note new API is still incubating and might change. Also, configuration propertyhibernate.search.automatic_indexing.synchronization.strategy
is now deprecated in favor ofhibernate.search.indexing.plan.synchronization.strategy
SPI changes
The SPI is mostly backward-compatible with Hibernate Search 6.1.
Below are the most notable SPI changes:
-
PojoGenericTypeModel
no longer exists; its methods moved toPojoTypeModel
. -
org.hibernate.search.mapper.pojo.mapping.spi.AbstractPojoMappingInitiator#annotatedTypeDiscoveryEnabled
is deprecated. Use.annotationMapping().discoverAnnotationsFromReferencedTypes(…)
instead. -
org.hibernate.search.util.common.reflect.spi.ValueReadHandleFactory
is deprecated. Use/implementorg.hibernate.search.util.common.reflect.spi.ValueHandleFactory
instead. -
PojoAdditionalMetadataCollectorTypeNode#markAsEntity(String, org.hibernate.search.mapper.pojo.model.path.spi.PojoPathsDefinition)
is deprecated. UsePojoAdditionalMetadataCollectorTypeNode#markAsEntity(String, org.hibernate.search.mapper.pojo.model.path.spi.PojoPathDefinitionProvider)
instead. -
AutomaticIndexingStrategyStartContext
is deprecated. It was introduced by mistake and does not have any use.
Behavior changes
Due to bugfixes, parts of Hibernate Search now behave differently:
-
The boolean predicate,
SearchPredicateFactory#bool()
, when used without any clause, used to match no documents with the Lucene backend, but all documents with the Elasticsearch backend. A boolean predicate with no clause will now consistently match no documents regardless of the backend. -
API methods matching
*Async(..)
pattern (e.g.SearchWorkspace#purgeAsync()
) will no longer block if internal queues of operations are full, but will throwRejectedOperationException
instead.
Due to switching from new URL(..)
to new URI(..)
in the Hibernate Search internals indexing
behaviour of URL
properties might change. In particular malformed URLs won’t be accepted anymore and would result in
a runtime exception.
Due to some optimizations applied to bool queries, the resulting query might get replaced with a more straightforward query that returns the same results. Possible changes can include: some clauses can be rearranged, nested bool queries might be flattened, a bool query might be replaced with its clause.
A bool query with a single mustNot
clause and applied boost would implicitly add a must
with match_all
clause.