Hibernate对Web应用程序更安全吗? [英] Is Hibernate safer for Web Applications?

查看:87
本文介绍了Hibernate对Web应用程序更安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我怀疑 Hibernate 对Web应用程序(JSP,Servlet,Hibernate,MySQL)来说是安全的,它会一次获得数千次访问用户。



我担心的原因如下。



想象一下,我有一个Web应用程序一名学校学生。他们有自己的个人资料,并会维护他们自己的学生课程,标记等等。现在,肯定有超过1个用户将始终在线,并拥有自己的配置文件。这意味着如果用户 A 编辑了他的数学符号,它将在用户 A 的配置文件中完成。它将永远不会被所有用户 A B 和'C`个档案同时在线。

Servlets 是多线程的,以提供上述支持。它使用纯JDBC可以很好地工作。它如何与 Hibernate



我也上传了我的 HibernateUtil 供您参考。在我的情况下,我称它为 SessionFactoryBuilder

  public class SessionFactoryBuilder 
{
private static SessionFactoryBuilder实例;
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());

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

}
返回实例;
}

public SessionFactory getSessionFactory()
{
return sessionFactory;
}

}


解决方案

在Hibernate中,每个应用程序都存在一个 Single SessionFactory对象

SessionFactory的内部状态是不可变的因此它是线程安全的。多线程可以同时访问它以获取Session实例。

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

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

/ **
* Hibernate Utility类用一个方法来获得Session Factory对象。
* /
public class HibernateUtil {
private static final SessionFactory sessionFactory; //创建后,其属性不能更改

static {
try {
//从标准(hibernate.cfg.xml)配置文件创建SessionFactory。

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

} catch(Throwable ex){

//记录异常。
System.err.println(Initial SessionFactory creation failed。+ ex);
抛出新的ExceptionInInitializerError(ex);



public static SessionFactory getSessionFactory(){

return sessionFactory;


$ b $ c

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

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



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

 一个典型的事务应该使用以下习惯用法:

Session sess = factory.openSession();
交易tx;
尝试{
tx = sess.beginTransaction();
//做一些工作
...
tx.commit();

catch(Exception e){
if(tx!= null)tx.rollback();
throw e;
}
finally {
sess.close();





$ b

如果会话引发异常,则必须回滚事务并且会话丢弃。 发生异常之后,会话的内部状态可能与数据库不一致。 b 2.1)列出了广泛用于获取Hibernate会话对象的两种方式。


  1. openSession //将其用于多线程环境

  2. getCurrentSession //将其用于单线程环境



Hibernate SessionFactory getCurrentSession()方法返回绑定到上下文的会话。但是为了这个工作,我们需要在hibernate配置文件中配置它。由于这个会话对象属于hibernate上下文,所以我们不需要关闭它。

 < property name =hibernate.current_session_context_class>线程< /性> 

Hibernate SessionFactory openSession()方法总是打开一个新会话。在完成所有数据库操作后,我们应关闭此会话对象。

我们应该在多线程环境中为每个请求打开一个新会话。


2.2)还有一种方法可以使用openStatelessSession()创建Hibernate 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作为后端API访问数据库。我们在多线程环境中从未遇到过这样的问题,因为我们使用了hibernate的最佳编程实践。即使DB发生任何异常,整个事务也会回滚。因此,与JDBC相比,数据库事务的ACID属性(Atomicity,Consistency,Isolation,Durability)可以以更高的成功率实现。

I have a doubt whether Hibernate is safe for web applications (JSP, Servlet, Hibernate, MySQL) where it will gain thousands of access "at once" by "different users".

The reason for my worry is something like below.

Imagine I have a web application for a school students. They have their own profile and will maintain their own student courses, marks and so on. Now, definitely more than 1 user will be online all the time, with their own profiles. That means if user A made an edit to his maths marks, it will be done in user As profile. It will never be replaced in all user A, B and 'C`s profiles who were online at the same time.

Servlets are multi threaded to provide the above support. It works pretty well as expected with pure JDBC. How is it with Hibernate ?

I have also uploaded my HibernateUtil for your reference. In my case I am calling it as 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) In Hibernate there exists a Single SessionFactory object per application.
Internal state of SessionFactory is immutable, so it’s thread safe. Multiple threads can access it simultaneously to get Session instances.

Below code depicts a standard way to get the SessionFactory instance via a Utility class.

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 is the interface between java application layer and hibernate. This is the core interface used to perform database operations. The lifecycle of a Session is bounded by the beginning and end of a logical transaction.

Hibernate Session object is not thread safe, every thread should get it’s own session instance and close it after it’s work is finished.

It is not intended/meant that implementors be threadsafe. Instead each thread/transaction should obtain its own instance from a 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();
 }

If the Session throws an exception, the transaction must be rolled back and the session discarded. The internal state of the Session might not be consistent with the database after the exception occurs.

2.1) Below listed are two ways widely used to get the Hibernate Session Object.

  1. openSession //Use this for Multi-threaded environment
  2. getCurrentSession //Use this for single threaded environment

Hibernate SessionFactory getCurrentSession() method returns the session bound to the context. But for this to work, we need to configure it in hibernate configuration file. Since this session object belongs to the hibernate context, we don’t need to close it. Once the SessionFactory is closed, this session object gets closed.

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

Hibernate SessionFactory openSession() method always opens a new session. We should close this session object once we are done with all the database operations.
We should open a new session for each request in multi-threaded environment.


2.2) There is one more way to create the Hibernate Session object using openStatelessSession() that gives you a hibernate Stateless Session.

It is a command-oriented API for performing bulk operations against a database.
A stateless session does not implement a first-level cache nor interact with any second-level cache, nor does it implement transactional write-behind or automatic dirty checking, nor do operations cascade to associated instances. Collections are ignored by a stateless session. Operations performed via a stateless session bypass Hibernate's event model and interceptors. Stateless sessions are vulnerable to data aliasing effects, due to the lack of a first-level cache.

For certain kinds of transactions, a stateless session may perform slightly faster than a stateful session.(For example: Batch processing/Bulk update)

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();

In this code example, the Customer instances returned by the query are immediately detached. They are never associated with any persistence context.

The insert(), update() and delete() operations defined by the StatelessSession interface are considered to be direct database row-level operations. They result in the immediate execution of a SQL INSERT, UPDATE or DELETE respectively.

The Stateless Session is not thread-safe, possible exception occurs while using stateless session is "org.hibernate.AssertionFailure: possible non-threadsafe access to the session"


3) Your Student records project is a multi-threaded application, so you need to be careful while using hibernate. Try to use best programming practices by opening a new session, make usage of transactions, commit and rollback and closing the session whenever needed.

I personally have used hibernate in our project where we have millions of users accessing the database via hibernate as back-end API. We never faced such issues in our multi-threaded environment, Since we used the best programming practices of hibernate. Even though any exception occurs with the DB, the entire transaction is rolled back.

Hence, the ACID properties (Atomicity, Consistency, Isolation, Durability) of database transactions can be achieved at higher success rate as compared with JDBC.

这篇关于Hibernate对Web应用程序更安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