I'm developing a Spring Data JPA application, and I've created an AttributeConverter
class in order to save an ArrayList
of objects as JSON in a database column. Inside this class I need to make use of a class I have defined as a Spring Bean.
As the AttributeConverter
class is managed by Hibernate, it seems to be instantiated before any Spring beans are created, and therefore DI does not seem to work (the Spring Bean in the AttributeConverter
class is null
, and I'm getting a NullPointer
exception thrown). So at the moment I'm creating another instance of the said bean to be able to use it in the AttributeConverter
class (which defeats the purpose of DI).
I've also tried creating a Util class (annotated with @Component
) which implements ApplicationContextAware
, which provides a method giving the SpringBean (cxt.getBean(BeanClass.class)
). But this also is instantiated after the AttributeConverter
.
Is there any idea of how this can be solved?
Thank you.
With JPA 2.2, Spring 5.1( SPR-16305) and Hibernate 5.3.0 (HHH-12135) you no longer need to use the mutable static property hack and can use dependency injection just like you would on a regular spring managed bean (note that annotations are no longer necessary):
public class MyAttributeConverter implements AttributeConverter<X,Y> { private final MySpringBean bean; public MyAttributeConverter(MySpringBean bean) { this.bean = bean; } public Y convertToDatabaseColumn(X attribute) { ... } public X convertToEntityAttribute(Y dbData) { ... } }
You can inject a bean(@Component, @Service, @Repository) inside an AttributeConverter using static properties
Setps:
Basically, the code should look like this...
//Step 1 @Component @Converter @Configurable public class MyAttributeConverter implements AttributeConverter<X,Y> { //Where: X = the type of the entity attribute and Y = the type of the database column //Step 2 private static MyRepository myRepository; //Step 3 @Autowired public void initMyRepository(MyRepository myRepository){ MyAttributeConverter.myRepository = myRepository; } //Step 4 Y convertToDatabaseColumn(X attribute){//TODO implement method} X convertToEntityAttribute(Y dbData){//TODO implement method} }
I hope it can help!!!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With