【问题标题】:Execute sql script after jpa/EclipseLink created tables?jpa/EclipseLink 创建表后执行 sql 脚本?
【发布时间】:2011-02-13 09:54:15
【问题描述】:

在 EclipseLink 生成 ddl 之后,是否有可能执行 sql 脚本?
换句话说,是否有可能使用带有“drop-and-create-tables”的 EclipseLink 属性“eclipselink.ddl-generation”,并且 EclipseLink 在创建后执行另一个 sql 文件(将一些数据插入到刚刚创建的一些表中)表定义?

我将 EclipseLink 2.x 和 JPA 2.0 与 GlassFish v3 一起使用。

或者我可以在项目(与 ejb3 的战争)部署中调用的 java 方法中初始化表吗?

【问题讨论】:

    标签: java orm jpa eclipselink jpa-2.0


    【解决方案1】:

    出于同样的原因,我遇到了这个问题,试图找到一种在 DDL 生成后运行初始化脚本的方法。我为一个老问题提供了这个答案,希望为那些寻求相同解决方案的人缩短“文学研究”的数量。

    我正在使用带有默认 EclipseLink 2.5 JPA 实现的 GlassFish 4。 JPA 2.1 下的新模式生成功能使得在 DDL 生成完成后指定“初始化”脚本变得相当简单。

    <?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="cbesDatabase" transaction-type="JTA">
            <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
            <jta-data-source>java:app/jdbc/cbesPool</jta-data-source>
            <properties>
                <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
                <property name="javax.persistence.schema-generation.create-source" value="metadata"/>
                <property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
                <property name="javax.persistence.sql-load-script-source" value="META-INF/sql/load_script.sql"/>
                <property name="eclipselink.logging.level" value="FINE"/> 
            </properties>
        </persistence-unit>
    </persistence>
    

    上述配置从元数据(即注释)生成 DDL 脚本,然后运行 ​​META-INF/sql/load_script.sql 脚本以填充数据库。在我的例子中,我使用测试数据为几个表添加种子并生成额外的视图。

    关于 EclipseLink 使用 JPA 属性的其他信息可以在EclipseLink/Release/2.5/JPA21 的 DDL 生成部分找到。同样,Oracle 的 Java EE 7 教程中的 Section 37.5 Database Schema CreationTOTD #187 也提供了快速介绍。

    【讨论】:

    • 感谢您的提示。
    【解决方案2】:

    查看Running a SQL Script on startup in EclipseLink,它描述了一种与 Hibernate 的import.sql 功能等效的解决方案1。感谢肖恩·史密斯:

    Running a SQL Script on startup in EclipseLink

    有时,在使用 DDL 时 生成运行脚本很有用 首先清理数据库。在 如果您放置一个名为的文件,则休眠 类路径上的“import.sql” 内容将被发送到数据库。 就个人而言,我不是魔术迷 文件名,但这可能很有用 功能。

    没有对此的内置支持 在 EclipseLink 中,但很容易做到 感谢 EclipseLink 的高 可扩展性。这是一个快速的解决方案 我想出了:我只需注册一个 会话的事件监听器 postLogin 事件和在处理程序中我 读取文件并发送每个 SQL 对数据库的声明——很好 干净的。我走得更远了 支持设置文件名 作为持久性单元属性。你 可以在代码中或在 持久性.xml。

    ImportSQL 类配置为 一个SessionCustomizer 通过一个 持久性单元属性,其中 postLogin 事件,读取文件 由“import.sql.file”标识 财产。这个楼盘也是 指定为持久性单元 传递给的属性 createEntityManagerFactory。这 示例还显示了如何定义 并使用您自己的持久性单元 属性。

    import org.eclipse.persistence.config.SessionCustomizer;
    import org.eclipse.persistence.sessions.Session;
    import org.eclipse.persistence.sessions.SessionEvent;
    import org.eclipse.persistence.sessions.SessionEventAdapter;
    import org.eclipse.persistence.sessions.UnitOfWork;
    
    public class ImportSQL implements SessionCustomizer {
    
        private void importSql(UnitOfWork unitOfWork, String fileName) {
            // Open file
            // Execute each line, e.g.,
            // unitOfWork.executeNonSelectingSQL("select 1 from dual");
        }
    
        @Override
        public void customize(Session session) throws Exception {
            session.getEventManager().addListener(new SessionEventAdapter() {
                @Override
                public void postLogin(SessionEvent event) {
                    String fileName = (String) event.getSession().getProperty("import.sql.file");
                    UnitOfWork unitOfWork = event.getSession().acquireUnitOfWork();
                    importSql(unitOfWork, fileName);
                    unitOfWork.commit() 
                }    
            });
        }
    

    public static void main(String[] args) {
        Map<String, Object> properties = new HashMap<String, Object>();
    
        // Enable DDL Generation
        properties.put(PersistenceUnitProperties.DDL_GENERATION, PersistenceUnitProperties.DROP_AND_CREATE);
        properties.put(PersistenceUnitProperties.DDL_GENERATION_MODE, PersistenceUnitProperties.DDL_DATABASE_GENERATION);
        // Configure Session Customizer which will pipe sql file to db before DDL Generation runs
        properties.put(PersistenceUnitProperties.SESSION_CUSTOMIZER, "model.ImportSQL");
        properties.put("import.sql.file","/tmp/someddl.sql");
    
        EntityManagerFactory emf = Persistence
                .createEntityManagerFactory("employee", properties);
    }
    

    虽然我不确定它是否严格等效,但我不确定脚本是否会在数据库生成后运行。需要测试。如果没有,也许它可以适应。

    1 Hibernate 有一个简洁的小功能,但文档严重不足且未知。您可以在数据库模式生成后立即在 SessionFactory 创建期间执行 SQL 脚本,以将数据导入新数据库中。您只需在类路径根目录中添加一个名为 import.sql 的文件,并将 create 或 create-drop 设置为 hibernate.hbm2ddl.auto 属性。

    【讨论】:

    • 感谢记录严重不足和未知的功能!
    • @javydreamercsw:我已经粘贴了内容。
    • 很荣幸被引用。 ;)
    【解决方案3】:

    这可能会有所帮助,因为这里存在混淆: 使用完全相同的一组属性(记录器除外)进行数据播种。

    请勿使用:

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

    使用:

    <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
    <property name="javax.persistence.schema-generation.create-source" value="metadata"/>
    <property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
    

    我确认这对我有用。

    【讨论】:

      【解决方案4】:

      :) 用你的数据代替

      <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
      <property name="javax.persistence.schema-generation.create-source" value="metadata-then-script"/>
      <property name="javax.persistence.sql-load-script-source" value="META-INF/seed.sql"/>
      

      【讨论】:

        【解决方案5】:

        在 ddl 执行之前调用。而且似乎没有很好的方法来适应它,因为没有合适的事件可以使用。

        【讨论】:

        • @Ralph the Pascal 的解决方案
        【解决方案6】:

        这个过程提供在 DDL 语句之前执行 sql,而更好的(例如,插入种子数据)是在 DDL 语句之后执行一些东西。如果我在这里遗漏了什么,我不会。有人可以告诉我如何在eclipselink创建表之后执行sql(当create-tables属性设置为tru时)

        【讨论】:

        • 看来,eclipse 做不到(现在——可能在未来的版本中)。您的问题与我最初的问题完全相同。我还没有找到答案。如果你,请张贴!
        猜你喜欢
        • 2014-03-10
        • 2011-04-29
        • 1970-01-01
        • 1970-01-01
        • 2019-01-09
        • 2017-03-29
        • 2017-09-02
        • 1970-01-01
        • 2012-12-30
        相关资源
        最近更新 更多