Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jpa 使用EclipseLink执行本机批处理更新_Jpa_Eclipselink_Native - Fatal编程技术网

Jpa 使用EclipseLink执行本机批处理更新

Jpa 使用EclipseLink执行本机批处理更新,jpa,eclipselink,native,Jpa,Eclipselink,Native,亲爱的程序员们: 我的任务是每分钟更新Oracle11g数据库中大约10000-100000条记录。这些记录的当前状态保存在一个全局ArrayList中,因此我不需要在数据库的每次更新中选择所有记录。计划程序在每分钟开始时更新ArrayList中的记录,然后开始更新数据库中的记录 我无法改变这个事实,这是客户的要求。 为了实现高性能,这些更新应该通过使用本机批处理更新功能来完成 我使用的是带有EclipseLink 2.6.3的TomEE plume 7.0.2应用服务器(此版本随TomEE提供

亲爱的程序员们:

我的任务是每分钟更新Oracle11g数据库中大约10000-100000条记录。这些记录的当前状态保存在一个全局ArrayList中,因此我不需要在数据库的每次更新中选择所有记录。计划程序在每分钟开始时更新ArrayList中的记录,然后开始更新数据库中的记录

我无法改变这个事实,这是客户的要求。 为了实现高性能,这些更新应该通过使用本机批处理更新功能来完成

我使用的是带有EclipseLink 2.6.3的TomEE plume 7.0.2应用服务器(此版本随TomEE提供)

代码:

不幸的是,由于以下例外情况,该方法也不起作用: org.eclipse.persistence.internal.sessions.IsolatedClient会话不能强制转换为org.eclipse.persistence.internal.sessions.UnitOfWorkImpl

我现在别无选择,希望你们中的某个人能给我一个提示,告诉我在哪里可以看到和解决这个问题。我们将不胜感激


我宁愿让本机批处理更新工作,而不是操纵EclipseLink在合并时不执行任何选择。

在搜索了很长时间并尝试了不同的方法后(感谢Chris),如果您想保持JPA的本机状态,我找到了最简单的解决方案:

@Schedule(second="0", minute="*", hour="*", persistent=false)
public void startUpdate(){
    String updateSql =
    "UPDATE " + 
        "SCHEMA.PROPERTIES_GRP_CONT " + 
    "SET " + 
        "STRVAL = ? " + //<-- SQL-Param 
    "WHERE " + 
        "STATES_ID = 1 " +
        "AND PROPERTIES_ID = ? " + //<-- SQL-Param
        "AND PROPERTIES_GRP_ID = ?"; //<-- SQL-Param

    java.sql.Connection connection = em.unwrap(java.sql.Connection.class);
    PreparedStatement prepStatement = connection.prepareStatement(updateSql);

    for(BatchInfo bi : biList){ 
        prepStatement.setString(1, Long.toString(bi.getLifetime()));
        prepStatement.setLong(2, bi.getPropertiesId());
        prepStatement.setLong(3, bi.getBatchId());

        prepStatement.addBatch();
    }

    prepStatement.executeBatch();
}
@Schedule(second=“0”,minute=“*”,hour=“*”,persistent=false)
公众假期开始日期(){
字符串更新SQL=
“更新”+
“SCHEMA.PROPERTIES\u GRP\u CONT”+
“集合”+

“STRVAL=?”+/在搜索了很长一段时间并尝试了不同的方法(感谢Chris)之后,如果您想保持JPA的本机状态,我找到了最简单的解决方案:

@Schedule(second="0", minute="*", hour="*", persistent=false)
public void startUpdate(){
    String updateSql =
    "UPDATE " + 
        "SCHEMA.PROPERTIES_GRP_CONT " + 
    "SET " + 
        "STRVAL = ? " + //<-- SQL-Param 
    "WHERE " + 
        "STATES_ID = 1 " +
        "AND PROPERTIES_ID = ? " + //<-- SQL-Param
        "AND PROPERTIES_GRP_ID = ?"; //<-- SQL-Param

    java.sql.Connection connection = em.unwrap(java.sql.Connection.class);
    PreparedStatement prepStatement = connection.prepareStatement(updateSql);

    for(BatchInfo bi : biList){ 
        prepStatement.setString(1, Long.toString(bi.getLifetime()));
        prepStatement.setLong(2, bi.getPropertiesId());
        prepStatement.setLong(3, bi.getBatchId());

        prepStatement.addBatch();
    }

    prepStatement.executeBatch();
}
@Schedule(second=“0”,minute=“*”,hour=“*”,persistent=false)
公众假期开始日期(){
字符串更新SQL=
“更新”+
“SCHEMA.PROPERTIES\u GRP\u CONT”+
“集合”+

“STRVAL=?”+//JPA被迫在每次updateObject调用时逐个执行您的语句,因此无法将它们收集到更大的批处理中。您应该考虑更改操作,以便计划程序使用相同的EntityManager实例进行读取和更新,避免不必要的选择。否则,如果必须使用本机SQL执行此操作(并将其与读数分开),JPA可能不适合您,您需要获得连接并直接管理批处理语句的执行。感谢您的评论@Chris。我对您的评论有一个问题:如果计划程序使用相同的EntityManager,则在提交后实体将分离,我需要在下一个调度程序调用?我的目的是只从数据库读取一次数据,然后每分钟更新一次这些记录,而不首先选择或合并它们。您可以研究使用扩展的EntityManager上下文,并保持EntityManager的存在。此EntityManager将管理读取到其中的所有内容,允许您将其附加到用于获取在这些托管实体上所做更改的事务。另请注意,EclipseLink使用共享缓存,这在某些情况下可以防止在合并时进行读取。JPA被迫在每次updateObject调用中逐个执行您的语句,因此它无法将它们收集到更大的批中。您应该考虑更改您的操作,以便scheduler使用同一EntityManager实例进行读取和更新,避免不必要的选择。否则,如果必须为此操作使用本机SQL(并将其与读取分开),则,JPA可能不适合您,您需要获得连接并直接管理批处理语句的执行。感谢您的评论@Chris。我对您的评论有一个问题:如果计划程序使用相同的EntityManager,则在提交后实体将分离,我需要在下一个调度程序调用?我的目的是只从数据库读取一次数据,然后每分钟更新一次这些记录,而不首先选择或合并它们。您可以研究使用扩展的EntityManager上下文,并保持EntityManager的存在。此EntityManager将管理读取到其中的所有内容,允许您将其附加到用于获取在这些托管实体上所做更改的事务。还请注意,EclipseLink使用共享缓存,在某些情况下可以防止在合并时进行读取。
<?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="MES_Tables" transaction-type="JTA">
        <jta-data-source>MES_Connection</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="javax.persistence.schema-generation.database.action" value="none" />
            <property name="eclipselink.ddl-generation" value="none" />
            <property name="eclipselink.logging.level" value="WARNING" />
            <property name="eclipselink.logging.level.sql" value="FINE" />
            <property name="eclipselink.logging.parameters" value="true" />

            <property name="javax.persistence.query.timeout" value="1800000" />
            <property name="eclipselink.jdbc.connections.wait-timeout" value="1800000" />
            <property name="eclipselink.jdbc.batch-writing" value="JDBC" />
            <property name="eclipselink.jdbc.batch-writing.size" value="600" />

            <property name="eclipselink.logging.logger" value="mes.core.logging.EclipseLinkLogger"/>
        </properties>
    </persistence-unit>
</persistence>
    EntityManagerImpl emImpl = ((EntityManagerImpl) em.getDelegate());
    UnitOfWork uow = emImpl.getUnitOfWork();
    AbstractSession as = uow.getParent();

    for(BatchInfo bi : biList)
        as.updateObject(bi);
@Schedule(second="0", minute="*", hour="*", persistent=false)
public void startUpdate(){
    String updateSql =
    "UPDATE " + 
        "SCHEMA.PROPERTIES_GRP_CONT " + 
    "SET " + 
        "STRVAL = ? " + //<-- SQL-Param 
    "WHERE " + 
        "STATES_ID = 1 " +
        "AND PROPERTIES_ID = ? " + //<-- SQL-Param
        "AND PROPERTIES_GRP_ID = ?"; //<-- SQL-Param

    java.sql.Connection connection = em.unwrap(java.sql.Connection.class);
    PreparedStatement prepStatement = connection.prepareStatement(updateSql);

    for(BatchInfo bi : biList){ 
        prepStatement.setString(1, Long.toString(bi.getLifetime()));
        prepStatement.setLong(2, bi.getPropertiesId());
        prepStatement.setLong(3, bi.getBatchId());

        prepStatement.addBatch();
    }

    prepStatement.executeBatch();
}