As it was discussed in one of the previous posts JPA: Mapping Enums the right way, JPA 2.1 standardized AttributeConverters, which can, for example, be used to map Java enums in more controlled/predicted way. Let's quickly recap how it can be done.
To be able to map this enum into the integer column of database table, which would match enum's id we need to create an attribute converter similar to the next one:
Having such converter we can annotate the corresponding filed in the entity with the @Covert annotation and that's it! This look pretty easy and doesn't require a lot of code.
What if we have one more enum? For example let's add AddressType. The process would be very similar - we need to create an attribute converter class and add @Covert annotation on the corresponding filed.
But what if we have even more enums that should be mapped this way? This would mean that we need to write a converter for each enum and basically duplicate the same logic in each of them...
Now let's make sure that our enums implement this interface:
Now that our enums have something in common we can generalize the operation of finding an enum value by id. For example next utility static method can be introduced:
But it would mean that an array of enums is needed to be passed all the time to make a call (for example like this - Utils.findByID( dbData, PhoneType.values() )). This can be solved with usage of Class#enumConstants method. DbEnumConstantHelper can be introduced, and to make it even more useful a few more variations of find methods can be added to it:
Now having such helper class, it can be added to enums for simple access to its functionality:
Finally we can get back to attribute converters.
We can see that all the conversion logic is placed in the abstract converter and implementations just need to pass a helper so the right find operations would be applied.
All the code samples can be found on GitHub.
To be continued ...
Using attribute converter to map java enum
Let's assume we have a PhoneType enum and a simple entity that has this enum as a field.To be able to map this enum into the integer column of database table, which would match enum's id we need to create an attribute converter similar to the next one:
Having such converter we can annotate the corresponding filed in the entity with the @Covert annotation and that's it! This look pretty easy and doesn't require a lot of code.
What if we have one more enum? For example let's add AddressType. The process would be very similar - we need to create an attribute converter class and add @Covert annotation on the corresponding filed.
But what if we have even more enums that should be mapped this way? This would mean that we need to write a converter for each enum and basically duplicate the same logic in each of them...
Handy utility for Enums
That's where an utility class comes. In Java it is not possible to build inheritance hierarchies of enums, but it is possible for enum to implement an interface. So if we have enums that we want to map by their id to a database columns we can create an interface similar to DbEnumConstant:Now let's make sure that our enums implement this interface:
Now that our enums have something in common we can generalize the operation of finding an enum value by id. For example next utility static method can be introduced:
But it would mean that an array of enums is needed to be passed all the time to make a call (for example like this - Utils.findByID( dbData, PhoneType.values() )). This can be solved with usage of Class#enumConstants method. DbEnumConstantHelper can be introduced, and to make it even more useful a few more variations of find methods can be added to it:
Now having such helper class, it can be added to enums for simple access to its functionality:
Finally we can get back to attribute converters.
AttributeConverter using enum helper
Now that we have all of the above in place we can write an abstract generic attribute converter for our enums with implementations for AddressType and PhoneType:We can see that all the conversion logic is placed in the abstract converter and implementations just need to pass a helper so the right find operations would be applied.
Conclusions
We looked once more at how Java enums can be mapped in JPA using AttributeConverter and provided a way to reduce code duplication in such converters. Even though, at first, it might not look like this amount of code is less then writing a simple converter. But it really pays of when you have quite a few enums to map in such a way. Also this enum helper, that was introduced, is useful outside the converters as well, it gives an easy access to finding enums by their properties.All the code samples can be found on GitHub.
To be continued ...