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
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!!!
Generally Ipandzic's answer is the right hint I guess. However it did not work for me how he described it. I argument-constructor also looks a little strange in a Spring-environment. I played around a bit and was able to use an AttributeConverter of the following form (indeed you do not need the @Converter
-annotation or any other on the AttributeConverter
-class itself):
import javax.persistence.AttributeConverter;
import org.springframework.beans.factory.annotation.Autowired;
public class MyConverter implements AttributeConverter<String, String> {
@Autowired
private MyBean mybean;
public String convertToDatabaseColumn(String value) {
return myBean.changeValue(value);
}
public String convertToEntityAttribute(String dbValue) {
return myBean.undoChange(dbValue);
}
}
But creating this class and upgrading to Spring-Boot 2.1 (including Spring 5.1, Hibernate 5.3 and JPA 2.2) did not do the trick for me. The thing was, that I used LocalContainerEntityManagerFactoryBean
to configure my persistent storage which will not enable Dependency injection for AttributeConverter
s. Reading the first link Ipandzic posted suggests you have to bring LocalSessionFactoryBuilder
into play somehow. That's why I ended up with the following configuration:
//...
@Bean
public LocalSessionFactoryBean entityManagerFactory(DataSource dataSource, Environment env) {
LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
factory.setDataSource(dataSource);
// somehow tell the factory where you entitiy-definitions are, this is just
// one possibility of doing so:
String entityPackage = JpaMarkerModel.class.getPackage().getName();
log.info("EntityManager will scan for entities in package [{}].", entityPackage);
factory.setPackagesToScan(entityPackage);
return factory;
}
@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
//...
This "answer" is merely an addition to Ipandzi's, but maybe it helps some people to solve their problem quicker than I did.