7
votes

I've never really made use of Java enum classes before for constant values, I've typically used the "public final" approach in the past. I've started using an enum now and I'm overriding the toString() method to return a different value than the enum name.

I have some JPA code in which I'm creating a TypedQuery with named parameters, one of which is a String representation of the enum value. If I merely set the parameter using Status.ACTIVE, I get the proper "A" value, but an exception is thrown because it's type is actually Status rather than String. It only works if I explicitly call the toString() method. I thought that simply overriding the toString() method would result in a String type being returned, no matter what the class type was.

This is the enum:

public enum Status {
    ACTIVE ("A"),
    PENDING ("P"),
    FINISHED ("F");

    private final String value;

    Status(String value) {
        this.value = value;
    }

    public String toString() {
        return value;
    }
};

This is the TypedQuery:

    TypedQuery<MechanicTimeEvent> query = entityManager().createQuery("SELECT o FROM MechanicTimeEvent o WHERE o.id.mechanicNumber = :mechanicNumber AND o.id.status = :status", MechanicTimeEvent.class);
    query.setParameter("mechanicNumber", mechanicNumber);
    query.setParameter("status", Status.ACTIVE.toString());
6
Can add the mapping of that field to the question?Augusto
If you're looking for a more concise way to write it, query.setParameter("status", Status.ACTIVE+""); will work.Eric
Is the field in your @Entity of type Status and is it annotated with @Enumerated(EnumType.STRING)? If so you should be able to use enums in queries just fine.Tomasz Nurkiewicz
Here and here similar problems and answers have been discussed already.A.H.
The field in my @Entity is merely a String, but it will only ever be a value of A, P or F, so I created an enum for those values so that in the code, I could use something like Status.ACTIVE and it would be more descriptive. I figured overriding the toString() method to return the actual value would return a String type without explicitly calling toString().Patrick Grimard

6 Answers

6
votes
public enum Status {
    ACTIVE,
    PENDING,
    FINISHED;

    @Override
    public String toString() {
        String name = "";
        switch (ordinal()) {
        case 0:
            name = "A";
            break;
        case 1:
            name = "P";
            break;
        case 2:
            name = "F";
            break;
        default:
            name = "";
            break;
        }
        return name;
    }
};
3
votes

Is the field status of the MechanicTimeEvent bean an enum type? If not, I would suggest to change it to the enum type Status.

You can annotate it with @Enumerated(EnumType.STRING)

Furthermore I would suggest to remove the value part of your enum and just use the names like:

public enum Status {
   ACTIVE,
   PENDING,
   FINISHED;
}
3
votes

If I understand your question correctly, You should do the enum mapping other way around. In this way states are stored as state and JPA would process the enum based on its name A,P, F).

public enum Status {
    A("ACTIVE"),
    P("PENDING"),
    F("FINISHED");

In this way you can just pass Status without invoking the toString() method to JPA. The .name() method on the ENUM will be invoked automatically to get the status code for persistence.

0
votes

toString is just an ordinary method in Object that is explicitly called by some methods like PrintStream.println (remember System.out.println) or considered during concatenation using the + operator. Not every method needs to implement this behavior.

I'd suggest you use a more descriptive method name like getValue and call it explicitly instead of override toString

0
votes

This or you simply implement a getter for the value:

public String getValue()

And you call it in your code:

query.setParameter("status", Status.ACTIVE.getValue());
-1
votes
java.lang.Enum said clearly:
 /**
 * Returns the name of this enum constant, exactly as declared in its
 * enum declaration.
 * 
 * <b>Most programmers should use the {@link #toString} method in
 * preference to this one, as the toString method may return
 * a more user-friendly name.</b>  This method is designed primarily for
 * use in specialized situations where correctness depends on getting the
 * exact name, which will not vary from release to release.
 *
 * @return the name of this enum constant
 */
 public final String name()

just like the loft say ,you can use "name" method to get the name. also you can use toString() method.

of course it is just name of this enum constant.