java - Hibernate对于Web应用程序更安全吗?

标签 java mysql multithreading hibernate servlets

我怀疑Hibernate对于Web应用程序(JSP,Servlet,Hibernate,MySQL)是否安全,在Web应用程序中“不同的用户”可以一次获得数千次访问。

我担心的原因如下。

想象一下,我有一个针对学校学生的Web应用程序。他们有自己的个人资料,并将维护自己的学生类(class),成绩等。现在,肯定有1个以上的用户将始终使用自己的个人资料在线。这意味着,如果用户A对他的数学标记进行了编辑,则将在用户A的配置文件中完成。永远不会同时在线的所有用户AB和'C`s个人资料中替换它。
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中,每个应用程序都有一个 Single SessionFactory对象
SessionFactory的内部状态为不变,因此它是线程安全的。多个线程可以同时访问它以获取Session实例。

下面的代码描述了通过Utility类获取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) hibernate session 是Java应用程序层和 hibernate 之间的接口(interface)。这是用于执行数据库操作的核心接口(interface)。
session 的生命周期受逻辑事务的开始和结束的限制。

hibernate session 对象不是线程安全的,每个线程都应获取其自己的 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 引发异常,则必须回滚事务并丢弃 session 。 发生异常后, session 的内部状态可能与数据库不一致。

2.1)下面列出了两种广泛用于获取Hibernate Session Object的方法。
  • openSession //用于多线程环境
  • getCurrentSession //将其用于单线程环境

  • Hibernate SessionFactory的 getCurrentSession()方法返回绑定(bind)到上下文的 session 。 但是,要使其正常工作,我们需要在 hibernate 配置文件中对其进行配置。由于此 session 对象属于 hibernate 上下文,因此我们无需关闭它。一旦SessionFactory关闭,该 session 对象就被关闭。
    <property name="hibernate.current_session_context_class">thread</property>
    

    Hibernate SessionFactory openSession()方法始终打开一个新 session 。一旦完成所有数据库操作,就应该关闭该 session 对象。
    我们应该在多线程环境中为每个请求打开一个新 session 。

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

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

    对于某些类型的事务,无状态 session 的执行速度可能比有状态 session 的执行速度稍快。(例如:批处理/批量更新)
    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接口(interface)定义的insert(),update()和delete()操作被视为直接数据库行级操作。它们分别导致立即执行SQL INSERT,UPDATE或DELETE。

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

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

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

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

    关于java - Hibernate对于Web应用程序更安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39694677/

    相关文章:

    java - 类不会在 GWT 应用程序中序列化

    java - 将字符串中的字符替换为其他字符会产生异常

    javascript - node.js 集群、redis、单线程和非阻塞 i/o 是如何工作的?

    multithreading - 复杂系统中的死锁预防

    java - 关于将 GUI 程序制作为 exe 文件.... (Java)

    java - 如何使用更改监听器 JavaFX 在两个 ListView 之间移动项目

    mysql - 简单的MySQL查询问题

    Php Sql 获取值

    php - PDO SELECT WHERE 不起作用

    java - Hibernate 上的多线程 'session.flush'