如何在没有 persistence.xml 的情况下配置 Spring?

Posted

技术标签:

【中文标题】如何在没有 persistence.xml 的情况下配置 Spring?【英文标题】:How to configure Spring without persistence.xml? 【发布时间】:2014-02-18 08:31:57 【问题描述】:

我正在尝试设置 spring xml 配置,而不必再创建一个 persistence.xml。但是我经常遇到以下异常,即使我将数据库属性包含在 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>

我在这里错过了什么?

【问题讨论】:

【参考方案1】:

来自弹簧指南Accessing Data with 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 的应用程序会更容易:

示例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

【讨论】:

这个解决方案对我有用,除了上面的说明,setPackagesToScan("package name"),其中“package name”是包含你的实体类的包,参考docs.spring.io/spring/docs/current/javadoc-api/org/…【参考方案2】:

在 entityManagerFactory bean 定义中指定“packagesToScan”和“persistenceUnitName”属性。

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

请注意,这是针对 Spring 版本 > 3.1

【讨论】:

您是否知道以您需要的相同方式配置复合持久单元及其成员而无需persistence.xml文件。 它是否允许我们使用 spring 加载 entityManager,例如:@PersistenceContext private EntityManager em; 我得到“在 EntityManagerConfiguration 中没有指定持久性提供程序...”异常。你在回答中错过了吗? 有什么用,'myPersistenceUnit'在哪里存在?? 但这是一个 xml 配置!【参考方案3】:

MariuszS 的回答很好,只是 entityManagerFactory 方法应该返回 EntityManagerFactory。为此,可以这样写:

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

对于未来的观众:以下代码有效:

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

【讨论】:

【参考方案4】:

假设你有一个PersistenceProvider 实现(例如org.hibernate.jpa.HibernatePersistenceProvider),你可以使用PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) 方法来引导一个EntityManagerFactory 而不需要persistence.xml

但是,您必须实现 PersistenceUnitInfo 接口很烦人,因此您最好使用 Spring 或 Hibernate,它们都支持在没有 persistence.xml 文件的情况下引导 JPA。

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

PersistenceUnitInfo 由 Spring 特定的 MutablePersistenceUnitInfo 类实现。

【讨论】:

以上是关于如何在没有 persistence.xml 的情况下配置 Spring?的主要内容,如果未能解决你的问题,请参考以下文章

创建没有 persistence.xml 配置文件的 JPA EntityManager

使用 JDBC 和 persistence.xml

如何设置可移植的 persistence.xml 文件?

JAVA JPA persistence.xml - 如何在我的应用程序中使用之前测试连接有效性

如何在 Wildfly 部署时设置 hibernate.hbm2ddl.auto 不使用 persistence.xml

JPA persistence.xml 和 MySQL - 没有采用正确的“hibernate.connection.url”目录