访问AttributeConverter类中的Spring Bean

时间:2017-11-10 09:23:40

标签: spring hibernate jpa

我正在开发Spring Data JPA应用程序,并且我已经创建了一个AttributeConverter类,以便将ArrayList个对象作为JSON保存在数据库列中。在这个类中,我需要使用我定义为Spring Bean的类。

由于AttributeConverter类由Hibernate管理,它似乎在创建任何Spring bean之前被实例化,因此DI似乎不起作用(AttributeConverter类中的Spring Bean是{ {1}},我收到了null异常。所以目前我正在创建所述bean的另一个实例,以便能够在NullPointer类中使用它(这违背了DI的目的)。

我还尝试创建一个实现AttributeConverter的Util类(带有@Component注释),它提供了一个给出SpringBean(ApplicationContextAware)的方法。但这也是 cxt.getBean(BeanClass.class)之后的实例化。

有什么想法可以解决这个问题吗?

谢谢。

3 个答案:

答案 0 :(得分:10)

您可以使用静态属性在AttributeConverter中注入bean(@ Component,@ Service,@ Repository)

Setps:

  1. 使用以下注释在AttributeConverter中设置:@ Component,@ Confverter和@Configurable
  2. 使用static modifier access
  3. 定义要自动装配的字段
  4. 创建一个init方法,以便自动连接存储库
  5. 实现接口AttributeConverter
  6. 中定义的方法

    基本上,代码看起来应该是这样......

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

    我希望它可以帮助!!!

答案 1 :(得分:7)

对于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) {
      ...
    }
}

答案 2 :(得分:0)

一般而言,我猜伊潘兹奇的答案是正确的提示。但是,他如何描述它对我没有用。在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(包括Spring 5.1,Hibernate 5.3和JPA 2.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的补充,但也许它可以帮助某些人比我更快地解决他们的问题。