Reputation: 6081
I have an Ink
class with a fixed set of constants. They never change and I don't want to store this class as a table.
public final class Ink {
public static final Ink Y = new Ink(91001, 'y', 90.70, -5.23, 94.37), "Yellow");
public static final Ink M = new Ink(92001, 'm', 48.19, 72.01, -1.78), "Magenta");
public static final Ink C = new Ink(93001, 'c', 56.46, -41.00, -43.50), "Cyan");
public static final Ink K = new Ink(94001, 'k', 18.64, 1.80, 5.21), "Black");
public int code;
public static Ink forCode(int code) {
//...
}
//...
}
Other classes can have Ink ink
or Collection<Ink> inks
fields, but every ink
instance must be mapped as a simple integer column with its code
value only. Code
is not a foreign key or something – it is a simple integer value from which I can always obtain Ink
instance.
@Entity
public class Order {
//...
@OneToMany
public Set<Ink> inks;
//...
}
I can use converter to restore Ink
class by its code
and back
@Converter(autoApply = true)
public class InkConverter implements AttributeConverter<Ink, Integer> {
@Overrcodee
public Integer convertToDatabaseColumn(Ink ink) {
return ink.code;
}
@Overrcodee
public Ink convertToEntityAttribute(Integer code) {
return Ink.forCode(code);
}
}
but the question is:
how to prevent Hibernate from mapping the class as a table and still have a class field loaded from its code
column?
Upvotes: 0
Views: 61
Reputation: 23226
Firstly, you can create an Enum to represent Ink instances. If you can change the column to store a char reference (Y,M,C,K) rather than code this would the easiest solution. If not then you can use a converter as you have suggested to convert from the code to the Enum instance.
public Enum Ink {
Y = new Ink(91001, 'y', 90.70, -5.23, 94.37), "Yellow");
M = new Ink(92001, 'm', 48.19, 72.01, -1.78), "Magenta");
C = new Ink(93001, 'c', 56.46, -41.00, -43.50), "Cyan");
K = new Ink(94001, 'k', 18.64, 1.80, 5.21), "Black");
.....
private static Ink (...) {
...
}
}
Mappings would be like the below if you save Y,M,C,K. If you must save the code then add the necessary converters (http://www.nurkiewicz.com/2013/06/mapping-enums-done-right-with-convert.html)
@Entity
public class Order {
@ElementCollection
@CollectionTable(...)
@Enumerated(EnumType.STRING)
public Set<Ink> inks;
@Enumerated(EnumType.STRING)
private Ink ink;
}
Upvotes: 1
Reputation: 1055
As you store the ink in your Java code. So you should implement the load action all by your self. First, you can prevent Hibernate from mapping the class as a table by annotation @Transient. And then you can handle the load action after order loaded:
public interface Inked {
getCode();
setInk(Ink ink);
}
public abstract class AbstractEntity {
@PostLoad
public void loadInk() {
if(this instanceof Inked){
Inked inked = (Inked) this;
inked.setInk(Ink.forCode(getCode()));
}
}
}
@Entity
public class Order extends AbstractEntity implement Inked {
//...
public Integer code;
@Transient
public Ink ink;
//...
}
Upvotes: 1