设置构造函数参数时,无法解析对bean'entityManagerFactory'的引用;

时间:2018-11-04 11:04:43

标签: java spring hibernate spring-mvc spring-data-jpa

我的代码中出现此错误。

  

org.springframework.beans.factory.BeanCreationException:错误   创建名称为'roleRepository'的bean:无法创建内部bean   类型的((内豆)#7540dc57''   设置时[org.springframework.orm.jpa.SharedEntityManagerCreator]   bean属性'entityManager';嵌套异常为   org.springframework.beans.factory.BeanCreationException:错误   创建名称为“((内部bean)#7540dc57”)的bean:无法解析   设置构造函数时对bean'entityManagerFactory'的引用   论点嵌套异常为   org.springframework.beans.factory.NoSuchBeanDefinitionException:否   名为“ entityManagerFactory”的bean可用

我看到了这些:

Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument

NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available

NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' is defined

他们都没有回答我的问题。问题是我能够解决问题,但对此有疑问。

让我分享我的相关代码,然后提出我的问题。

@Configuration
@EnableTransactionManagement 
public class HibernateConfig {

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerF() {
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(dataSource());
    em.setPackagesToScan(new String[] {"com.gitreporter"});
    JpaVendorAdapter jpaAdapter = new HibernateJpaVendorAdapter();
    em.setJpaVendorAdapter(jpaAdapter);
    em.setJpaProperties(jpaProperties());

    return em;
}

@Bean
public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory emf) {
    JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
    jpaTransactionManager.setEntityManagerFactory(emf);

    return jpaTransactionManager;
}

private final Properties jpaProperties() {
    Properties properties = new Properties();
    properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");

    return properties;
}


@Bean
public DataSource dataSource() {
    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/MyDBNAME?useSSL=false");
    dataSource.setUsername("username");
    dataSource.setPassword("password");

    return dataSource;
}

问题出在这条线上:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerF() {

我将方法名称更改为entityManagerFactory,如下所示:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

在上下文中使工厂bean的名称等于“ entityManagerFactory”,因为默认情况下,除非明确指定,否则bean的名称将等于方法名称。

我的问题:在JPA API中是否有一个地方“按惯例”正在Spring容器中寻找名为“ entityManagerFactory”的EntityManagerFactory bean?方法名称为“ entityManagerF”时为什么不起作用?

这是其余的代码:

@NoRepositoryBean
public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {

public List<T> findByAttributeContainsText(String attributeName, String text);

}

public class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
    implements GenericRepository<T, ID> {

private EntityManager entityManager;

public GenericRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
    super(entityInformation, entityManager);
    this.entityManager = entityManager;
 }
}


public interface RoleRepository extends GenericRepository<Role, Long> {

}

2 个答案:

答案 0 :(得分:1)

我找到了答案。

为{EnableJpaRepositories注释签出documentation

在可选元素中,您将看到以下内容:

  

entityManagerFactoryRef   配置EntityManagerFactory bean定义的名称,该定义用于创建通过此注释发现的存储库。

在页面上转到详细信息,您将看到以下内容:

  

entityManagerFactoryRef

     

公共抽象字符串entityManagerFactoryRef

     

配置名称   用于创建的EntityManagerFactory bean定义   通过此注释发现的存储库。默认为    entityManagerFactory

     

返回:

     

默认:“ entityManagerFactory”

因此,此“常规”默认配置来自@EnableJpaRepositories批注本身。

答案 1 :(得分:0)

是的,我相信。在您的情况下,Spring确实已经预先配置了一个Bean entityManagerFactory

javadoc摘录的@EnableAutoConfiguration

        Enable auto-configuration of the Spring Application Context, attempting to guess and configure beans that you are likely to need. Auto-configuration classes are usually applied based on your classpath and what beans you have defined. For example, if you have tomcat-embedded.jar on your classpath you are likely to want a TomcatServletWebServerFactory (unless you have defined your own ServletWebServerFactory bean).

然后,看到您的休眠配置,

private final Properties jpaProperties() {
    Properties properties = new Properties();
    properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");

    return properties;

...我认为这必须被调用,它是从JpaBaseConfiguration

派生的
@Configuration
@ConditionalOnSingleCandidate(DataSource.class)
class HibernateJpaConfiguration extends JpaBaseConfiguration {

JpaBaseConfiguration确实有一个entityManagerFactory的bean定义,这就是您要覆盖的内容。

@Bean
@Primary
@ConditionalOnMissingBean({ LocalContainerEntityManagerFactoryBean.class,
        EntityManagerFactory.class })
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
        EntityManagerFactoryBuilder factoryBuilder) {
    Map<String, Object> vendorProperties = getVendorProperties();
    customizeVendorProperties(vendorProperties);
    return factoryBuilder.dataSource(this.dataSource).packages(getPackagesToScan())
            .properties(vendorProperties).mappingResources(getMappingResources())
            .jta(isJta()).build();
}

修改:- 感谢OP的回答。因此,它甚至可以用于通过

之类的声明来提供自定义bean名称。
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerF",
)         

位于https://stackoverflow.com/a/45665826/5107365的另一个stackoverflow线程提供了对该问题的更深入了解。