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
Jakarta ee 在EntityManager关闭之前执行任务_Jakarta Ee_Jpa_Glassfish_Eclipselink_Entitymanager - Fatal编程技术网

Jakarta ee 在EntityManager关闭之前执行任务

Jakarta ee 在EntityManager关闭之前执行任务,jakarta-ee,jpa,glassfish,eclipselink,entitymanager,Jakarta Ee,Jpa,Glassfish,Eclipselink,Entitymanager,我想在关闭EntityManager(例如关闭AS或取消应用程序的下载)并查找钩子、侦听器或类似的东西之前执行任务 实际问题是: 我想用我的应用程序在数据库中保存很多小数据。为了减轻数据库的负载,我将数据缓存在一个列表中,并希望在给定的时间间隔内保存所有数据 到目前为止,这非常有效,但如果AS关闭,数据将丢失。这就是我希望在EntityManager关闭之前保存数据的原因 到目前为止,我尝试的是: 我试图在bean被销毁之前使用@PreDestroy注释保存数据。不幸的是,EntityManag

我想在关闭EntityManager(例如关闭AS或取消应用程序的下载)并查找钩子、侦听器或类似的东西之前执行任务

实际问题是: 我想用我的应用程序在数据库中保存很多小数据。为了减轻数据库的负载,我将数据缓存在一个列表中,并希望在给定的时间间隔内保存所有数据

到目前为止,这非常有效,但如果AS关闭,数据将丢失。这就是我希望在EntityManager关闭之前保存数据的原因

到目前为止,我尝试的是: 我试图在bean被销毁之前使用@PreDestroy注释保存数据。不幸的是,EntityManager的使用不起作用,正如我在后面读到的,PreDestroy方法中不允许使用EntityManager

@Singleton
@Startup
@DependsOn(value = "StatisticRepository")
public class StatisticService {
    private static final Logger LOG = Logger.getLogger(StatisticService.class.getName());

    @EJB
    private StatisticRepository repository;
    private List<Statistic> stats = new ArrayList<>();

    @PreDestroy
    public void destroy() {
        LOG.log(Level.INFO, "Saving before destroying Service.");
        for (Statistic stat : stats) {
            // ---> EntityManager in Repository already destroyed
            repository.create(stat);
        }
        stats.clear();
    }
...
}
@Singleton
@启动
@DependsOn(value=“StatisticRepository”)
公共类统计服务{
私有静态最终记录器LOG=Logger.getLogger(StatisticService.class.getName());
@EJB
私有统计存储库;
private List stats=new ArrayList();
@发情前期
公共空间销毁(){
LOG.LOG(Level.INFO,“销毁服务前保存”);
用于(统计数据:统计数据){
//-->存储库中的EntityManager已销毁
创建(stat);
}
stats.clear();
}
...
}

@Singleton
@启动
公共类StatisticRepository扩展了BaseRepository{
公共统计信息库(){
超级(统计类);
}
@PersistenceContext(unitName=PERSISTENCE\u UNIT\u NAME)
实体管理器;
@凌驾
受保护的EntityManager getEntityManager(){
返回em;
}
...
}

@MappedSuperclass
公共抽象类库{
受保护的抽象EntityManager getEntityManager();
私有最终类实体类;
公共BaseRepository(类entityClass){
this.entityClass=entityClass;
}
公共T创建(T实体){
getEntityManager().persist(实体);
getEntityManager().flush();
返回此。编辑(实体);
}
...
}
我在网上得到这个例外

Information: Saving Statistics before destroying Service. Warnung: RAR5114 : Error allocating connection : [{ PoolInfo : (name=java:app/pool), (applicationName=AppName) }: Es ist kein Poolmetadaten-Objekt mit dem Pool { PoolInfo : (name=java:app/pool), (applicationName=AppName) } verknüpft. Stellen Sie die Anwendung erneut bereit. ] Warnung: Local Exception Stack: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLException: { PoolInfo : (name=java:app/pool), (applicationName=AppName) }: Es ist kein Poolmetadaten-Objekt mit dem Pool { PoolInfo : (name=java:app/pool), (applicationName=AppName) } verknüpft. Stellen Sie die Anwendung erneut bereit. Error Code: 0 ... 信息:在销毁服务之前保存统计信息。 警告:RAR5114:分配连接时出错:[{poolfo:(name=java:app/pool),(applicationName=AppName)}:Es ist kein Poolmetadaten Objekt mit dem pool:{poolfo:(name=java:app/pool),(applicationName=AppName)}verknüpft.Stellen Sie die an wendung Ernut bereit.] 警告:本地异常堆栈: 异常[EclipseLink-4002](Eclipse持久性服务-2.5.0.v20130507-3faac2b):org.Eclipse.Persistence.exceptions.DatabaseException 内部异常:java.sql.SQLException:{poolfo:(name=java:app/pool),(applicationName=AppName)}:Es ist kein Poolmetadaten Objekt mit dem pool{poolfo:(name=java:app/pool),(applicationName=AppName)}verknüpft。你可以去看看欧内斯特·贝雷特。 错误代码:0 ... 该池(应用程序范围)似乎已取消部署

完整堆栈跟踪:

