Невозможно разрешить ссылку на bean-компонент "entityManagerFactory" при установке аргумента конструктора; - PullRequest
0 голосов
/ 04 ноября 2018

Я получаю эту ошибку в своем коде.

org.springframework.beans.factory.BeanCreationException: ошибка создание компонента с именем roleRepository: невозможно создать внутренний компонент '(внутренний бин) # 7540dc57' типа [org.springframework.orm.jpa.SharedEntityManagerCreator] при настройке свойство бина 'entityManager'; вложенное исключение org.springframework.beans.factory.BeanCreationException: ошибка создание компонента с именем '(внутренний компонент) # 7540dc57': не удается разрешить ссылка на bean-компонент "entityManagerFactory" при установке конструктора аргумент; вложенное исключение org.springframework.beans.factory.NoSuchBeanDefinitionException: нет бин с именем entityManagerFactory доступен

Я видел это:

Невозможно разрешить ссылку на bean-компонент "entityManagerFactory" при установке аргумента конструктора

NoSuchBeanDefinitionException: недоступен компонент с именем entityManagerFactory

NoSuchBeanDefinitionException: не определен боб с именем entityManagerFactory

Никто из них не отвечает на мой вопрос. Дело в том, что я смог решить проблему, но у меня есть вопрос по этому поводу.

Позвольте мне поделиться своим связанным кодом, а затем задать вопрос, который у меня есть.

@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() {

Я изменил имя medhod на entityManagerFactory следующим образом:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

Создание имени фабричного компонента в контексте, равного «entityManagerFactory», поскольку по умолчанию имя компонента будет равно имени метода, если это не указано явно.

Мой вопрос: есть ли место в JPA API, где "по соглашению" он ищет объект EntityManagerFactory с именем "entityManagerFactory" внутри контейнера Spring? Почему он не работает, если имя метода «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 голосов
/ 04 ноября 2018

Я нашел ответ.

Оформление документации для аннотации @EnableJpaRepositories.

В дополнительных элементах вы увидите это:

entityManagerFactoryRef Настраивает имя определения компонента EntityManagerFactory, которое будет использоваться для создания хранилищ, обнаруженных с помощью этой аннотации.

Перейдите по странице к деталям, и вы увидите это:

entityManagerFactoryRef

открытый абстрактный String entityManagerFactoryRef

Конфигурирует имя определение компонента EntityManagerFactory, которое должно быть , использовалось для создания репозитории, обнаруженные с помощью этой аннотации . По умолчанию EntityManagerFactory .

Возвращает:

По умолчанию: "entityManagerFactory"

Таким образом, эта «обычная» конфигурация по умолчанию взята из самой аннотации @EnableJpaRepositories.

0 голосов
/ 04 ноября 2018

Да, я верю в это. В вашем случае Spring предварительно настроил бин 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 действительно имеет определение bean-компонента для entityManagerFactory, которое вы пытаетесь переопределить.

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

Edit: - Благодаря ответу ОП. Таким образом, его даже можно использовать для предоставления собственного имени бина через объявление типа

@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerF",
)         

Другой поток stackoverflow в https://stackoverflow.com/a/45665826/5107365 обеспечивает более глубокое понимание этой проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...