Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to emulate Attribute Converter in JPA <= 2.0?

JPA 2.1 introduced a nice new feature Attribute Converter - see an article e.g. here: http://www.thoughts-on-java.org/jpa-21-how-to-implement-type-converter/

It allows you to have an attribute of a certain type and store it as something else in the database column. E.g. you have an entity with a field color which is of a type java.awt.Color but you want it to be stored in the database as a String, such as RED or WHITE.

@Entity
class Tag {
    String name;
    java.awt.Color color; // I want it to be stored as a different type
}

Is there a way of obtaining the similar result in JPA <= 2.0? I want to do it for a type which is not an enum.

We do not distinguish between the business domain layer and the @Entity classes. Of course I can imagine many working solutions if there were some kind of mapping between them. What I am searching for is a solution where we use directly the @Entity classes themselves in the business domain layer.

like image 531
Honza Zidek Avatar asked Jul 02 '15 16:07

Honza Zidek


2 Answers

What I suggest is making this column @Transient and add another @Column that will be the String value of the awt.Color, use getters and setters as the converters.

Your class will be as this:

@Transient
java.awt.Color color;
@Column
String colorField;

Every time you use your Color use the setter, this setter will decode the color and add this to the colorField field.

public setColor(java.awt.Color color){
  this.colorField = color.toString();
  this.color = color;
}
like image 116
Koitoer Avatar answered Oct 29 '22 11:10

Koitoer


As i mention in comment, in system which I was working, custom non-entity class was serialized to byte array and put to db as blob, and deserialize before use.

field was mapped as:

 @Column(name = "data")
 private byte[] data;

then we had util class with two static methods

public static byte[] serialize(Object object) throws IOException,
            ClassNotFoundException {
        // Serialize to a byte array
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(object);
        out.close();

        // Get the bytes of the serialized object
        byte[] buf = bos.toByteArray();
        return buf;
    }

    public static Object deserialize(byte[] data) throws IOException,
            ClassNotFoundException {
        // Deserialize from a byte array
        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(
                data));
        Object o = in.readObject();
        in.close();
        return o;
    }

now you could create transient getter and setter and use derialize and deserialize do translate from and to your class

not sure is it recommended solution, but this is copied straight from existing system

like image 25
user902383 Avatar answered Oct 29 '22 10:10

user902383