Enum getting next code in Java

0

I have a class in java that one of its attributes is an enum and has the following values:

    HIPERTROFIA(1, "Hipertrofia"),
    DEFINICAO(2, "Definição"),
    RESISTENCIA(3, "Resistência"),
    OUTROS(4, "Outros");

When I send the value 0, it saves the value in the bank 1. When I send the value 1, it saves the value 2 in the bank and so on.

package br.com.academia.domain;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;

import org.hibernate.validator.constraints.Length;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;

import br.com.academia.domain.enums.StatusSerie;
import br.com.academia.domain.enums.TipoSerie;

@Entity
public class Solicitacao implements Serializable{
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = 
"seqSolicitacao")
@SequenceGenerator(name = "seqSolicitacao", sequenceName = 
"seq_id_solicitacao")
private Integer id;

private Integer tipoSerie;
//definição de todos os atributos

public Solicitacao() {
    super();
}


public Solicitacao((...), TipoSerie tipoSerie, (...)) {
    super();
    (...)
    this.tipoSerie = (tipoSerie == null) ? null : tipoSerie.getCodigo();
    (...)

}


//get e set

public TipoSerie getTipoSerie() {
    return TipoSerie.toEnum(tipoSerie);
}


public void setTipoSerie(TipoSerie tipoSerie) {
    this.tipoSerie = tipoSerie.getCodigo();
}

//get e set

}

The enum class:

package br.com.academia.domain.enums;

public enum TipoSerie {

HIPERTROFIA(1, "Hipertrofia"),
DEFINICAO(2, "Definição"),
RESISTENCIA(3, "Resistência"),
OUTROS(4, "Outros");

private int codigo;
private String descricao;

private TipoSerie(int codigo, String descricao) {
    this.codigo = codigo;
    this.descricao = descricao;
}

public int getCodigo() {
    return codigo;
}

public String getDescricao() {
    return descricao;
}

public static TipoSerie toEnum(Integer codigo)
{
    if(codigo == null)
    {
        return null;
    }

    for (TipoSerie serie: TipoSerie.values())
    {
        if(codigo.equals(serie.getCodigo()))
        {
            return serie;
        }
    }
    throw new IllegalArgumentException("Código inválido" + codigo);
}


}

Images that demonstrate the problem:

NoticethatinpostmanIsend0andthebanksaved1.

Myresource,whereIgettherequest

@RequestMapping(method=RequestMethod.POST)publicResponseEntity<Solicitacao>create(@Valid@RequestBodySolicitacaosolicitacao){solicitacao=solicitacaoService.save(solicitacao);URIuri=ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(solicitacao.getId()).toUri();
    return ResponseEntity.created(uri).build();
    }

In the service I only do a few sets in some values, but I do not make any changes to the type, which in turn, arrives in the wrong value service.

    
asked by anonymous 29.03.2018 / 15:59

2 answers

2

When Jackson is deserializing a JSON and its AUTO_DETECT_GETTERS and AUTO_DETECT_SETTERS properties are set to true (default value), its object's setters / getters are used for populat (if any).

Since your setter gets an enum of type TipoSerie , Jackson tries to use the number entered in his JSON to identify the corresponding element in > enum . The problem is that Jackson does not know that he should use the toEnum method since you did not inform him. Then it uses the standard form in this conversion, which is through the ordinal (when the value is a number). So when you enter 0, it returns the element HIPERTROFIA (index 0, code 1).

In order for it to use the toEnum method to deserialize JSON, you should note this method with @JsonCreator , so it will convert as expected.

Just as you need to tell it about deserializing JSON, you need to inform it about how to serialize the object. For this, you should use the @JsonValue annotation in your getCodigo method.

So, your enum TipoSerie would look like this:

public enum TipoSerie {

    HIPERTROFIA(1, "Hipertrofia"),
    DEFINICAO(2, "Definição"),
    RESISTENCIA(3, "Resistência"),
    OUTROS(4, "Outros");

    private int codigo;
    private String descricao;

    private TipoSerie(int codigo, String descricao) {
        this.codigo = codigo;
        this.descricao = descricao;
    }

    @JsonValue
    public int getCodigo() {
        return codigo;
    }

    public String getDescricao() {
        return descricao;
    }

    @JsonCreator
    public static TipoSerie toEnum(Integer codigo) {
        if(codigo == null) {
            return null;
        }

        for (TipoSerie serie: TipoSerie.values()) {
            if(codigo.equals(serie.getCodigo())) {
                return serie;
            }
        }
        throw new IllegalArgumentException("Código inválido" + codigo);
    }
}
    
30.03.2018 / 01:37
0

You can try using a Converter / AttributeConverter :

package br.com.academia.domain;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;

import org.hibernate.validator.constraints.Length;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;

import br.com.academia.domain.enums.StatusSerie;
import br.com.academia.domain.enums.TipoSerie;

@Entity
public class Solicitacao implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqSolicitacao")
    @SequenceGenerator(name = "seqSolicitacao", sequenceName = "seq_id_solicitacao")
    private Integer id;

    private TipoSerie tipoSerie;

    // Definição de outros atributos.

    public Solicitacao() {
        super();
    }

    public Solicitacao(/*...,*/ TipoSerie tipoSerie /*, ...*/) {
        super();
        // ...
        this.tipoSerie = tipoSerie;
        // ...
    }

    // Getters e setters.

    public TipoSerie getTipoSerie() {
        return tipoSerie;
    }

    public void setTipoSerie(TipoSerie tipoSerie) {
        this.tipoSerie = tipoSerie;
    }
}
public enum TipoSerie {
    HIPERTROFIA("Hipertrofia"),
    DEFINICAO("Definição"),
    RESISTENCIA("Resistência"),
    OUTROS("Outros");

    private final String descricao;

    private TipoSerie(String descricao) {
        this.descricao = descricao;
    }

    public int getCodigo() {
        return ordinal() + 1;
    }

    public String getDescricao() {
        return descricao;
    }

    public static TipoSerie toEnum(Integer codigo) {
        if (codigo == null) return null;
        try {
            return values()[codigo - 1];
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new IllegalArgumentException("Código inválido" + codigo, e);
        }
    }
}
import javax.persistence.Converter;
import javax.persistence.AttributeConverter;

@Converter(autoApply = true)
public class MapeadorTipoSerie implements AttributeConverter<TipoSerie, Integer> {

    @Override
    public Integer convertToDatabaseColumn(TipoSerie x) {
        return x.getCodigo();
    }

    @Override
    public TipoSerie convertToEntityAttribute(Integer y) {
        return TipoSerie.toEnum(y);
    }
}

Also note that you can take advantage of ordinal() that all enum has to derive the code.

    
29.03.2018 / 17:01