Hibernate 和多线程逻辑

2024-01-06

我正在开发一个 java 独立项目。我需要在多线程应用程序中使用休眠,但我只是不知道如何正确设置它。

每个线程处理其他线程的相同进程。

当我以非异步方式运行它时,一切都很好,但是当我使用线程调用相同的东西时,休眠就无法正常工作。

谁能解释一下在多线程 Java 独立应用程序中使用 Hibernate 的正确方法是什么?

休眠实用程序

public class HibernateUtil {

private static final Session session;

static {
    try {
        SessionFactory sessionFactory;
        Properties properties = new Properties();
        properties.load(new FileInputStream("middleware.properties"));
        Configuration cfg = new Configuration().configure();
        cfg.addProperties(properties);
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(cfg.getProperties()).build();
        sessionFactory = cfg.buildSessionFactory(serviceRegistry);
        session = sessionFactory.openSession();
    } catch (IOException | HibernateException he) {
        JOptionPane.showMessageDialog(null, DataBaseMessage.CONNECTION_ERROR.getMessage(),              DataBaseMessage.CONNECTION_ERROR.getTitle(),JOptionPane.ERROR_MESSAGE);
        throw new ExceptionInInitializerError(he);          
    }  
}
public static Session getSession() {
    return session;
}

错误来到这里

TbHistoDespachos despacho = Dao.findDespachoByTagId(element.getChild("tagID").getText());

public synchronized List<TbHistoDespachos> ExractDespachoAndNotify(String data, String nombreConexion) {
    List<TbHistoDespachos> despachos = new ArrayList<>();
    String nombreConexionUpp = nombreConexion.toUpperCase();
    try {
        Document doc = convertStringToDocument(data);
        if (!doc.getRootElement().getChild("reply").getChild("readTagIDs")
                .getChildren().isEmpty()) {
            for (Element element : doc.getRootElement().getChild("reply").
                    getChild("readTagIDs").getChild("returnValue")
                    .getChildren()) {
                TbHistoDespachos despacho = Dao.findDespachoByTagId(element.getChild("tagID").getText());
                if (despacho != null) {
                    if(evaluateDespacho(nombreConexionUpp, despacho)){
                        despachos.add(despacho);
                    }
                }
            }
        }
    } catch (JDOMException | IOException ex) {
        JOptionPane.showMessageDialog(null, FilesMessageWarnings.NOTIFICATION_SAP_WARNING.
                getMessage().replace("&nombreConexion", nombreConexion).replace("&tagID", ""),
                FilesMessageWarnings.NOTIFICATION_SAP_WARNING.getTitle(), JOptionPane.WARNING_MESSAGE);
    }
    return despachos;
}

这是 DAO

public class Dao {

private static Session sesion;
public static TbHistoDespachos findDespachoByTagId(String tagId) {
    TbHistoDespachos despacho = null;
    try {
        startTransmission();
        despacho = (TbHistoDespachos)sesion.createQuery("FROM TbHistoDespachos WHERE TAG_ID =:tagId")
                .setParameter("tagId", tagId)
                .uniqueResult();
        stopTransmission();
    } catch (HibernateException he) {
        System.out.println("error: " + he.getMessage());
        JOptionPane.showMessageDialog(null, DataBaseMessage.QUERY_ERROR.getMessage(),
                DataBaseMessage.QUERY_ERROR.getTitle(), JOptionPane.ERROR_MESSAGE);
    }
    return despacho;
}
private static void startTransmission() {

    sesion = HibernateUtil.getSession();
    sesion.getTransaction().begin();

}
private static void stopTransmission() {

    sesion.getTransaction().commit();
    sesion.getSessionFactory().getCurrentSession().close();
    sesion.clear();

}

有任何想法吗?


问题源于static Session变量。 ASessionFactory是线程安全的,一般来说,每个数据库只需要一个(静态)实例。 ASession另一方面,它不是线程安全的,通常是创建的(使用SessionFactory)并立即丢弃/关闭。

要解决您眼前的问题,请删除static Session sesion来自您的 Dao 的变量并且也“内联”startTransmission and stopTransmission中的方法findDespachoByTagId方法。这将确保每个线程调用findDespachoByTagId创建并使用自己的会话实例。为了分析当前的问题,想象两个线程调用findDespachoByTagId同时。现在静态会话变量将被赋值两次startTransmission方法。这意味着一个会话实例在创建后几乎立即丢失,而另一个会话实例同时被两个线程使用。不是什么好事。

但也存在其他问题:没有finally保证事务关闭并释放数据库连接(通过关闭会话)的块。另外,您可能需要使用数据库池,因为 Hibernate 提供的数据库池不适合生产。我推荐你看一下HibHik https://github.com/intercommit/hibhik:我创建这个项目是为了展示一个最小的独立 Java 应用程序,该应用程序使用 Hibernate 和数据库池 (HikariCP),该应用程序使用推荐的模式和实践(主要显示在TestDbCrud.java https://github.com/intercommit/hibhik/blob/master/src/test/java/com/descartes/hibhik/TestDbCrud.java)。使用应用程序中的相关部分,而不是编写多线程单元测试来验证数据库层 (DAO) 是否正常工作,即使在出现故障的情况下(例如,当数据库突然不再可用,因为网络电缆中断时)拔掉插头)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Hibernate 和多线程逻辑 的相关文章

随机推荐

  • 如何在Android中没有SQL数据库的情况下显示在线数据以供离线使用?

    我想要节目3fragments in my Activity并从中加载数据json in any fragments 我将网站数据显示到Recyclerview with OkHTTP v3图书馆 我想离线显示此数据 我的意思是如果用户关闭
  • 上下文切换线程等待

