PersistenceException:没有为名为 default 的持久性单元的模式生成找到持久性提供程序

Posted

技术标签:

【中文标题】PersistenceException:没有为名为 default 的持久性单元的模式生成找到持久性提供程序【英文标题】:PersistenceException: No persistence provider found for schema generation for persistence-unit named default 【发布时间】:2015-05-13 21:05:05 【问题描述】:

我尝试设置一个 gradle 任务,该任务运行一个旨在生成 SQL 模式的 java 主类。

我没有 persistence.xml 配置文件。

这是我的配置和代码:

我的毕业任务:

task JpaSchemaExport(type: JavaExec)
       description "Exports Jpa schema"
       dependsOn compileJava
       main = "com.bignibou.tools.jpa.JpaSchemaExport"
       classpath = sourceSets.main.runtimeClasspath + configurations.compile
    

我的导出工具:

public class JpaSchemaExport 

    public static void main(String[] args) throws IOException 
        // execute(args[0], args[1]);
        execute("default", "build/schema.sql");
        System.exit(0);
    

    public static void execute(String persistenceUnitName, String destination) 
        final Properties persistenceProperties = new Properties();

        // XXX force persistence properties : remove database target
        persistenceProperties.setProperty(org.hibernate.cfg.AvailableSettings.HBM2DDL_AUTO, "");
        persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_DATABASE_ACTION, "none");

        // XXX force persistence properties : define create script target from metadata to destination
        // persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_CREATE_SCHEMAS, "true");
        persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_SCRIPTS_ACTION, "create");
        persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_CREATE_SOURCE, "metadata");
        persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_SCRIPTS_CREATE_TARGET, destination);

        Persistence.generateSchema(persistenceUnitName, persistenceProperties);
    

我的数据配置:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() 
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
    emf.setPackagesToScan("com.bignibou.domain");
    emf.setDataSource(dataSource);
    emf.setPersistenceProvider(new HibernatePersistenceProvider());
    emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    emf.setJpaPropertyMap(propertiesMap());
    return emf;


