13

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

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

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

4

6 回答 6

18

出于同样的原因,我遇到了这个问题,试图找到一种在 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/Release/2.5/JPA21的 DDL Generation 部分中找到有关 EclipseLink 使用 JPA 属性的其他信息。同样,Oracle 的 Java EE 7 教程和TOTD #187中的第 37.5 节数据库模式创建也提供了快速介绍。

于 2014-02-13T17:10:16.900 回答
16

查看在 EclipseLink 中启动时运行 SQL 脚本,它描述了一种解决方案,该解决方案与 Hibernate 的import.sql功能1等效。肖恩·史密斯的学分:

在 EclipseLink 中启动时运行 SQL 脚本

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

EclipseLink 中没有对此的内置支持,但由于 EclipseLink 的高可扩展性,它很容易做到。这是我想出的一个快速解决方案:我只需为会话 postLogin 事件注册一个事件侦听器,然后在处理程序中读取一个文件并将每个 SQL 语句发送到数据库——既好又干净。我更进一步,支持将文件名设置为持久性单元属性。您可以在代码或persistence.xml 中指定这一切。

该类通过持久性单元属性ImportSQL配置为在事件中读取由“import.sql.file”属性标识的文件。此属性也被指定为传递给的持久性单元属性 。此示例还显示了如何定义和使用自己的持久性单元属性。SessionCustomizerpostLogincreateEntityManagerFactory

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 属性。

于 2010-04-28T16:53:37.380 回答
2

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

不使用:

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

我确认这对我有用。

于 2014-10-12T13:46:39.400 回答
1

:) 只需用您的数据替换

<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"/>
于 2015-12-09T10:39:09.267 回答
0

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

于 2010-08-29T19:17:35.480 回答
0

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

于 2011-02-18T10:48:44.270 回答