web-dev-qa-db-fra.com

Comment configurer Spring sans persistence.xml?

J'essaie de mettre en place la configuration xml de printemps sans avoir à créer un autre persistence.xml. Mais je reçois constamment l'exception suivante, même si j'ai inclus les propriétés de la base de données dans le spring.xml

    Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in file [C:\Users\me\workspace\app\src\main\webapp\WEB-INF\applicationContext.xml]: Invocation of init method failed; nested exception is Java.lang.IllegalStateException: No persistence units parsed from {classpath*:META-INF/persistence.xml}

spring.xml:

  <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
  </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
     <property name="jpaProperties">
         <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
         </props>
      </property>
    </bean>

Qu'est-ce que j'oublie ici?

31
membersound

Spécifiez les propriétés "packagesToScan" et "persistenceUnitName" dans la définition du bean entityManagerFactory.

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />

        <property name="persistenceUnitName" value="myPersistenceUnit" />
        <property name="packagesToScan" >
            <list>
                <value>org.mypackage.*.model</value>
            </list>
        </property>

        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
            </props>
        </property>
    </bean>

Notez que cela concerne la version Spring> 3.1

28
Zaki

Depuis Spring Guide Accès aux données avec JPA

@Configuration
@EnableJpaRepositories
public class Application {

    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder().setType(H2).build();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
        LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
        lef.setDataSource(dataSource);
        lef.setJpaVendorAdapter(jpaVendorAdapter);
        lef.setPackagesToScan("hello");
        return lef;
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setShowSql(false);
        hibernateJpaVendorAdapter.setGenerateDdl(true);
        hibernateJpaVendorAdapter.setDatabase(Database.H2);
        return hibernateJpaVendorAdapter;
    }

Spring Boot

Avec l'application activée Spring Boot, c'est encore plus simple:

Exemple application.yaml

spring:
    datasource:
        url: jdbc:h2:mem:test
        username: sa
        password: sa
        driver-class-name: org.h2.Driver
    jpa:
        database: H2
        show-sql: false
        hibernate:
            format_sql: true
            ddl-auto: auto
41
MariuszS

La réponse de MariuszS est bonne, sauf que la méthode entityManagerFactory doit retourner EntityManagerFactory. Pour ce faire, il peut être écrit comme ceci:

@Bean
public EntityManagerFactory entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
    LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
    lef.setDataSource(dataSource);
    lef.setJpaVendorAdapter(jpaVendorAdapter);
    lef.setPackagesToScan("hello");
    return lef.object();
}

Pour le futur public: le code ci-dessous a fonctionné:

@Bean (name = "entityManagerFactory")
public EntityManagerFactory entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter)
{
    LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
    lef.setDataSource(dataSource);
    lef.setJpaVendorAdapter(jpaVendorAdapter);
    lef.setPackagesToScan("*.models*");
    lef.afterPropertiesSet(); // It will initialize EntityManagerFactory object otherwise below will return null
    return lef.getObject();
}
3
Mustafa

En supposant que vous avez une implémentation PersistenceProvider (par exemple org.hibernate.jpa.HibernatePersistenceProvider), Vous pouvez utiliser la méthode PersistenceProvider # createContainerEntityManagerFactory (informations PersistenceUnitInfo, Map map) à bootstrap an EntityManagerFactory sans avoir besoin d'un persistence.xml.

Cependant, il est ennuyeux de devoir implémenter l'interface PersistenceUnitInfo, il vaut donc mieux utiliser Spring ou Hibernate qui prennent tous les deux en charge l'amorçage JPA sans fichier persistence.xml:

this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory(
    this.persistenceUnitInfo, 
    getJpaPropertyMap()
);

Où le PersistenceUnitInfo est implémenté par la classe spécifique à Spring MutablePersistenceUnitInfo .

Consultez cet article pour une belle démonstration de la façon dont vous pouvez atteindre cet objectif avec Hibernate.

2
Vlad Mihalcea