0

I want to have a simple parent children relationship but somehow it does not work and I don't get what is missing.

Parent Mapper Interface (adding uses = {LayerMapper.class} does not change anything):

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
@DecoratedWith(MlpConfigMapperDecorator.class)
public interface MlpConfigMapper {

    @Mapping(target = "epochNumber", source = "epochs")
    @Mapping(target = "activationFunction", ignore = true)
    MlpConfig toEntity(CustomMlpConfigRequest mlpConfigDto);
}

Parent decorator according to this answer (https://stackoverflow.com/a/60217018/10565504):

public abstract class MlpConfigMapperDecorator implements MlpConfigMapper {

    @Autowired
    @Qualifier("delegate")
    private MlpConfigMapper delegate;

    @Autowired
    private ActivationFunctionService activationFunctionService;

    @Override
    public MlpConfig toEntity(CustomMlpConfigRequest mlpConfigDto) {

        MlpConfig mlpConfig = delegate.toEntity(mlpConfigDto);

        mlpConfig.setActivationFunction(activationFunctionService.findByType(mlpConfigDto.getActivationFunction()));

        return mlpConfig;
    }
}

The Parent DTO:

public class CustomMlpConfigRequest {

    private String name;

    private String description;

    private int batchSize;

    private int epochs;

    private List<LayerDto> layers;

    private String activationFunction;

}

The Child DTO:

public class LayerDto {

    public String type;
    public int orderNumber;
    public int neuronsNumber;

}

Parent Entity:

public class MlpConfig {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;

    private String description;

    private int batchSize;

    private int epochNumber;

    @JoinColumn(nullable = false, name = "activationFunction_id")
    @ManyToOne(fetch = FetchType.LAZY)
    private ActivationFunction activationFunction;

    @JsonManagedReference
    @Column(nullable = false)
    @OneToMany(mappedBy = "mlpConfig", cascade = CascadeType.ALL)
    private List<Layer> layers;

    @ManyToOne(fetch = FetchType.LAZY)
    private User user;

    private Date lastUpdated;
}

Child Entity:

public class Layer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private ELayer type;

    private int neuronsNumber;

    private int orderNumber;

    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @ManyToOne(fetch = FetchType.LAZY, optional=false)
    @JoinColumn(name = "mlpConfig_id", nullable=false)
    @JsonBackReference
    private MlpConfig mlpConfig;
}

Generated Child Entity Mapper Method (setChildren or setMlpConfig() in my case is missing):

@Override
public LayerDto layerToDto(Layer layer) {
    if ( layer == null ) {
        return null;
    }

    LayerDto layerDto = new LayerDto();

    if ( layer.getType() != null ) {
        layerDto.setType( layer.getType().name() );
    }
    layerDto.setOrderNumber( layer.getOrderNumber() );
    layerDto.setNeuronsNumber( layer.getNeuronsNumber() );

    return layerDto;
}

How do I get the mapper to set the parent in the child?

CptDayDreamer
  • 1,526
  • 6
  • 25
  • 61

2 Answers2

0

do you have Layer toEntity(LayerDto layerDto);

Also, on setter of layers on entity class, you should say, layers.forEach (layer -> layer.setmlpConfig(this));

Did you do that setting job? If you don't, layers of mplConfig entity can always be null when you try to get it.

  • Yes I have the toEntity method sorry. Why for each? I'm using lombok for getter and setter so everything should be fine. On Layer entity side the following exists: `public void setMlpConfig(MlpConfig mlpConfig) { this.mlpConfig = mlpConfig; }` – CptDayDreamer Jul 28 '20 at 10:59
  • I think the problem is that in LayerDTO no correspondence to `MlpConfig` or `CustomMlpConfigRequest` is existing. – CptDayDreamer Jul 28 '20 at 11:01
  • i think you should rewrite setter of layers. Since LayerDto (of course) do not have MlpConfig, its MlpConfig is always null . So on setter of layers, if you say this "layers.forEach (layer -> layer.setmlpConfig(this));", their MlpConfig will not be null again , i think – fatma zehra güç Jul 28 '20 at 11:07
  • In which entity? And why of course? I'm still not getting the point. Where is the problem? – CptDayDreamer Jul 28 '20 at 11:09
  • i am not sure if this is your problem but i had the same problem once, and this was the answer for me. Can you please try it. – fatma zehra güç Jul 28 '20 at 11:09
  • in mlpConfig entity, you should say layers.forEach ... on setLayers method. – fatma zehra güç Jul 28 '20 at 11:10
  • I've tried but it has the same behaviour. Still no setter generated in the auto generated mapper of `layerToEntity` – CptDayDreamer Jul 28 '20 at 11:14
  • on layerToEntity method, it is normal if there is no setter for parent. Because LayerDto does not have parent. And it should not already. You should try create MlpConfig entity withLayers to see if Layers have MlpConfig id or not. – fatma zehra güç Jul 28 '20 at 11:28
  • What? Why? I know everything is mapped fine and the MlpConfig object does contain everything that it should after the mapping. Only the reference in the layers of the MlpConfig object to MlpConfig is missing. – CptDayDreamer Jul 28 '20 at 11:51
0

In the end I fixed it myself. I don't know if it is best practice and probably the mapper should do it without manual help but at least it works:

public abstract class MlpConfigMapperDecorator implements MlpConfigMapper {

    @Autowired
    @Qualifier("delegate")
    private MlpConfigMapper delegate;

    @Autowired
    private ActivationFunctionService activationFunctionService;

    @Override
    public MlpConfig mlpConfigToEntity(CustomMlpConfigRequest mlpConfigDto) {

        MlpConfig mlpConfig = delegate.mlpConfigToEntity(mlpConfigDto);

        mlpConfig.setActivationFunction(activationFunctionService.findByType(mlpConfigDto.getActivationFunction()));
        
        //this is the difference. I set the config for the layer manually
        mlpConfig.getLayers().forEach(e -> e.setMlpConfig(mlpConfig));

        return mlpConfig;
    }
}
CptDayDreamer
  • 1,526
  • 6
  • 25
  • 61