Using enum property as ormlite column value instea

2019-05-31 05:29发布

问题:

@DatabaseField(dataType=DataType.ENUM_STRING,columnName=TIPO_FIELD_NAME)
private TipoPedido tipo;

public enum TipoPedido {
    REGISTARNOTIFICACAORESPOSTA("Registar Notificação Resposta",SIGLA_TIPO_REGISTARNOTIFICATIORESPOSTA);

    private String tipoName;


    private String tipoValue;

    TipoPedido(String tipoName,String tipoValue){
        this.tipoName=tipoName;
        this.tipoValue=tipoValue;
    }

    public String getTipoName(){
        return tipoName;
    }

    public String getTipoValue(){
        return tipoValue;
    }

}

Is it possible to use the tipoValue enum property as the value for the column instead of the ordinal?

Edit:here's what i did:

Created the MyEnumPersister class:

public class MyEnumPersister extends EnumStringType{

private static final MyEnumPersister singleTon = new MyEnumPersister();

/**
 * @param sqlType
 * @param classes
 */
protected MyEnumPersister() {

    super(SqlType.STRING, new Class<?>[] { Enum.class });
}

public static MyEnumPersister getSingleton() {
    return singleTon;
}


@Override
public Object javaToSqlArg(FieldType fieldType, Object obj) {

    return ((EstadoPedido)obj).getEstadoValue();
}


@Override
public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos)
        throws SQLException {

    return PedidoDTO.siglaEstadoPedidoComparator((String)sqlArg);

}

}

In javatoSqlArg i return directly the string corresponding to the estadoValue by using the getter inside the Enum. I assume to get it back to a Enum from the DataBase i will need to implement the sqlArgToJava method too, but i'm yet to build it.

edit2: Seems that when i do a query on the table that holds the data, the method javaToSqlArg gets called before the sqlArgToJava, why??? here's the query:

public List<PedidoDTO> getPendingRequests(){

    List<PedidoDTO> pendingReq=null;
    QueryBuilder<PedidoDTO, Integer> queryBuild=null;

    try {
        queryBuild=getHelper().getPedidosDao().queryBuilder();
        pendingReq=queryBuild.where().eq(PedidoDTO.ESTADO_FIELD_NAME, PedidoDTO.SIGLA_ESTADO_PENDENTE).query();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return pendingReq;
}

The obj value appears as "P" which was what i convert to sql when i inserted it in the Database. Doesnt make too much sense....

回答1:

By default ORMLite stores the string name of the enumerated type -- in your case it would store REGISTARNOTIFICACAORESPOSTA. You can override this behavior and store the ordinal value by using the ENUM_INTEGER data-type:

@DatabaseField(dataType=DataType.ENUM_INTEGER)
private TipoPedido tipo;

This will store the integer ordinal value in the database instead of the string. To quote the docs:

The string name is the default (and recommended over ENUM_INTEGER) because it allows you to add additional enums anywhere in the list without worrying about having to convert data later.

However, it seems like you want to store the tipoValue string from the enum instead. To do this you are doing to have to register a custom persister instead. See the docs about this:

http://ormlite.com/docs/custom-persister

This allows you to define specifically how you want to translate the Java field into the database representation, and vice versa. The two important methods are:

  • javaToSqlArg(...) which converts from the Java into the database format and
  • sqlArgToJava(...) which converts from the database back into Java.

You can extend BaseDataType and build the converter from the ground up or you can extend EnumStringType or StringType and just override the above important methods.



回答2:

I use the Enum.name() method to fill in Db columns and Enum.valueOf() to parse the value back. IMHO, I think the oridinals should never be used.

Also, you might want to take a look at this with regards to storing labels for enumeration values:

Is there an Enum string resource lookup pattern for Android?strong text