8

I have an enum:

public enum NotificationType {

    OPEN("open"),
    CLOSED("closed");

    public String value;

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

I want to pass the custom string open or closed rather than OPEN or CLOSED to entity. Currently, I've mapped it in the entity as follows:

@Enumerated(EnumType.STRING)
private NotificationType notificationType;

Which is the best way to store/ fetch enum value?

2
  • You can use a custom converter that internally builds a NotificationType from your value, since NotificationType.valueOf(String) is case sensitive. (This implies you still keep the enum type in your entity but have a custom value persisted in the database.) Commented Mar 3, 2020 at 5:45
  • Did you try to save with your mentioned configuration. I think it should work fine. Commented Mar 3, 2020 at 5:46

2 Answers 2

8

You can create a custom converter like this:

@Converter(autoApply = true)
public class NotificationTypeConverter implements AttributeConverter<NotificationType, String> {

    @Override
    public String convertToDatabaseColumn(NotificationType notificationType) {
        return notificationType == null
                ? null
                : notificationType.value;
    }

    @Override
    public NotificationType convertToEntityAttribute(String code) {
        if (code == null || code.isEmpty()) {
            return null;
        }

        return Arrays.stream(NotificationType.values())
                .filter(c -> c.value.equals(code))
                .findAny()
                .orElseThrow(IllegalArgumentException::new);
    }
}

And perhaps you'll need to remove annotation from your notificationType field so that this converter takes effect.

Sign up to request clarification or add additional context in comments.

4 Comments

If used frequently, i would also recommend to cache values of NotificationType in a Map to reduce the stream overhead.
@Glains yes, and I would move it to a method in the enum itself, that would take a string and return the enum
Thanks Kartik and glains, I tried to use AttributeConverter but i want to pass string value to jpa
@VanithaV that's what the convertToDatabaseColumn method above is doing - converting enum to string and passing it on to the persistence layer for storage
2

Yes, basically you have to develop a custom converter for that but I suggest you use Optional to avoid dealing with null and exceptions.

Add in NotificationType:

public static Optional<NotificationType> getFromValue(String value) {
   return Optional.ofNullable(value)
                  .flatMap(dv -> Arrays.stream(NotificationType.values())
                                    .filter(ev -> dv.equals(ev.value))
                                    .findFirst());
}

Create the required converter:

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;    

@Converter(autoApply = true)
public class NotificationTypeConverter implements AttributeConverter<NotificationType, String> {

   @Override
   public String convertToDatabaseColumn(NotificationType notificationType) {
      return null == notificationType ? null : notificationType.value;
   }

   @Override
   public NotificationType convertToEntityAttribute(String databaseValue) {
      return NotificationType.getFromValue(databaseValue)
                             .orElse(null);
   }
 }

And now, you only have to modify your model:

@Entity
@Table
public class MyEntity {

   @Convert(converter=NotificationTypeConverter.class)
   private NotificationType notificationType;
}  

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.