Hibernate执行更新SQL语句但更新没有写入数据库

问题描述 投票:0回答:1

我有一个在 WildFly 服务器上运行的 Java EE 应用程序。持久化单元中的配置如下:

<persistence-unit name="default" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>java:/jboss/datasources/templateDS</jta-data-source>
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
        <validation-mode>AUTO</validation-mode>
        
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="use_sql_comments" value="false" />

            <property name="hibernate.cache.use_second_level_cache" value="true" />
            <property name="hibernate.cache.use_query_cache" value="true" />
<!--            <property name="hibernate.cache.region.factory_class" vvalue="org.hibernate.transaction.CMTTransactionFactory"/>-->
<!--            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.JndiInfinispanRegionFactory" />-->
            <property name="hibernate.cache.infinispan.cachemanager" value="java:jboss/infinispan/container/hibernate" /> 
<!--            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>-->


            <property name="hibernate.generate_statistics" value="false" />
            <!-- none | validate | update | create | create-drop -->
            <property name="hibernate.hbm2ddl.auto" value="none" />
        </properties>
        
    </persistence-unit>

我有一些业务逻辑,用于向用户发送 Firebase 推送通知,作为一种有针对性的通信形式。用户基数相当大(> 10k),因此我们决定以 10 个为一组对消息收件人进行分页和批处理,以确保不存在内存问题。我有一个名为 MessageRecipient 的实体,它管理接收消息的用户。它有一个列来管理状态,当逻辑运行时,我们希望将每条已发送消息的状态从“未发送”更新为“已发送”或“失败”。以下是我在方法中运行的业务逻辑:

private void sendTargetedMessages(CsvFile dueFile) {

        LOGGER.debug("in send targeted messages");
        String filename = dueFile.getFilename();
        String batchRef = filename.substring(0, filename.indexOf('.'));
        // Calculate number of recipients.
        int numberOfRecipients = crudService.findAllByColumn(MessageRecipient.class, batchRef, "batchRef").size();
        int pageNumber = 0;
        int pageSize = 10; //TODO: Change this to config entry
        Integer num_sent = 0;
        // Calculate number of pages. Use calculated number of pages to run the logic in a do while loop that increments
        do {
            List<MessageRecipient> recipients = crudService.findAllByColumn(MessageRecipient.class, batchRef, "batchRef", new Paging(pageNumber, pageSize));
            // Execute the logic
            if (recipients != null) {
                // send targeted messages
                User u;
                for (MessageRecipient r : recipients) {
                    u = null;
                    if (RecipientState.UNSENT.equals(r.getState())) {
                        if (UserReferenceType.CVS_REF.equals(dueFile.getUserReferenceType())) {
                            u = userRepository.findUserByCvsRef(r.getReference(), Status.ACTIVE);
                        } else {
                            try {
                                u = userRepository.findUserByUserId(Long.parseLong(r.getReference()), Status.ACTIVE);
                            } catch (NumberFormatException e) {
                                r.setState(RecipientState.FAILED);
                                LOGGER.error("Reference cannot be converted to long.", e);
                            }
                        }
                        if (u != null) {
                            pushNotificationService.sendTargetedCommunication(u, dueFile.getCommId());
                            r.setState(RecipientState.SENT);
                            num_sent++;
                        }
                        //crudService.merge(r);
                        entityManager.merge(r);
                        entityManager.flush();
                    }
                }
            } else {
                LOGGER.error("No recipients found for targeted communication.");
            }
            // Increment page number
            pageNumber++;
        } while (pageNumber <= (calculateNumberOfPages(numberOfRecipients, pageSize) - 1));

        // Send email report once done
        if (!StringUtils.isBlank(dueFile.getReportEmails())) {
            String[] reportEmails = dueFile.getReportEmails().split(",");
            List<String> reportEmailsList = Arrays.asList(reportEmails);
            messagingReportService.sendEmailReport(reportEmailsList, batchRef, numberOfRecipients, num_sent, dueFile.getBucketName());
        }
    }

我调用entityManager merge() 和flush() 来尝试在发送推送通知后更新每个MessageRecipient 记录的状态,但状态在我的数据库(MySQL 数据库)中没有更新。我在应用程序中打开了 SQL 语句日志记录,并且看到 Hibernate 执行更新 SQL 语句,尽管我的数据库中没有更新。我该如何解决这个问题?

11:04:54,017 INFO  [stdout] (EE-ManagedScheduledExecutorService-default-Thread-1) Hibernate: 
11:04:54,018 INFO  [stdout] (EE-ManagedScheduledExecutorService-default-Thread-1)     update
11:04:54,018 INFO  [stdout] (EE-ManagedScheduledExecutorService-default-Thread-1)         message_recipient 
11:04:54,019 INFO  [stdout] (EE-ManagedScheduledExecutorService-default-Thread-1)     set
11:04:54,019 INFO  [stdout] (EE-ManagedScheduledExecutorService-default-Thread-1)         last_updated=?,
11:04:54,019 INFO  [stdout] (EE-ManagedScheduledExecutorService-default-Thread-1)         batch_ref=?,
11:04:54,020 INFO  [stdout] (EE-ManagedScheduledExecutorService-default-Thread-1)         reference=?,
11:04:54,020 INFO  [stdout] (EE-ManagedScheduledExecutorService-default-Thread-1)         state=? 
11:04:54,021 INFO  [stdout] (EE-ManagedScheduledExecutorService-default-Thread-1)     where
11:04:54,021 INFO  [stdout] (EE-ManagedScheduledExecutorService-default-Thread-1)         id=?

最初我只是调用

entityManager.merge(T entity)
,Hibernate 在尝试更新实体时没有生成更新 SQL 语句,但我添加了
entityManager.flush()
,现在我在日志中看到它。但是,我的问题是数据库也没有更新。

hibernate jpa jta
1个回答
0
投票

您正在使用二级缓存,可能是缓存尚未刷新事务,请尝试读取应用程序中的更改(如果您尝试读取时存在更改),没问题,它按预期工作,那么这意味着它的缓存未刷新还没有到 DB。

另一件事是确保您使用 EJB 和 @TransactionManagement(TransactionManagementType.CONTAINER) 在容器管理的 TX 范围内进行操作

© www.soinside.com 2019 - 2024. All rights reserved.