Hibernate 对于 Web 应用程序来说更安全吗?

2024-03-30

我有疑问是否Hibernate对于 Web 应用程序(JSP、Servlet、Hibernate、MySQL)来说是安全的,它将获得“不同用户”“一次”的数千个访问。

我担心的原因如下。

想象一下,我有一个供学校学生使用的网络应用程序。他们有自己的个人资料,并会维护自己的学生课程、分数等。现在,肯定会有超过 1 个用户始终在线,并拥有自己的个人资料。这意味着如果用户A对其数学成绩进行了编辑,这将在用户中完成A的个人资料。在所有用户中永远不会被替换A, B和'C'的个人资料同时在线。

Servlets都是多线程来提供上述支持。它与纯 JDBC 一起工作得非常好。怎么样?Hibernate ?

我也上传了我的HibernateUtil供你参考。就我而言,我将其称为SessionFactoryBuilder

public class SessionFactoryBuilder
{
    private static SessionFactoryBuilder instance;
    private static SessionFactory sessionFactory;

    private SessionFactoryBuilder()
    {
        buildConfig();
        System.out.println("hehehehe");
    }

    private static void buildConfig()
    {
        Configuration configuration = new Configuration().configure();
            StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties());
            sessionFactory = configuration.buildSessionFactory(builder.build());
    }

    public static SessionFactoryBuilder getInstance()
    {
         if(instance == null)
         {
            instance = new SessionFactoryBuilder();

         }
      return instance;
    }

    public SessionFactory getSessionFactory()
    {
        return sessionFactory;
    }

}

1)在 Hibernate 中存在一个单个 SessionFactory 对象每个应用程序。
SessionFactory的内部状态是不可变的, 所以它是线程安全的。多个线程可以同时访问它以获取 Session 实例。

下面的代码描述了通过实用程序类获取 SessionFactory 实例的标准方法。

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

/**
 * Hibernate Utility class with a method to get Session Factory object.
 */
public class HibernateUtil {
private static final SessionFactory sessionFactory;//Once created, its properties cannot be changed

static {
    try {
        // Create the SessionFactory from standard (hibernate.cfg.xml) config file.

        sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();

    } catch (Throwable ex) {

        // Log the exception.
        System.err.println("Initial SessionFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

public static SessionFactory getSessionFactory() {

    return sessionFactory;

}
}

2)休眠Session是java应用层和hibernate之间的接口。这是用于执行数据库操作的核心接口。 会话的生命周期受逻辑事务的开始和结束的限制。

Hibernate Session 对象不是线程安全的,每个线程都应该获取自己的会话实例,并在工作完成后关闭它。

这并不意味着实现者是线程安全的。相反,每个线程/事务应该从 SessionFactory 获取自己的实例。

A typical transaction should use the following idiom:

 Session sess = factory.openSession();
 Transaction tx;
 try {
     tx = sess.beginTransaction();
     //do some work
     ...
     tx.commit();
     }
 catch (Exception e) {
    if (tx!=null) tx.rollback();
    throw e;
 }
 finally {
      sess.close();
 }

如果会话抛出异常,则必须回滚事务并丢弃会话。异常发生后Session的内部状态可能与数据库不一致。

2.1)下面列出了两种广泛用于获取 Hibernate Session 对象的方法。

  1. 开放会话//用这个来多线程环境
  2. 获取当前会话//用这个来单线程环境

Hibernate会话工厂getCurrentSession() 方法返回绑定到上下文的会话。但要使其工作,我们需要在 hibernate 配置文件中对其进行配置。由于这个会话对象属于hibernate上下文,所以我们不需要关闭它。一旦 SessionFactory 关闭,该会话对象也将关闭。

<property name="hibernate.current_session_context_class">thread</property>

Hibernate会话工厂打开会话()方法总是打开一个新会话。我们应该close一旦我们完成了所有的数据库操作,这个会话对象。
我们应该在多线程环境中为每个请求打开一个新会话。


2.2) 还有一种使用 openStatelessSession() 创建 Hibernate Session 对象的方法,它为您提供了一个 hibernate Stateless Session。

它是一个面向命令的 API,用于对数据库执行批量操作。
无状态会话不实现一级缓存,也不与任何二级缓存交互,也不实现事务性后写或自动脏检查,也不将操作级联到关联的实例。无状态会话会忽略集合。通过无状态会话执行的操作绕过 Hibernate 的事件模型和拦截器。由于缺乏一级缓存,无状态会话容易受到数据别名效应的影响。

对于某些类型的事务,无状态会话的执行速度可能比有状态会话稍快。(例如:批处理/批量更新)

StatelessSession session = sessionFactory.openStatelessSession();
Transaction tx = session.beginTransaction();

ScrollableResults customers = session.getNamedQuery("GetCustomers")
.scroll(ScrollMode.FORWARD_ONLY);
while ( customers.next() ) {
Customer customer = (Customer) customers.get(0);
customer.updateStuff(...);
session.update(customer);
}

tx.commit();
session.close();

在此代码示例中,查询返回的 Customer 实例立即分离。它们从不与任何持久性上下文相关联。

StatelessSession接口定义的insert()、update()和delete()操作被认为是直接的数据库行级操作。它们分别导致立即执行 SQL INSERT、UPDATE 或 DELETE。

无状态会话不是线程安全的,使用无状态会话时可能发生的异常是“org.hibernate.AssertionFailure:可能对会话进行非线程安全访问”


3)您的学生记录项目是一个多线程应用程序,因此在使用 hibernate 时需要小心。尝试通过打开新会话、使用事务、提交和回滚以及在需要时关闭会话来使用最佳编程实践。

