从 JPA 注释的实体类自动生成数据模式

Posted

技术标签:

【中文标题】从 JPA 注释的实体类自动生成数据模式【英文标题】:Auto generate data schema from JPA annotated entity classes 【发布时间】:2010-09-22 18:49:02 【问题描述】:

我正在使用 JPA(Hibernate 的实现)来注释实体类以持久保存到关系数据库(mysql 或 SQL Server)。有没有一种简单的方法可以从带注释的类中自动生成数据库模式(表创建脚本)?

我仍处于原型设计阶段,预计会频繁更改架构。我希望能够从带注释的代码中指定和更改数据模型。 Grails 的相似之处在于它从域类生成数据库。

【问题讨论】:

查看***.com/questions/779479/… 【参考方案1】:

您可以使用 Hibernate 中的hbm2ddl。文档是here。

【讨论】:

他询问是否仅从带注释的类中生成模式。我的团队想做同样的事情。我相信 hbm2dll 仅适用于我的团队不想使用的 .hbm.xml 映射文件。我认为 OP 也没有。 根据“Manning Java Persistence with Hibernate”是的,您可以使用 hbm2ddl:“Hibernate 中自动生成 SQL DDL 的先决条件始终是 Hibernate 映射元数据定义,无论是在 XML 映射文件中还是在 Java 中源代码注释。”【参考方案2】:

作为相关说明:使用 EclipseLink JPA 生成数据库模式的文档可以在 here 找到。

【讨论】:

谢谢。多亏了你,我的问题在第一次谷歌点击时得到了回答。【参考方案3】:

为给定的 JPA 实体生成创建和删除脚本

我们使用这段代码来生成 drop 和 create 语句: 只需使用所有实体类构建此类并调用 create/dropTableScript。

如果需要,您可以改用 persitence.xml 和持久性单元名称。说些什么吧 我也发布了代码。

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

【讨论】:

相当不错的解决方案!但是直接使用persistence.xml对我们来说会舒服得多。您能否使用persistence.xml 发布代码?提前致谢! 这一行:public SqlTableCreator(final Collection> entity) 应该是 final Collection 实体 @r590 代码块在格式上有一些问题,但来源是正确的。我进行了编辑。 我想知道这如何与更现代的 HIbernate 版本(如 Hibernate 5.x)一起工作【参考方案4】:

这里解释了如何使用 hibernate SchemaExport 类来做你想做的事。

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

【讨论】:

尝试此解决方案会在引用 List 时使用 JDK1.8 产生编译错误【参考方案5】:

如果您更喜欢在 Spring 中进行配置,那么这应该会有所帮助:

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

【讨论】:

【参考方案6】:

你可以使用maven插件来实现。

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

【讨论】:

【参考方案7】:
<property name="hibernate.hbm2ddl.auto" value="update"/>

在persistence.xml的properties标签下添加上述代码。 "update" 将在您第一次运行代码时创建表,之后仅在域对象发生任何变化时更新表结构。

【讨论】:

【参考方案8】:

由于 Hibernate 4.3+ 现在实现了 JPA 2.1,生成 DDL 脚本的适当方法是使用以下一组 JPA 2.1 属性:

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

由于它将在运行时运行,您可能希望在构建时执行此 DDL 生成。 Hibernate4 不再支持官方 maven 插件,可能是因为 Hibernate 团队正在迁移到 Gradle。

无论如何,这是以编程方式生成此脚本的 JPA 2.1 方法:

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


如您所见,它非常简单!

您现在可以在 AntTask 或 MAVEN 构建中使用它(对于 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>

【讨论】:

java.lang.UnsupportedOperationException: 应用程序必须提供 JDBC 连接 ***.com/questions/34897410/…【参考方案9】:

使用 EclipseLink,您应该添加属性:

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

正如这里所说: http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/p_ddl_generation.htm

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

【讨论】:

以上是关于从 JPA 注释的实体类自动生成数据模式的主要内容,如果未能解决你的问题,请参考以下文章

JPA的模式:从实体生成数据传输对象DTO并将DTO合并到数据库

JPA 模式:从实体生成数据传输对象 DTO 并将 DTO 合并到数据库

springboot jpa oracle实体类中配置注解无法在数据库中生成注释的一种解决方式

Eclipse 通过JPA自动生成注解实体

IDEA生成JPA实体类

Spring Boot:如何从 JPA/Hibernate 注释中保持 DDD 实体的清洁?