Imagine, your JavaEE oder Spring application has to save a EnumSet into a database JPA/Hibernate. The easiest way to do, is to create a table/row like this:
@Entity
@Setter
@Getter
public class Person {
/* ... */
@ElementCollection
@Enumerated(EnumType.STRING)
@CollectionTable(name = "SET_ATTRIBUTE")
private Set<EnAttribute> setOfAttributes;
/* ... */
}
This simple implementation allows us to use the JPA-QL languange, in order to filter for Person entries by giving a enum attribute. This might be our finder, that resides in a SpringJPA reporistory (works similar in JavaEE):
public interface PersonRepo extends CrudRepository<Person, Long> {
@Query("SELECT pers FROM Person pers WHERE :pAttr MEMBER OF pers.setOfAttributes ")
List<Person> findPersonBy (final EnAttribute pAttr);
}
But sometimes, you may be envisaged with a low performance of the above shown filter, so you might get rid of the SET_ATTRIBUTE table and the implicit JOIN operation, by using a simple bitfield instead of a table. If the domain of the EnAttribute does not hold more that 30 enum-items, you may try to translate the enumeration ordinal number into a position of a number like, i.e. an integer.
Fortunately JPA comes with an attribute-converter, that can be used like this:
@Entity
@Setter
@Getter
public class Person {
/* ... */
@Convert(converter = ConverterSetOfPersAttribute.class)
private Set<EnAttribute> setOfAttributes;
/* ... */
}
This works perfectly for saving and loading complete (Entity)Sets into/from the database into your application by simply reading one db row. But there is one problem, my selected datatype may be wrong. I received immediately an exception, when my application was starting an JPA tried to translate the finder into the postgres database. I received an exception containing a similar message to "bytea is not compatible with integer".
This message make sense, JPA/Hibernate recognizes the absense of a SET_ATTRIBUTE and translates the member-of expression also to a numeric expression and expect it to be a array of bytes (bytea). So i guess i was choosing the wrong target datatype (integer).
My questions:
- Shall i use one of both EnumSet implementation (for small and lage enumsets) or what type should i use to save the set as a cardinal into the database ?
- I know, that postgres comes with the support of enumeration. Will the postgres hibernate implementation support these features in future ?
Thank you all!
I tried to change the set-representation in the database and expected the JPA-QL finder is still working, but i must be wrong.