private Map<String, String> propertiesMap() 
    Map<String, String> propertiesMap = new HashMap<>();
    propertiesMap.put("hibernate.dialect", hibernateDialect);
    propertiesMap.put("hibernate.hbm2ddl.auto", hibernateHbm2ddlAuto);
    propertiesMap.put("hibernate.ejb.naming_strategy", hibernateEjbNamingStrategy);
    propertiesMap.put("hibernate.connection.charSet", hibernateConnectionCharset);
    propertiesMap.put("hibernate.show_sql", hibernateLogSqlInfo);
    propertiesMap.put("hibernate.format_sql", hibernateLogSqlInfo);
    propertiesMap.put("hibernate.use_sql_comments", hibernateLogSqlInfo);
    propertiesMap.put("hibernate.generate_statistics", hibernateGenerateStatistics);
    propertiesMap.put("hibernate.cache.use_second_level_cache", hibernateCacheUseSecondLevelCache);
    propertiesMap.put("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
    propertiesMap.put("javax.persistence.sharedCache.mode", "ENABLE_SELECTIVE");
    return propertiesMap;

这是我得到的例外:

Exception in thread "main" javax.persistence.PersistenceException: No persistence provider found for schema generation for persistence-unit named default
 at javax.persistence.Persistence.generateSchema(Persistence.java:93)
 at com.bignibou.tools.jpa.JpaSchemaExport.execute(JpaSchemaExport.java:31)
 at com.bignibou.tools.jpa.JpaSchemaExport.main(JpaSchemaExport.java:14)

编辑:我确实收到了警告:

:bignibou-server:JpaSchemaExport
2015-05-16 14:46:44,423 [main] WARN  org.hibernate.ejb.HibernatePersistence - HHH015016: Encountered a deprecated javax.persistence.spi.PersistenceProvider [org.hibernate.ejb.HibernatePersistence]; use [org.hibernate.jpa.HibernatePersistenceProvider] instead.
2015-05-16 14:46:44,423 [main] WARN  org.hibernate.ejb.HibernatePersistence - HHH015016: Encountered a deprecated javax.persistence.spi.PersistenceProvider [org.hibernate.ejb.HibernatePersistence]; use [org.hibernate.jpa.HibernatePersistenceProvider] instead.
2015-05-16 14:46:44,423 [main] WARN  org.hibernate.ejb.HibernatePersistence - HHH015016: Encountered a deprecated javax.persistence.spi.PersistenceProvider [org.hibernate.ejb.HibernatePersistence]; use [org.hibernate.jpa.HibernatePersistenceProvider] instead.
Exception in thread "main" javax.persistence.PersistenceException: No persistence provider found for schema generation for persistence-unit named default
 at javax.persistence.Persistence.generateSchema(Persistence.java:93)
 at com.bignibou.tools.jpa.JpaSchemaExport.execute(JpaSchemaExport.java:32)
 at com.bignibou.tools.jpa.JpaSchemaExport.main(JpaSchemaExport.java:14)
:bignibou-server:JpaSchemaExport FAILED 

【问题讨论】:

查看AvailableSettings 类,有一个PROVIDER 常量,根据文档是“PersistenceProvider 实现者的名称”。所以也许你也应该设置那个属性。该值应该是HibernatePersistenceProvider 类的 FQN,但不幸的是,文档对此并不清楚... 谢谢。我尝试添加以下行:persistenceProperties.setProperty(AvailableSettings.PROVIDER, "org.hibernate.jpa.HibernatePersistenceProvider"); 无济于事... 你的持久化单元“默认”在哪里定义? @andih:我使用 Spring Boot,但我没有定义任何似乎默认为“默认”的持久性单元名称。 根据文档docs.spring.io/spring/docs/current/javadoc-api/org/… 的默认 PersistenceUnit,也根据 JPA 规范是无(空)。尝试设置 PersistenceUnit emf. setPersistenceUnitName("default"); 如果“default”是 PersistenceUnit 的默认名称,那么这不应该改变任何东西,否则它定义了一个名为“default”的命名 PersistenceUnit,您已经在引用它。 【参考方案1】:

据我从您的代码中可以看出,您的 JpaSchemaExport 并未在 Spring 上下文中执行。

当您从 Gradle 或命令行运行 JpaSchemaExport 时,您会创建自己的 EntityManager,它与 Spring 无关,并在 META-INF 目录中查找 persistence.xml 文件。对于 Spring Boot 应用程序,此文件不是必需的,因此可能不存在。

当我运行看起来与您的 JpaSchemaExport 相似的东西时 输出类似于

[main] INFO o.h.j.b.i.PersistenceXmlParser - HHH000318:在类路径中找不到任何 META-INF/persistence.xml 文件 [main] DEBUG o.h.jpa.HibernatePersistenceProvider - 定位并解析 0 个持久性单元;检查每个 [main] DEBUG o.h.jpa.HibernatePersistenceProvider - 在线程“main”中找不到匹配的持久性单元异常 javax.persistence.PersistenceException:找不到持久性提供程序 为名为 default 的持久性单元生成模式 javax.persistence.Persistence.generateSchema(Persistence.java:93) 在 com.example.springboot.jpa.JpaSchemaExport.execute(JpaSchemaExport.java:42) 在 com.example.springboot.jpa.JpaSchemaExport.main(JpaSchemaExport.java:14)

Spring Boot 命令行应用程序(具有 Spring 上下文的应用程序)看起来像:

@SpringBootApplication
public class Application implements CommandLineRunner 


    public static void main(String[] args) 
        SpringApplication.run(Application.class);
    

    @Override
    public void run(String... strings) throws Exception 

    


即你的JpaSchemaExport 可能被改写为

@SpringBootApplication
public class JpaSchemaExport implements CommandLineRunner 


    public static void main(String[] args) 
        // maybe activate a special spring profile to enable 
        // "hibernate.hbm2ddl.auto", validate | update | create | create-drop
        // AvailableSettings.SCHEMA_GEN_DATABASE_ACTION, "none" 
        // AvailableSettings.SCHEMA_GEN_CREATE_SCHEMAS, "true"
        // AvailableSettings.SCHEMA_GEN_SCRIPTS_ACTION, "create"
        // AvailableSettings.SCHEMA_GEN_CREATE_SOURCE, "metadata"
        // AvailableSettings.SCHEMA_GEN_SCRIPTS_CREATE_TARGET, destination

        SpringApplication.run(JpaSchemaExport.class);
    

    @Override
    public void run(String... strings) throws Exception 
       // nothing needed here 
    


作为替代方案,您可以创建一个 META-INF/persistence.xml,您的 Spring Boot 应用程序和您的 JpaSchemaExport 都可以使用它。

【讨论】:

【参考方案2】:

您的代码非常好和干净。服务器启动时是否还有其他警告,例如缺少 log4j 属性 .. 等,

我认为问题与缺少 jar 或类路径条目有关,但不确定。

【讨论】:

你是对的。我很肯定它与类路径配置问题有关。任何 gradle 用户都知道如何对此进行排序?【参考方案3】:

似乎Persistence.generateSchema() 使用了PersistenceProviderResolverHolder,其中包含PersistenceProviderResolver 来获取所有可用PersistenceProviders 的列表。也许你应该尝试实现你自己的PersistenceProviderResolver(只有两种方法)来返回你想要使用的那个(org.hibernate.jpa.HibernatePersistenceProvider),然后再调用Persistence.generateSchema()

PersistenceProviderResolverHolder.setPersistenceProviderResolver(new PersistenceProviderResolver() 

    public List<PersistenceProvider> getPersistenceProviders() 
        return Collections.singletonList(new HibernatePersistenceProvider());
    

    public void clearCachedProviders() 
);

【讨论】:

【参考方案4】:

使用 Spring Boot 应用生成架构:

import org.hibernate.jpa.AvailableSettings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import java.util.Properties;

@SpringBootApplication
public class JpaSchemaExport implements CommandLineRunner 
    @Autowired LocalContainerEntityManagerFactoryBean entityManagerFactory;

    public static void main(String... args) 
        new SpringApplicationBuilder(JpaSchemaExport.class).run(args);
    

    @Override
    public void run(String... args) throws Exception 
        final Properties persistenceProperties = new Properties();

        // XXX force persistence properties : remove database target
        persistenceProperties.setProperty(org.hibernate.cfg.AvailableSettings.HBM2DDL_AUTO, "");
        persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_DATABASE_ACTION, "none");

        // XXX force persistence properties : define create script target from metadata to destination
        persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_CREATE_SCHEMAS, "true");
        persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_SCRIPTS_ACTION, "create");
        persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_CREATE_SOURCE, "metadata");
        persistenceProperties.setProperty(AvailableSettings.SCHEMA_GEN_SCRIPTS_CREATE_TARGET, "./generated-schema.ddl");

        // generate sql with semicolon - workaround for HHH-10278
        String systemLineSeparator = System.getProperty("line.separator");
        System.setProperty("line.separator", ';' + systemLineSeparator);
        // get a persistence provider from spring context
        entityManagerFactory.getJpaVendorAdapter().getPersistenceProvider().generateSchema(entityManagerFactory.getPersistenceUnitInfo(), persistenceProperties);

        System.setProperty("line.separator", systemLineSeparator);
        System.exit(0);
    


