访问AttributeConverter类中的Spring Bean

monwx1rj  于 2022-11-21  发布在  Spring
关注(0)|答案(3)|浏览(145)

我正在开发一个SpringDataJPA应用程序,我创建了一个AttributeConverter类,以便将ArrayList对象作为JSON保存在数据库列中。
由于AttributeConverter类是由Hibernate管理的,因此它似乎在创建任何Springbean之前被示例化,因此DI似乎不起作用(AttributeConverter类中的Spring Bean是null,并且抛出了一个NullPointer异常)。因此,现在我正在创建上述bean的另一个示例,以便能够在AttributeConverter类中使用它(这违背了DI的目的)。
我也尝试过创建一个实现ApplicationContextAware的Util类(用@Component注解),它提供了一个给出SpringBean(cxt.getBean(BeanClass.class))的方法。
有什么办法可以解决这个问题吗?

  • 谢谢-谢谢
hgc7kmma

hgc7kmma1#

使用JPA 2.2、Spring 5.1(SPR-16305)和Hibernate 5.3.0(HHH-12135),您不再需要使用可变静态属性hack,并且可以像在常规Spring托管Bean上一样使用依赖项注入(请注意,不再需要注解):

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) {
      ...
    }
}
5w9g7ksd

5w9g7ksd2#

可以使用静态属性将Bean( @Component 、@服务、@存储库)注入AttributeConverter
步骤:
1.在AttributeConverter中设置以下注解: @Component 、@转换器和 @configurable
1.定义要使用静态修饰符访问自动关联的字段
1.创建init方法以自动连接存储库
1.实现在接口AttributeConverter中定义的方法
基本上,代码应该如下所示...

// 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}
}

希望能有所帮助!

23c0lvtd

23c0lvtd3#

一般来说,我猜Ipandzic的回答是正确的。但是,他的描述对我来说并不管用。我的argument-constructor在Spring环境中看起来也有点奇怪。我试了一下,能够使用以下形式的AttributeConverter(实际上,你不需要@Converter-注解或AttributeConverter-类本身的任何其他注解):

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);
    }
}

但是创建该类并升级到Spring-Boot 2.1(包括Spring5.1、Hibernate 5.3和JPA2.2)对我来说并不管用。我使用LocalContainerEntityManagerFactoryBean来配置我的持久存储,这将不会启用AttributeConverter的依赖注入。阅读Ipandzic发布的第一个链接,建议您必须以某种方式使用LocalSessionFactoryBuilder。这就是我最终采用以下配置的原因:

//...

@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;
}

//...

这个“答案”只是对Ipandzi的补充,但也许它能帮助一些人比我更快地解决他们的问题。

相关问题