在 jpa/EclipseLink 创建表后执行 sql 脚本?

2022-09-04 05:59:13

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

我正在使用EclipseLink 2.x和JPA 2.0与GlassFish v3。

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


答案 1

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

我正在使用GlassFish 4及其默认的EclipseLink 2.5 JPA实现。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 教程和 TOTD #187 中的第 37.5 节数据库模式创建也提供了快速介绍。


答案 2

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

在 EclipseLink 中启动时运行 SQL 脚本

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

EclipseLink中没有内置的支持,但很容易感谢EclipseLink的高可扩展性。以下是我想出的一个快速解决方案:我只需为会话PostLogin事件注册一个事件侦听器,然后在处理程序中读取一个文件并将每个SQL语句发送到数据库 - 漂亮而干净。我走得更远,支持将文件名设置为持久性单元属性。您可以在代码中或在持久性.xml中指定这一切。

该类配置为通过持久性单元属性,该属性在事件上读取由“import.sql.file”属性标识的文件。此属性还指定为持久性单元属性,该属性将传递给 。此示例还演示如何定义和使用自己的持久性单元属性。ImportSQLSessionCustomizerpostLogincreateEntityManagerFactory

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 冬眠有一个整洁的小功能,记录严重不足和未知。您可以在数据库架构生成后立即在 SessionFactory 创建期间执行 SQL 脚本,以导入新数据库中的数据。您只需要在类路径根目录中添加一个名为 import.sql 的文件,并将 create 或 create-drop 设置为 hibernate.hbm2ddl.auto 属性。


推荐