我个人在我们的项目中使用了 hibernate,我们有数百万用户通过 hibernate 作为后端 API 访问数据库。我们在多线程环境中从未遇到过此类问题,因为我们使用了 hibernate 的最佳编程实践。即使数据库发生任何异常,整个事务也会回滚。

因此,与 JDBC 相比,可以以更高的成功率实现数据库事务的 ACID 属性(原子性、一致性、隔离性、持久性)。

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

Hibernate 对于 Web 应用程序来说更安全吗? 的相关文章

  • 想要从java中的char数组创建字符流

    我想从 char 数组构造一个流以使用 java 8 功能 例如过滤器和映射 char list a c e Stream
  • Apache Commons VFS - 无法解析文件

    VFS 方法无法处理此 URI jboss server temp dir local outgoing配置在jboss beans xml这是决心 C Download jboss eap 5 1 1 server default tmp
  • 为什么我的 @OneToMany 属性出现主键违规?

    我有一个实体 Entity public class Student GeneratedValue strategy GenerationType AUTO Id private long id OneToMany private Set
  • 在 BIRT 中输入参数后更新数据集查询

    在 BIRT 报告设计中传递参数后 如何更改或更新数据集的查询 详细说明 我有一个如下所示的查询 WHERE 该参数标记可以保存不同的值 在用户输入参数后 它看起来像这样 例如 WHERE column name 1 or WHERE co
  • 锁定 ASP.NET 应用程序变量

    我在 ASP NET 应用程序中使用第三方 Web 服务 对第 3 方 Web 服务的调用必须同步 但 ASP NET 显然是多线程的 并且可能会发出多个页面请求 从而导致对第 3 方 Web 服务的同时调用 对 Web 服务的调用封装在自
  • 为本地@ExceptionHandler编写JUnit测试

    我有以下控制器 class Controller ResponseStatus HttpStatus OK RequestMapping value verifyCert method RequestMethod GET public vo
  • 使用java在网页中进行字符编码

    如何使用java找出网页中的字符编码类型 打开与 URL 的连接 使用URL openConnection http download oracle com javase 6 docs api java net URL html openC
  • ODBC 链接表中突然开始出现写入冲突消息

    我有一个 mySQL 数据库 用于跟踪我们的项目并驱动我们的网站显示其信息 为了方便更新数据库 我设置了一个使用 ODBC 连接 MySQL ODBC 5 1 来编辑数据的访问数据库 过去几个月一直运行良好 没有出现任何问题 然而 昨晚用户
  • 如何构建和使用 TimeSeriesCollections

    我想在图表的 X 轴上显示一些日期 并且here https stackoverflow com questions 5118684 jfreechart histogram with dates据说我必须使用 TimeSeriesColl
  • 在Java中将日期“2020-05-22T12:51:20.765111Z”解析为Instant [重复]

    这个问题在这里已经有答案了 如何解析 2020 05 22T12 51 20 732111Z Java 中的 Instant I used LocalDateTime parse startTime DateTimeFormatter of
  • EJB 中 @Stateless 相对于 @Singleton 的真正用例是什么

    如果我正确理解EJB Singleton实际上与普通Java中的Singleton相同 也是spring中的单例 gt 一个实例 每个调用同时通过同一个实例 Stateless 声明一个 bean 它可以 但不得 具有多个实例 但限制是一个
  • Java:java.util.Preferences 失败

    我的程序将加密的产品密钥数据保存到计算机上java util Preferences类 系统首选项 而不是用户 问题是 在 Windows 和 Linux 上 尚未在 OSX 上测试过 但可能是相同的 如果我不运行该程序sudo或者具有管理
  • Java给定长度的随机数

    我需要在 Java 中生成一个恰好 6 位数字的随机数 我知道我可以在随机发生器上循环 6 次 但是在标准 Java SE 中还有其他方法可以做到这一点吗 要生成 6 位数字 Use Random http download oracle
  • 一个类中有多个具有相同参数类型的方法

    我知道 至少已经有了关于这个主题的一个问题 https stackoverflow com questions 5561436 can two java methods have same name with different retur
  • 根据最大值连接表

    这是我正在谈论的内容的一个简化示例 Table students exam results id name id student id score date 1 Jim 1 1 73 8 1 09 2 Joe 2 1 67 9 2 09 3
  • MYSQL 按喜欢/不喜欢和受欢迎程度排序

    我有评论表 其中包括喜欢和不喜欢的内容 现在我在正确的顺序上遇到了问题 实际上 我的系统在顶部显示了最多点赞的评论 我正在 youtube 上寻找类似系统的东西 这意味着 100like 100dislikes 的评论的顺序高于 1 1 我
  • while循环只执行一次

    我很难弄清楚为什么 while 循环实际上不会循环 它运行一次并停止 import java util public class mileskm public static void main String args Scanner inp
  • 如何让JComboBox中的内容居中显示?

    目前我有这个JComboBox 我怎样才能将其中的内容居中 String strs new String 15158133110 15158133124 15158133458 JComboBox com new JComboBox str
  • Swing:创建可拖动组件...?

    我在网上搜索了可拖动 Swing 组件的示例 但我发现示例不完整或不起作用 我需要的是一个摇摆组件那可以是dragged通过鼠标 在另一个组件内 被拖拽的时候 应该已经 改变它的位置 而不仅仅是 跳 到目的地 我很欣赏无需非标准 API 即
  • 在 for 循环比较中使用集合大小

    Java 中 Collections 的 size 方法是否有编译器优化 考虑以下代码 for int i 0 i

随机推荐