How to serialize and deserialize multi argument enum in Java using JPA 2.1 or lower (Postgres)

590 Views Asked by At

    public enum CameraType {
    
    CAMERA(false, false, "External lens ", ""),
    
    
    CameraType{
                boolean collector,
                boolean hidden,
                String description
            ) {
            this.collector = collector;
            this.granular = hidden;
            this.description = description;
            } // end ctor
           
           public void setHide(boolean hidden) {
               this.hide = hidden;
           }
    
    } // end enum

I have few Instance of CameraType.

I have a setter for "hidden" property which on certain condition is set to true or false.

Now I serialize CameraType with few other fields inside SecurityEntity.

```
@Entity
@Table
public class Security {

 Few more fields...

@Enumerated(EnumType.STRING)
    @Column(nullable = false)
private CameraType cameraType

And other fields...
}
```

When I deserialize the value of "hidden" field is always false. If I understand correctly, during deserialization ctor is called and default is assigned.

Is there a way I can retain the value of "hidden" field(true or false) after deserialization per instance of CameraType.

I am using Postgres DB 10.

enter code here

Please Please help. I am out of clues.

2

There are 2 best solutions below

1
jurez On BEST ANSWER

By definition, enums are immutable elements of a fixed set. Because of this, to represent an enum value you just need its name. That's exactly what JPA does during serialization/deserialization.

You are trying to violate the rules. While Java allows you to treat enums almost as plain objects, JPA treats them according to what they are supposed to be. That's why your code is not working.

You can either:

  • make CameraType into a class and serialize it as such, or
  • split CameraType into two parts, for example enum CameraType (immutable) and class CameraConfig (with all the mutable fields)
0
de-jcup On

The former answer is correct : enums must be immutable and dividing parts into immutable and mutable data is a good choice.

One addition here: using the enum values for database storage is often not a good choice, because when another developer decides to refactor the enum names and you are after this reading old entries from database, you got a crashing application...

So I would suggest to use javax.persistence.AttributeConverter to deserialize/serialize an enum in a specific and rename save way.

Here a very simple example with an enum called MyDefinition:

enum MyDefinition{

   ONE("def_one"),
   TWO"def_two"),
   THREE("def_three"),
   
   ;
   
   private String id;

   private MyDefinition(String id){
      this.id=id;
   }

   public String getId(){
      return id;
   }

    public static MyDefinition fromId(String id) {
        for (MyDefinition definition : MyDefinition.values()) {
            if (definition.id.equals(id)) {
                return definition;
            }
        }
        return null;
    }


}

Here the converter:

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

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

    @Override
    public String convertToDatabaseColumn(MyDefinition attribute) {
       if (attribute == null){
           return null;}
       }
       return attribute.getId();
    }

    @Override
    public MyDefinition convertToEntityAttribute(String dbData) {
        return MyDefinition.fromId(dbData);
    }
 
 

So we can use the ids for database. A renaming of the enum names will no longer lead to a crashing application when reading old data.