web-dev-qa-db-fra.com

Générer automatiquement un schéma de données à partir de classes d'entités annotées JPA

J'utilise JPA (implémentation d'Hibernate) pour annoter des classes d'entités afin qu'elles persistent dans une base de données relationnelle (MySQL ou SQL Server). Existe-t-il un moyen simple de générer automatiquement le schéma de base de données (scripts de création de table) à partir des classes annotées?

Je suis encore en phase de prototypage et j'anticipe de fréquents changements de schéma. Je voudrais pouvoir spécifier et changer le modèle de données du code annoté. Grails est similaire en ce qu'il génère la base de données à partir des classes de domaine.

41
Steve Kuo

Vous pouvez utiliser hbm2ddl depuis Hibernate. Les documents sont ici .

14
Vincent Ramdhanie

Générer un script de création et de suppression pour des entités JPA données

Nous utilisons ce code pour générer les instructions drop et create: Construisez simplement cette classe avec toutes les classes d'entité et appelez create/dropTableScript.

Si nécessaire, vous pouvez utiliser un nom d'unité persitence.xml et persitance à la place. Dites juste quelque chose et je poste aussi le code.

import Java.util.Collection;
import Java.util.Properties;

import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.dialect.Dialect;
import org.hibernate.ejb.Ejb3Configuration;

/**
 * SQL Creator for Tables according to JPA/Hibernate annotations.
 *
 * Use:
 *
 * {@link #createTablesScript()} To create the table creationg script
 *
 * {@link #dropTablesScript()} to create the table destruction script
 * 
 */
public class SqlTableCreator {

    private final AnnotationConfiguration hibernateConfiguration;
    private final Properties dialectProps;

    public SqlTableCreator(final Collection<Class<?>> entities) {

        final Ejb3Configuration ejb3Configuration = new Ejb3Configuration();
        for (final Class<?> entity : entities) {
            ejb3Configuration.addAnnotatedClass(entity);
        }

        dialectProps = new Properties();
        dialectProps.put("hibernate.dialect", "org.hibernate.dialect.SQLServerDialect");

        hibernateConfiguration = ejb3Configuration.getHibernateConfiguration();
    }

    /**
     * Create the SQL script to create all tables.
     * 
     * @return A {@link String} representing the SQL script.
     */
    public String createTablesScript() {
        final StringBuilder script = new StringBuilder();

        final String[] creationScript = hibernateConfiguration.generateSchemaCreationScript(Dialect
                .getDialect(dialectProps));
        for (final String string : creationScript) {
            script.append(string).append(";\n");
        }
        script.append("\ngo\n\n");

        return script.toString();
    }

    /**
     * Create the SQL script to drop all tables.
     * 
     * @return A {@link String} representing the SQL script.
     */
    public String dropTablesScript() {
        final StringBuilder script = new StringBuilder();

        final String[] creationScript = hibernateConfiguration.generateDropSchemaScript(Dialect
                .getDialect(dialectProps));
        for (final String string : creationScript) {
            script.append(string).append(";\n");
        }
        script.append("\ngo\n\n");

        return script.toString();
    }
}
13
H2000

Comme note connexe: la documentation pour générer des schémas de base de données à l'aide d'EclipseLink JPA peut être trouvée ici .

9
hohonuuli

Comme Hibernate 4.3+ implémente désormais JPA 2.1, la façon appropriée de générer des scripts DDL consiste à utiliser l'ensemble de propriétés JPA 2.1 suivant:

<property name="javax.persistence.schema-generation.scripts.action" value="create"/>
<property name="javax.persistence.schema-generation.create-source" value="metadata"/>
<property name="javax.persistence.schema-generation.scripts.create-target" value="target/jpa/sql/create-schema.sql"/>

Comme il sera exécuté au moment de l'exécution, vous souhaiterez peut-être exécuter cette génération DDL lors de la génération. Il n'y a plus de plugin maven officiel pris en charge pour Hibernate4 probablement parce que l'équipe Hibernate passe à Gradle.

