web-dev-qa-db-ja.com

コンストラクター引数の設定中は、Bean 'entityManagerFactory'への参照を解決できません。

私のコードでこのエラーが発生しています。

org.springframework.beans.factory.BeanCreationException: 'roleRepository'という名前のBeanの作成エラー:Beanプロパティ 'entityManagerを設定しているときに、タイプ[org.springframework.orm.jpa.SharedEntityManagerCreator]の内部Bean'(内部Bean)#7540dc57 'を作成できません';ネストされた例外はorg.springframework.beans.factory.BeanCreationException:名前が「(インナーBean)#7540dc57」のBeanの作成中にエラーが発生しました:コンストラクター引数の設定中にBean 'entityManagerFactory'への参照を解決できません。ネストされた例外はorg.springframework.beans.factory.NoSuchBeanDefinitionException: 'entityManagerFactory'という名前のBeanがありません

私はこれらを見ました:

コンストラクタ引数の設定中はBean 'entityManagerFactory'への参照を解決できません

NoSuchBeanDefinitionException: 'entityManagerFactory'という名前のBeanはありません

NoSuchBeanDefinitionException: 'entityManagerFactory'という名前のBeanが定義されていません

それらのどれも私の質問に答えません。問題は解決できたのですが、質問があります。

関連するコードを共有してから、質問をします。

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

明示的に指定されない限り、デフォルトでBeanの名前はメソッド名と同じになるため、コンテキスト内のファクトリBeanの名前を「entityManagerFactory」と等しくします。

私の質問: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> {

}
7
honor

答えを見つけました。

@EnableJpaRepositoriesアノテーションの documentation をチェックアウトします。

オプションの要素では、次のようになります。

entityManagerFactoryRefこのアノテーションで検出されたリポジトリを作成するために使用されるEntityManagerFactory Bean定義の名前を構成します。

ページに移動して詳細を確認すると、次のように表示されます。

entityManagerFactoryRef

パブリック抽象文字列entityManagerFactoryRef

EntityManagerFactory Bean定義の名前を このアノテーションで発見されたリポジトリを作成するために使用されます。デフォルトはentityManagerFactoryです。

戻り値:

デフォルト: "entityManagerFactory"

したがって、この「従来の」デフォルト構成は、@ EnableJpaRepositoriesアノテーション自体からのものです。

3
SoftwareTheory

はい、そう思います。あなたの場合、SpringはBean entityManagerFactoryを事前に設定しています。

@EnableAutoConfigurationのjavadocからの抜粋

        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スレッドは、この問題についてより深い洞察を提供します。

0
Raj