Hi! I’m trying to implement indexing against set of enums.
(Java 21 • Hibernate 7.3.0.Final • Hibernate Search 8.3.0.Final)
public enum UserRole {
ROLE_ADMIN,
ROLE_EDITOR...
}
@Column( columnDefinition = "TEXT" )
@Convert( converter = UserRolesConverter.class )
// @Enumerated(EnumType.STRING)
@PropertyBinding(
binder = @PropertyBinderRef( type = UserRolesPropertyBinder.class )
)
private Set<UserRole> roles;
Enums are stored as a string rather than a collection in addtional table.
The problem is I don’t know how to add the bridge to the context.
public class UserRolesPropertyBinder
implements PropertyBinder
{
@Override
public void bind( final PropertyBindingContext context ) {
context.dependencies().useRootOnly();
final UserRolePropertyBridge userRolesBridge =
new UserRolePropertyBridge(
context
.indexSchemaElement()
.field(
context.bridgedElement().name(),
f -> f.asString()
)
.toReference()
);
//-------------------------------------------------------
context.bridge( ??????, userRolesBridge );
//-------------------------------------------------------
}
private static class UserRolePropertyBridge
implements
PropertyBridge<Set<UserRole>>
{
private final IndexFieldReference<String> stringField;
private UserRolePropertyBridge(
final IndexFieldReference<String> stringField
) {
this.stringField = stringField;
}
@Override
public void write(
final DocumentElement target,
final Set<UserRole> userRoles,
final PropertyBridgeWriteContext context
) {
for( final UserRole role : userRoles ) {
target.addValue( this.stringField, role.name() );
}
}
}
}
Tried to find solution to employ TypeReference because Jackson has something similar which I use in converters, but couldn’t find any appropriate TypeReference to use here.
Once I fix ths, usage would be:
pf.match()
.field( Field.USER_ROLES.getFieldName() ) // -> "roles"
.matching( userRole )
.toPredicate();
Is there a chance this solutio might work? Or I missed it in total?
Thanks!
P.S. Just for the record, another question of mine from the past, with similar theme:
Here is the converter just to provide all the information.
public class UserRolesConverter
implements
AttributeConverter< Set<UserRole>, String >,
Serializable
{
public static final TypeReference< Set<UserRole> > TYPE_REFERENCE =
new TypeReference<>() {
//
};
@Override
public String convertToDatabaseColumn(
final Set<UserRole> attribute
) {
if (attribute == null || attribute.isEmpty()) {
return null;
}
try {
return
JacksonUtil.OBJECT_WRITER
.writeValueAsString( attribute );
}
catch( final JsonProcessingException e ) {
return null;
}
}
@Override
public Set<UserRole> convertToEntityAttribute(
final String dbData
) {
if( dbData == null ) {
return Collections.emptySet();
}
try {
return
JacksonUtil.OBJECT_READER
.forType( TYPE_REFERENCE )
.readValue( dbData );
}
catch( final JsonProcessingException e ) {
throw new IllegalStateException(
"JsonProcessingException: " + e.getMessage()
);
}
}
}