    我已经寻找这个问题的答案一天了 但找不到直接的答案 我正在阅读上下文切换等待队列之类的内容 确实很好地掌握了所有内容 在阅读一篇文章时 写到当发生车队情况时 将会有大量的上下文切换 那么让我直接说一下 假设一个线程处于等待互斥体解锁的队列中
  • 类型错误:引导日期选择器中未定义日期

    我正在使用引导日期选择器http www eyecon ro bootstrap datepicker http www eyecon ro bootstrap datepicker 但 firebug 显示 bootstrap datep
  • 在 SQLPLUS 中正确格式化表

    在这被投票为重复问题之前 我在 S O 上花了相当多的时间 试图解决这个问题 正如您在下面的屏幕截图中看到的 我的表格看起来很乱 对于第一个和第二个表 您可以看到每个表有 2 组列标题 那么 例如 我怎样才能将所有 5 条客户记录包含在一张
  • 如何将任何 mp3 文件转换为 .wav 16khz 单声道 16 位

    请帮助选择将任何 mp3 文件转换为特殊 wav 的解决方案 我是 Linux 命令行工具的新手 所以现在对我来说很难 我需要从任何 mp3 文件中获取具有 16khz 单声道 16 位声音属性的 wav 我正在尝试 ffmpeg i 11
  • 将转换后的 DataFrame 保存/导出回 JDBC / MySQL

    我正在尝试弄清楚如何使用新的DataFrameWriter将数据写回 JDBC 数据库 我似乎找不到任何相关文档 尽管查看源代码似乎应该是可能的 我正在尝试的一个简单示例如下所示 sqlContext read format jdbc op
  • 引用 dplyr across() 内的列名称

    是否可以参考专栏names在 lambda 函数里面across df lt tibble age c 12 45 sex c f f allowed values lt list age 18 100 sex c f m df gt mu
  • 在C中获取文件大小的正确方法

    我正在做一个套接字编程作业 其中我必须在 sparc 和 Linux 机器之间发送一个文件 在以字符流发送文件之前 我必须获取文件大小并告诉客户端 以下是我尝试获取尺寸的一些方法 但我不确定哪一种是合适的 出于测试目的 我创建了一个内容为
  • Glassfish 上的领域身份验证后重定向

    我目前正在 Glassfish 上运行 JPA EJB JSF 应用程序 并使用安全 JDBC 领域进行身份验证 该领域运行得很好 满足了要求 直到客户要求对导航进行小的更改 如今 如果您尝试访问受保护的页面 身份验证机制会将您重定向到 w
  • 从视频中提取音频为 wav

    我知道有一个与我类似的问题 从视频文件中提取 wav 文件 https stackoverflow com questions 1010937 extract wav file from video file 我是 C 新手 了解 COM
  • array.reduce() 方法中此语法的含义是什么?

    我正在研究一个功能性的 JavaScript 库 并发现了一个单行函数 它取数组中数字的平均值 我对语法中包含的某些内容感到困惑 但似乎不需要正确返回结果 const numArr 1 2 3 4 5 6 7 8 9 10 const av
  • 如何获取具有给定属性的所有 Unicode 字符的列表?

    如果不循环整个 Unicode 字符范围 如何获取具有给定属性的字符列表 特别是我想要一个所有数字字符的列表 即那些匹配 d 我看过Unicode UCD http perldoc perl org Unicode UCD html 它对于
  • 如何使用vue js滚动结束页面

    如何滚动到页面底部 scroll let container this el querySelector scrollingChat container scrollTop container scrollHeight 我正在这样做 并且总
  • 在 Pandas 中有效地嵌套查询/比较多个数据集

    我正在使用 Pandas 第一次 来确定人员是否满足课程出勤的先决条件 下面的代码返回所需的结果 但我确信有更好的方法来实现相同的结果 确定您是否可以学习物理的标准如下 Math A OR Math B OR Math C AND Eng
  • 父进程和子进程都可以访问记录器吗?

    在python中 如果在父进程中配置了记录器 那么子进程也会获取该记录器吗 更清楚地说 在我的应用程序中 我通过执行以下操作为父进程配置根记录器logger logging getlogger 并向其中添加处理程序 现在 当一个子进程被分叉
  • 如何使 Facebook 测试页拥有 Instagram Business 帐户?

    当您尝试为您的应用程序申请 Facebook 权限时 您可能会遇到一些需要应用审核的权限 就我而言 我需要使用Facebook登录企业帐户 因此我需要申请Facebook的App Review 为了对 Facebook 进行应用程序审核 您
  • 检查没有值的 HTML5 数据属性

    我有一个具有 HTML5 的元素data属性没有值 只有键 如下所示 div Foo div 如果我使用dataset像这样 getElementById 1 dataset foo 那么 这将返回一个空值 并且我无法区分该元素是否具有da
  • monodis 和 ikdasm 有什么区别?

    我使用的是mono 3 8 0 安装后 我发现mono bin 目录中有两个汇编程序 monodis 和 ildasm 在测试过程中 我发现生成的 il 文件不同 ikdasm 生成的文件与 MS Net 中的 ildasm exe 相同
  • C++ 数组(初学者)

    我把数组误认为是向量 抱歉 数组在瑞典语中是向量 我正在制作的程序需要一些帮助 这是一项作业 所以我真的需要了解如何做到这一点 而不仅仅是获取代码 P 我需要创建一个包含 10 个 数字 的数组 我想让它们在程序运行时可编辑 完成此操作后
  • Hibernate 和多线程逻辑

    我正在开发一个 java 独立项目 我需要在多线程应用程序中使用休眠 但我只是不知道如何正确设置它 每个线程处理其他线程的相同进程 当我以非异步方式运行它时 一切都很好 但是当我使用线程调用相同的东西时 休眠就无法正常工作 谁能解释一下在多