Skip to content

Method with @Condition acts strange when applying to source  #3459

Description

@foxii-cn

Expected behavior

when @Condition annotated method's parameter type is same to mapping source

    DTO toDto(E entity);

    @Condition
    default boolean isEntityAvailable(E entity) {
        if (entity == null) {
            return false;
        }
        return Persistence.getPersistenceUtil().isLoaded(entity);
    }

hope to generate something like

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        if ( !isEntityAvailable( entity ) ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        subCategoryDto.id( entity.getId() );
        subCategoryDto.name( entity.getName() );
        subCategoryDto.nick( entity.getNick() );
        return SubCategoryDto.build();
    }

or just ignore it

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        subCategoryDto.id( entity.getId() );
        subCategoryDto.name( entity.getName() );
        subCategoryDto.nick( entity.getNick() );
        return SubCategoryDto.build();
    }

Actual behavior

but now I got this

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();

        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.id( entity.getId() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.name( entity.getName() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.nick( entity.getNick() );
        }

        return SubCategoryDto.build();
    }

Steps to reproduce the problem

using JPA with Mapstruct
I have a base interface:

public interface EntityMapper<DTO extends EntityDto, E extends BasicEntity> {
    E toEntity(DTO dto);

    DTO toDto(E entity);

    // try to avoid JPA lazy loading issue
    // and this one worked well
    @Condition
    default boolean isCollectionAvailable(Collection<E> collection) {
        if (collection == null) {
            return false;
        }
        return Persistence.getPersistenceUtil().isLoaded(collection);
    }

    // try to avoid JPA lazy loading issue
    // got problem with this
    @Condition
    default boolean isEntityAvailable(E entity) {
        if (entity == null) {
            return false;
        }
        return Persistence.getPersistenceUtil().isLoaded(entity);
    }

    @MapperConfig(mappingControl = DeepClone.class,
                  mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_ALL_FROM_CONFIG)
    interface Config {
    }
}

and entity mappers:

@Mapper(config = EntityMapper.Config.class, uses = {SubCategoryMapper.class})
public interface ParentCategoryMapper extends EntityMapper<ParentCategoryDto, ParentCategory> {
}

@Mapper(config = EntityMapper.Config.class, uses = {ParentCategoryMapper.class})
public interface SubCategoryMapper extends EntityMapper<SubCategoryDto, SubCategory> {
}

and then I got this:

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        // Calling isEntityAvailable() so much times does not make any sense.
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.id( entity.getId() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.name( entity.getName() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.nick( entity.getNick() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.theOrder( entity.getTheOrder() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.icon( entity.getIcon() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.link( entity.getLink() );
        }
        // this is right
        if ( ParentCategoryMapper.isEntityAvailable( entity.getParentCategory() ) ) {
            subCategoryDto.parentCategory( ParentCategoryMapper.toDto( entity.getParentCategory() ) );
        }
        return SubCategoryDto.build();
    }

and what I want is:

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        if ( !isEntityAvailable( entity ) ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        subCategoryDto.id( entity.getId() );
        subCategoryDto.name( entity.getName() );
        subCategoryDto.nick( entity.getNick() );
        subCategoryDto.theOrder( entity.getTheOrder() );
        subCategoryDto.icon( entity.getIcon() );
        subCategoryDto.link( entity.getLink() );
        if ( ParentCategoryMapper.isEntityAvailable( entity.getParentCategory() ) ) {
            subCategoryDto.parentCategory( ParentCategoryMapper.toDto( entity.getParentCategory() ) );
        }
        return SubCategoryDto.build();
    }

MapStruct Version

MapStruct 1.6.0.Beta1

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions