PersistenceException: No persistence provider found for schema generation for persistence-unit named default

大憨熊 提交于 2019-12-05 08:25:13

Your JpaSchemaExport is not executed within a Spring Context as far as I can see from your code.

When you run your JpaSchemaExport from Gradle or command line you create your own EntityManager which has nothing to do with Spring and looks for a persistence.xml file in the META-INF directory. For Spring Boot Applications this file is not needed and thus may not exist.

When I run something which looks similar your JpaSchemaExport the output is something like

[main] INFO  o.h.j.b.i.PersistenceXmlParser - HHH000318: Could not find any META-INF/persistence.xml file in the class path
[main] DEBUG o.h.jpa.HibernatePersistenceProvider - Located and parsed 0  persistence units; checking each 
[main] DEBUG o.h.jpa.HibernatePersistenceProvider - Found no matching persistence units 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.example.springboot.jpa.JpaSchemaExport.execute(JpaSchemaExport.java:42)
    at
com.example.springboot.jpa.JpaSchemaExport.main(JpaSchemaExport.java:14)

A Spring Boot Commandline Application (one that has a Spring Context) looks something like:

@SpringBootApplication
public class Application implements CommandLineRunner {


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

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

    }

}

i.e. your JpaSchemaExport may be rewritten as

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

}

As an alternative you can create a META-INF/persistence.xml which can be used by your Spring Boot application as well as by your JpaSchemaExport.

Your code is very good and clean. Is there any other warning on server startup like log4j properties missing .. etc.,

I think the problem is related to some missing jar or classpath entry, though not sure about it.

It seems that Persistence.generateSchema() uses PersistenceProviderResolverHolder which holds a PersistenceProviderResolver to get a list of all available PersistenceProviders. Maybe you should try implementing your own PersistenceProviderResolver (only 2 methods) to return the one you want to use (org.hibernate.jpa.HibernatePersistenceProvider) before calling Persistence.generateSchema().

PersistenceProviderResolverHolder.setPersistenceProviderResolver(new PersistenceProviderResolver() {

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

    public void clearCachedProviders() {}
});

You would need to set an explicit name for the persistence unit that is created programmatically using the following method and then make sure to call the afterPropertiesSet() method:

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

Refer to your persistence unit using this name instead of "default"

Generating schema with Spring Boot app:

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

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!