Modelmapper ne reconnaît pas les UUID

Oct 26 2020

Hé, je viens de commencer à jouer avec Modelmapper pour mapper les enregistrements jOOQ aux POJO.

Ceci est le schéma de la table dont je tente de convertir les enregistrements (Postgresql)

CREATE TABLE IF NOT EXISTS actor(
    actor_id UUID DEFAULT uuid_generate_v4(),
    first_name VARCHAR(256) NOT NULL,
    last_name VARCHAR(256) NOT NULL,
    PRIMARY KEY(actor_id)
);

Voici à quoi ressemble le POJO:

@JsonDeserialize(builder = Actor.Builder.class)
public class Actor {
    private final UUID actorId;
    private final String firstName;
    private final String lastName;

    private Actor(final Builder builder) {
        actorId = builder.actorId;
        firstName = builder.firstName;
        lastName = builder.lastName;
    }

    public static Builder newBuilder() {
        return new Builder();
    }

    public UUID getActorId() {
        return actorId;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static final class Builder {
        private UUID actorId;
        private String firstName;
        private String lastName;

        private Builder() {
        }

        public Builder withActorId(final UUID val) {
            actorId = val;
            return this;
        }

        public Builder withFirstName(final String val) {
            firstName = val;
            return this;
        }

        public Builder withLastName(final String val) {
            lastName = val;
            return this;
        }

        public Actor build() {
            return new Actor(this);
        }
    }
}

Je crée un ModelMapperbean dans mon application et j'y enregistre un UUIDconvertisseur.

   @Bean
    public ModelMapper modelMapper() {
        final ModelMapper mapper = new ModelMapper();
        Provider<UUID> uuidProvider = new AbstractProvider<UUID>() {
            @Override
            public UUID get() {
                return UUID.randomUUID();
            }
        };

        final Converter<String, UUID> uuidConverter = new AbstractConverter<>() {
            @Override
            protected UUID convert(final String source) {
                return UUID.fromString(source);
            }
        };
        mapper.createTypeMap(String.class, UUID.class);
        mapper.addConverter(uuidConverter);
        mapper.getTypeMap(String.class, UUID.class).setProvider(uuidProvider);


        mapper.getConfiguration()
                .setSourceNameTokenizer(NameTokenizers.UNDERSCORE)
                .addValueReader(new RecordValueReader())
                .setDestinationNameTransformer(NameTransformers.builder("with"))
                .setDestinationNamingConvention(NamingConventions.builder("with"));
        mapper.validate();
        return mapper;
    }

J'utilise ensuite le mappeur de modèle pour mapper le ActorRecordcode généré automatiquement par jOOQ vers le POJO

public Optional<Actor> getActor(final UUID actorId) {
    return Optional.ofNullable(dsl.selectFrom(ACTOR)
            .where(ACTOR.ACTOR_ID.eq(actorId))
            .fetchOne())
            .map(e -> modelMapper.map(e, Actor.Builder.class).build());
}

Cela fonctionne sauf que l'UUID est toujours null. Par exemple:

{"actor_id":null,"first_name":"John","last_name":"Doe"}

Cependant, lorsque je change les éléments suivants dans Builder:

    public Builder withActorId(final String val) {
        actorId = UUID.fromString(val);
        return this;
    }

Ça marche! Malheureusement, cela ne fonctionne pas avec une méthode surchargée:

    public Builder withActorId(final String val) {
        actorId = UUID.fromString(val);
        return this;
    }

    public Builder withActorId(final UUID val) {
        actorId = val;
        return this;
    }

Comme cela revient également null.

Vous pouvez voir à partir du code jOOQ généré automatiquement qu'il devrait gérer un UUID:

/**
 * The column <code>public.actor.actor_id</code>.
 */
public final TableField<ActorRecord, UUID> ACTOR_ID = createField(DSL.name("actor_id"), org.jooq.impl.SQLDataType.UUID.nullable(false).defaultValue(org.jooq.impl.DSL.field("uuid_generate_v4()", org.jooq.impl.SQLDataType.UUID)), this, "");

Je ne suis pas sûr de ce qui me manque exactement. Je ne souhaite pas créer de convertisseur personnalisé pour chacune de mes entités car j'en ai beaucoup et elles contiennent toutes (au moins 1) UUID. Idéalement, je veux configurer le ModelMapperpour savoir UUIDet chaque fois qu'il en voit un, il peut le gérer. Merci!

REMARQUE : j'ai également essayé cela avec l' @Dataobjet Lombok et cela ne fonctionne pas non plus.

@JsonDeserialize(builder = Actor.ActorBuilder.class)
@Data
public class Actor {
    private UUID actorId;
    private String firstName;
    private String lastName;

    @JsonPOJOBuilder(withPrefix = "with")
    public static class ActorBuilder {

    }
}

Réponses

fr3ddie Nov 08 2020 at 11:15

UUID.fromString(val)n'est pas autorisé. J'ai eu le même problème hier. Essayez de mettre l'UUID dans les configurations ModelMapper converti en String.