Skip to content

[BUG] Collection .contains() not working anymore #3618

@H-Lo

Description

@H-Lo

Observed vs. expected behavior

The query that I wrote in the past previously was working with older Hibernate, now is not working.

Steps to reproduce

In the repository classes there are 3 methods and none of those is working:

[UserRepositoryImpl] findByUserRole_1()

org.hibernate.query.SemanticException: Operand of 'member of' operator must be a plural path

[UserRepositoryImpl] findByUserRole_2() Alternate where clause also throws exception:

org.hibernate.query.QueryArgumentException:
Argument [ROLE_ADMIN] of type [com.thevegcat.app.config.UserRole]
did not match parameter type [java.util.Set (n/a)]

[UserRepository] findByUserRole_3() This one also used to work and now throws exception:

java.lang.ClassCastException:
class org.hibernate.metamodel.mapping.internal.BasicAttributeMapping cannot be cast to class
org.hibernate.sql.ast.tree.from.TableGroupJoinProducer
(org.hibernate.metamodel.mapping.internal.BasicAttributeMapping and
org.hibernate.sql.ast.tree.from.TableGroupJoinProducer are in unnamed module of loader 'app')

UserRole.java

public enum UserRole {
    ROLE_ADMIN,
    ROLE_ADVANCED,
    ROLE_EDITOR,
    ROLE_USER,
    ROLE_ANONYMOUS
}

User.java

@Entity 
public class User {
    // ...

	@Convert( converter = UserRolesConverter.class )
	@Column( columnDefinition = "TEXT" )
	private Set<UserRole> roles;

    // ...
}


UserRepositoryImpl.java

public class UserRepositoryImpl 
    // ...

    // case #1 - using user.roles.contains( userRole )
    public List<User> findByUserRole_1( final UserRole userRole ) {
        final QUser user = QUser.user;
        return 
            new JPAQueryFactory( this.entityManager )
                .selectFrom( user )
                .where(
                    new BooleanBuilder().and( user.roles.contains( userRole ) ).getValue()
                )
                .fetch();
    }

    // case #2 - using user.roles.any().eq( userRole )
    public List<User> findByUserRole_2( final UserRole userRole ) {
        final QUser user = QUser.user;
        return 
            new JPAQueryFactory( this.entityManager )
                .selectFrom( user )
                .where(
                    new BooleanBuilder().and( user.roles.any().eq( userRole ) ).getValue()
                )
                .fetch();
    }

    // ...
}

UserRepository.java

public interface UserRepository extends
    PagingAndSortingRepository<User, Integer>,
    CrudRepository<User, Integer>
{
    // ...

    @Query( "SELECT u FROM User u LEFT JOIN FETCH u.roles r WHERE :role IN ( r )" )
    List<User> findByUserRole_3( UserRole role );

    // ...
}

UserRolesConverter.java

public class UserRolesConverter implements AttributeConverter<Set<UserRole>, String>, Serializable {

	@Serial private static final long serialVersionUID = -6105356555706277280L;

	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 new ObjectMapper().writeValueAsString( attribute );
		}
		catch( final JsonProcessingException e ) {
			return null;
		}
	}

	@Override
	public Set<UserRole> convertToEntityAttribute( final String dbData ) {
		if( dbData == null ) {
			return Collections.emptySet();
		}
		try {
			final Set<UserRole> result = new ObjectMapper().readValue( dbData, TYPE_REFERENCE );
			if( result == null ) {
				throw new IllegalStateException( "This should never happen" );
			}
			return result;
		}
		catch( final JsonProcessingException e ) {
			throw new IllegalStateException( "JsonProcessingException: " + e.getMessage() );
		}
	}

}

Environment

OS: Windows 11 Pro 23H2 22631.2506 Windows Feature Experience Pack 1000.22677.1000.0
IDE: Eclipse STS Version: 4.20.1.RELEASE Build Id: 202310260003 Revision: b4f357cb0399519f520df4fc968315d5735367da
Spring: Spring Boot 3.1.5
Hibernate: Hibernate ORM 6.3.1.Final
Querydsl version: 5.0.0
Querydsl module: querydsl-apt, querydsl-jpa, com.querydsl.apt.jpa.JPAAnnotationProcessor
Database: mysql Ver 8.0.16 for Win64 on x86_64 (MySQL Community Server - GPL)
JDK: openjdk version "17.0.7" 2023-04-18 OpenJDK Runtime Environment Temurin-17.0.7+7 (build 17.0.7+7) OpenJDK 64-Bit Server VM Temurin-17.0.7+7 (build 17.0.7+7, mixed mode, sharing)

See also

https://stackoverflow.com/questions/77409442/querydsl-collection-contains

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions