Spring Boot: desativa a busca de PersistentBag programaticamente

Nov 13 2020

Eu tenho uma entidade no Spring Boot que se parece com isso:

@Entity
@Table(name = "race_class")
@Getter @Setter
public class RaceClass
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer dbid;

    private String name;

    private String colorHexcode;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "raceClass", cascade = CascadeType.ALL)
    private List<Entry> entries;
}

No meu serviço já tenho um método, que busca todas as entradas da raceclass adicionalmente. Que se parece com isso:

public List<RaceClassDto> getClassesEntries( int eventDbid )
{
    return this.raceClassRepo.findByEventDbid( eventDbid )
        .stream()
        .map( c -> addEntriesToRaceClass( eventDbid, c ) )
        .map( raceClassMapper :: mapToDto )
        .collect( Collectors.toList() );
}

O mapeador é assim:

public RaceClassDto mapToDto( RaceClass raceClass )
{
    return modelMapper.map ( raceClass, RaceClassDto.class );
}

Agora, eu quero ter um segundo método, que não busca as entradas automaticamente. Mas exatamente aqui está o meu problema. O novo método seria assim:

public List<RaceClassDto> getClasses( int eventDbid )
{
    return this.raceClassRepo.findByEventDbid( eventDbid )
            .stream()
            .map( raceClassMapper :: mapToDto )
            .collect( Collectors.toList() );
}

Mas as entradas serão buscadas mesmo assim, porque getEntries () será chamado no DTO-Mapper, que executa as consultas selecionadas automaticamente e preenche o contêiner de entradas. Como é possível desativar programaticamente a sincronização automática do PersistentBag apenas para o método getClassesEntries ()?

Respostas

1 jccampanero Nov 13 2020 at 20:50

Acho que você não pode desativar programaticamente a resolução de relacionamento.

Uma abordagem melhor será definir um novo método em seu mapeador, nomeá-lo mapToDTOWithoutResolvingEntriese não resolver o relacionamento nesse método.

Para seus comentários, se você estiver usando o ModelMapper, em seu caso de uso específico, talvez você possa pular a entriespropriedade do seu DTO.

Por favor, tente algo como o seguinte:

public RaceClassDto mapToDTOWithoutResolvingEntries( RaceClass raceClass) {
    return modelMapperWithoutResolvingEntries
      .map ( raceClass, RaceClassDto.class );
}

Onde modelMapperWithoutResolvingEntriesé o mesmo que modelMappervocê definiu antes com o seguinte mappingadicionado:

ModelMapper modelMapperWithoutResolvingEntries = new ModelMapper();
modelMapperWithoutResolvingEntries
    .addMappings(mapper -> mapper.skip(RaceClassDto::setEntries));

Em TypeMapvez disso, você pode usar create a , ele deve se comportar da mesma forma.

Você tem outras alternativas. Por exemplo, você pode fornecer o seu próprio PropertyMap(por favor, consulte o javadoc relevante e como eles sobrescrevem o configuremétodo), ou talvez até mesmo um Converter.

1 MAnouti Nov 13 2020 at 20:50

Acredito que modelMapperesteja vindo da biblioteca ModelMapper , então, neste caso, você poderia dizer a ela para pular o mapeamento das entradas, conforme abordado nesta pergunta .

Caso contrário, você provavelmente pode copiar os dados do objeto carregado JPA em outro objeto, excluindo aqueles dados buscados lentamente.