【讨论】:

【参考方案5】:

您需要为使用以下方法以编程方式创建的持久性单元设置一个显式名称,然后确保调用 afterPropertiesSet() 方法:

emf.setPersistenceUnitName( "puname" );
...
emf.afterPropertiesSet();

使用此名称而不是“默认”来引用您的持久性单元

【讨论】:

【参考方案6】:

如果我不使用 META-INF/persistence.xml,则无法通过其名称找到持久性单元。

我不得不注入 EntityManagerFactory

@Autowired private LocalContainerEntityManagerFactoryBean emf;

... 并通过 info 对象找到持久性单元:

PersistenceProvider provider = emf.getJpaVendorAdapter().getPersistenceProvider();
provider.generateSchema(emf.getPersistenceUnitInfo(), persistenceProperties);

这对我有用。我希望它也可以帮助其他人。

【讨论】:

以上是关于PersistenceException:没有为名为 default 的持久性单元的模式生成找到持久性提供程序的主要内容,如果未能解决你的问题,请参考以下文章

线程“主”javax.persistence.PersistenceException 中的异常:org.hibernate.InstantiationException:实体没有默认构造函数:[重复

PersistenceException:传递给持久化的分离实体

Proguard - PersistenceException:构造函数与类不匹配

mybatis中SqlSession的selectList方法报错 org.apache.ibatis.exceptions.PersistenceException

竖亥——京东以神为名出击,神一样的物流黑科技

excel表格如何一键添加以时间为名的表格