Quoi qu'il en soit, c'est l'approche JPA 2.1 pour générer ce script par programme:

import Java.io.IOException;
import Java.util.Properties;

import javax.persistence.Persistence;

import org.hibernate.jpa.AvailableSettings;

public class JpaSchemaExport {

    public static void main(String[] args) throws IOException {
        execute(args[0], args[1]);
        System.exit(0);
    }

    public static void execute(String persistenceUnitName, String destination) {
        System.out.println("Generating DDL create script to : " + 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);
    }

}

Comme vous pouvez le voir, c'est très simple!

Vous pouvez maintenant utiliser ceci dans une AntTask, ou une construction MAVEN comme celle-ci (pour MAVEN):

            <plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.7</version>
                <executions>
                    <execution>
                        <id>generate-ddl-create</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <!-- ANT Task definition -->
                                <Java classname="com.orange.tools.jpa.JpaSchemaExport"
                                    fork="true" failonerror="true">
                                    <arg value="${persistenceUnitName}" />
                                    <arg value="target/jpa/sql/schema-create.sql" />
                                    <!-- reference to the passed-in classpath reference -->
                                    <classpath refid="maven.compile.classpath" />
                                </Java>
                            </target>
                        </configuration>

                    </execution>
                </executions>
            </plugin>
8
Donatello

Voici une explication de l'utilisation de la classe hibernate SchemaExport pour faire exactement ce que vous voulez.

http://jandrewthompson.blogspot.com/2009/10/how-to-generate-ddl-scripts-from.html

6
Andrew Thompson

Si vous préférez configurer au printemps, cela devrait être utile:

 <!-- CONTAINER-MANAGED JPA Entity manager factory (No need for persistence.xml)-->
    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
    <!-- Fine Grained JPA properties Create-Drop Records -->
    <property name="jpaProperties">
    <props>
    <prop key="hibernate.hbm2ddl.auto">create</prop>
    </props>
    </property> 
    </bean> 
     <!-- The JPA vendor -->
    <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <!-- <property name="database" value="MySQL"/> -->
    <property name="showSql" value="true"/>
    <!--  <property name="generateDdl" value="true"/>  -->
    <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>      
    </bean> 
     <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="emf" />
     </bean>
2

Vous pouvez utiliser le plugin maven pour y parvenir.

       <plugin>
            <!-- run command "mvn hibernate3:hbm2ddl" to generate DLL -->
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>hibernate3-maven-plugin</artifactId>
            <version>3.0</version>
            <configuration>
                <hibernatetool>
                    <classpath>
                        <path location="${project.build.directory}/classes" />
                        <path location="${project.basedir}/src/main/resources/META-INF/" />                                               
                    </classpath>   

                    <jpaconfiguration persistenceunit="galleryPersistenceUnit" />                     
                    <hbm2ddl create="true" export="false" destdir="${project.basedir}/target" drop="true" outputfilename="mysql.sql" format="true" console="true"/>
                </hibernatetool>
            </configuration>
        </plugin>
2
sendon1982

Avec EclipseLink, vous devez ajouter une propriété:

<property name="eclipselink.ddl-generation" value="create-tables"/>

Comme il est dit ici: http://www.Eclipse.org/eclipselink/documentation/2.4/jpa/extensions/p_ddl_generation.htm

Mon persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="appDB" transaction-type="JTA">
        <provider>org.Eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>LocalMySQL</jta-data-source>
        <class>entity.Us</class>
        <class>entity.Btl</class>
        <class>entity.Co</class>
        <properties>
            <property name="eclipselink.ddl-generation" value="create-tables"/>
        </properties>
    </persistence-unit>
</persistence>
1
Krystian
<property name="hibernate.hbm2ddl.auto" value="update"/>

Ajoutez le code ci-dessus dans le persistence.xml sous la balise properties. "mise à jour" créera la table lors de la première exécution de votre code, après cela, ne mettez à jour les structures de la table qu'en cas de modification de l'objet de domaine.

1
sendon1982