'Provide an AttributeConverter using @Bean
I am trying to provide an AttributeConverter using a Bean, but it does not seems to be picked up?
@SpringBootApplication
class TestJpaConvertApplication implements CommandLineRunner {
@Autowired
private CoordinateRepository repository;
@Override
public void run(String... args) throws Exception {
repository.save(new Coordinate().setAt(new Complex(1, 2)));
System.out.println(repository.findAll());
}
/* Bean to provide to the context, that is not being picked-up by JPA */
@Bean
public ComplexConverter complexConverter() {
return new ComplexConverter(":");
}
public static void main(String[] args) {
SpringApplication.run(TestJpaConvertApplication.class, args);
}
};
/* Dummy AttributeConverter that need to be instanciated with a specific value */
/* Use cases would be providing a password for encryption */
class ComplexConverter implements AttributeConverter<Complex, String> {
private final String separator;
public ComplexConverter(String separator) {
this.separator = separator;
}
@Override
public String convertToDatabaseColumn(Complex attribute) {
/* output would be 'i:j' for example */
return String.format("%d%s%d", attribute.getI(), separator, attribute.getJ());
}
@Override
public Complex convertToEntityAttribute(String dbData) {
String[] ij = dbData.split(separator);
return new Complex(Integer.parseInt(ij[0]), Integer.parseInt(ij[1]));
}
}
/* Dummy class */
@Data
@AllArgsConstructor
class Complex {
private int i;
private int j;
};
/* Dummy entity class */
@Entity
@Table
@Data
@Accessors(chain = true)
class Coordinate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column
@Convert(converter = ComplexConverter.class)
private Complex at;
};
@Repository
interface CoordinateRepository extends JpaRepository<Coordinate, Long> {
}
Is is possible to do something like that?
A real use case is to provide a password that will store the encrypted version (and then can decrypt too).
Here is the error I get:
......
2022-04-12 21:00:59.446 ERROR 30864 --- [ restartedMain] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: Unable to determine basic type mapping via reflection [test.Coordinate -> at]
......
2022-04-12 21:00:59.693 ERROR 30864 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in test.ComplexConverter required a bean of type 'java.lang.String' that could not be found.
Action:
Consider defining a bean of type 'java.lang.String' in your configuration.
The problem seems that when Hibernate start mapping entity classes, not all of the bean has been discovered? That what I discovered by running the code with the debugger. When trying to find the bean, the reference map was empty, so he was having no other choice than to create a new instance.
EDIT 1: Added more comment
EDIT 2: Added output
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