我在glassfish-resources.xml上创建JNDI资源和连接池。因此,它不是应用服务器范围的资源。也许这就是重现错误的关键

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
  <!-- MySQL -->
  <jdbc-connection-pool allow-non-component-callers="false"
                        associate-with-thread="false"
                        connection-creation-retry-attempts="0"
                        connection-creation-retry-interval-in-seconds="10"
                        connection-leak-reclaim="false"
                        connection-leak-timeout-in-seconds="0"
                        connection-validation-method="auto-commit"
                        datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
                        fail-all-connections="false"
                        idle-timeout-in-seconds="170"
                        is-connection-validation-required="true"
                        is-isolation-level-guaranteed="true"
                        transaction-isolation-level="repeatable-read"
                        lazy-connection-association="false"
                        lazy-connection-enlistment="false"
                        match-connections="false"
                        max-connection-usage-count="0"
                        max-pool-size="100"
                        max-wait-time-in-millis="60000"
                        name="java:app/mysql_app_appPool"
                        non-transactional-connections="false"
                        ping="true"
                        pool-resize-quantity="2"
                        pooling="true"
                        res-type="javax.sql.DataSource"
                        statement-cache-size="0"
                        statement-leak-reclaim="false"
                        statement-leak-timeout-in-seconds="0"
                        statement-timeout-in-seconds="0"
                        steady-pool-size="20"
                        validate-atmost-once-period-in-seconds="0"
                        wrap-jdbc-objects="true">
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
  </jdbc-connection-pool>
  <jdbc-resource enabled="true" jndi-name="java:app/jdbc/app" object-type="user" pool-name="java:app/mysql_app_appPool"/>


java:app/jdbc/app
假的
问题: 你对这一机制的总体看法如何? 缓存有意义吗,因为JPA可以自己更好地处理它?
有监听器或钩子吗?

eclipselink上有很多缓存选项。看一看

此外,对于现实生活中的性能,我强烈建议使用Infinspan。看一看

如果您的用例非常简单,那么使用
@Startup
注释的
@Singleton
ejbbean应该可以完成这项任务。像这样:

@Singleton
@Startup
public class StartupShutdownBean {

    @PostConstruct
    private void startup() {
        // your startup code here
    }

    @PreDestroy
    private void shutdown() {
        // your shutdown code here
    }

}
在这个bean上注入
EntityManager
应该不会有任何问题。很可能,您不能在bean中使用实体管理器,因为事务在您可以执行“缓存更新”之前结束

编辑:

与您的
@PreDestroy
调用之前一样,应用程序配置的资源似乎正在被删除,因此您应该在asadmin deploy或redeploy命令中使用
preserveAppScopedResources=true
参数,以便在这些操作期间保持池的活动状态


一些文档。

您是否尝试过用@Transactional注释装饰预销毁方法?另外,为什么要自己执行数据缓存?您是否尝试在JPA提供程序上配置缓存选项?此外,您可以使用带有@Startup注释的单例ejb bean,但是您仍然需要澄清您是否正在为每个无状态调用缓存数据。您不应该重新发明轮子。通过使用eclipselink,您有很多JPA缓存选项。此外,如果您使用的是高可用性要求,您应该查看Infinispan,了解实际应用程序数据缓存的性能。为了以防万一,请删除“stats.clear();”行。该方法可能比em.persist操作更快,因此使实体无效(准备进行垃圾收集)。persist flush merge操作非常昂贵。只有当您不需要任何数据库生成的ID或其他信息时,才避免使用它们。单独使用em.persist。不幸的是,这对我不起作用。我也用@DependsOn'测试了它。顺便说一句,包含entitymanager的bean的所有其他操作都运行良好。数据库的连接池(应用程序范围)似乎已在“@PreDestroy”上关闭。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
  <!-- MySQL -->
  <jdbc-connection-pool allow-non-component-callers="false"
                        associate-with-thread="false"
                        connection-creation-retry-attempts="0"
                        connection-creation-retry-interval-in-seconds="10"
                        connection-leak-reclaim="false"
                        connection-leak-timeout-in-seconds="0"
                        connection-validation-method="auto-commit"
                        datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
                        fail-all-connections="false"
                        idle-timeout-in-seconds="170"
                        is-connection-validation-required="true"
                        is-isolation-level-guaranteed="true"
                        transaction-isolation-level="repeatable-read"
                        lazy-connection-association="false"
                        lazy-connection-enlistment="false"
                        match-connections="false"
                        max-connection-usage-count="0"
                        max-pool-size="100"
                        max-wait-time-in-millis="60000"
                        name="java:app/mysql_app_appPool"
                        non-transactional-connections="false"
                        ping="true"
                        pool-resize-quantity="2"
                        pooling="true"
                        res-type="javax.sql.DataSource"
                        statement-cache-size="0"
                        statement-leak-reclaim="false"
                        statement-leak-timeout-in-seconds="0"
                        statement-timeout-in-seconds="0"
                        steady-pool-size="20"
                        validate-atmost-once-period-in-seconds="0"
                        wrap-jdbc-objects="true">
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
  </jdbc-connection-pool>
  <jdbc-resource enabled="true" jndi-name="java:app/jdbc/app" object-type="user" pool-name="java:app/mysql_app_appPool"/>
<?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 for MySQL -->
  <persistence-unit name="com.app.web_app-webapp_war_1.0-SNAPSHOTPU" transaction-type="JTA">
    <jta-data-source>java:app/jdbc/app</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="javax.persistence.schema-generation.database.action" value="create"/>
      <property name="javax.persistence.schema-generation.create-source" value="metadata-then-script"/>
      <property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
      <property name="javax.persistence.schema-generation-target" value="database"/>
    </properties>
  </persistence-unit>
</persistence>
@Singleton
@Startup
public class StartupShutdownBean {

    @PostConstruct
    private void startup() {
        // your startup code here
    }

    @PreDestroy
    private void shutdown() {
        // your shutdown code here
    }

}