2016-09-26 3 views
1

Hibernateは、Webアプリケーション(JSP、Servlet、Hibernate、MySQL)で安全であるかどうかは疑いがあります。ここでは、「異なるユーザー」によって「一度に」何千ものアクセス権が得られます。HibernateはWebアプリケーションにとって安全ですか?

私の心配理由は以下のようなものです。

私は学校の学生のためのWebアプリケーションがあるとします。彼らは自分のプロフィールを持っており、彼ら自身の学生のコース、マークなどを維持します。今、確かに1人以上のユーザーが、常に自分のプロファイルでオンラインになります。つまり、ユーザーAが数学記号を編集した場合は、ユーザーAのプロフィールで処理されます。それは、すべてのユーザA,Bと同時にオンラインになった 'C`のプロファイルに置き換えられることはありません。

Servletsは、上記のサポートを提供するためにマルチスレッドです。純粋なJDBCで期待通りに動作します。 Hibernateとはどうですか?

私はHibernateUtilもアップロードしました。私の場合は、アプリケーションごとにシングルのSessionFactoryオブジェクトが存在休止状態では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

はいハイバーネーションは安全に使用できます。それだけでORMの関係を提供します...残りはすべてJDBCとかなり同じです – Naruto

+0

@ Naruto:複数のユーザーが同時にオンラインになり、データが重複しない私の例でさえ、 –

+0

@ドリュー:errr ....私は混乱していますか? –

答えて

4

1)としてそれを呼び出しています。
SessionFactoryの内部状態は不変ですのでスレッドセーフです。複数のスレッドが同時にアクセスして、セッションインスタンスを取得できます。

以下のコードは、ユーティリティクラスを介して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)休止セッションは、Javaアプリケーション層と休止状態との間のインターフェースです。これは、データベース操作を実行するために使用されるコアインターフェイスです。 セッションのライフサイクルは、論理トランザクションの開始と終了によって制限されます。

Hibernateセッションオブジェクトはスレッドセーフではありません、すべてのスレッドは独自のセッションインスタンスを取得し、作業が終了したら閉じます。

実装者がスレッドセーフであることを意図したものではありません。代わりに、各スレッド/トランザクションは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(); 
} 

セッションで例外がスローされた場合は、トランザクションをロールバックしてセッションを破棄する必要があります。 例外が発生した後、セッションの内部状態がデータベースと一貫しない可能性があります。

2.1)下記は、Hibernateセッションオブジェクトを取得するために広く使用される2つの方法です。

  1. のOpenSession // getCurrentSessionは// シングルスレッド環境

のHibernateのSessionFactory getCurrentSession()メソッドの戻りのためにこれを使用マルチスレッド環境に

  • をこれを使用コンテキストにバインドされたセッションしかし、これが動作するためには、ハイバネート設定ファイルで設定する必要があります。このセッションオブジェクトはハイバネートコンテキストに属しているため、セッションオブジェクトを閉じる必要はありません。 SessionFactoryが閉じられると、このセッションオブジェクトは閉じられます。

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

    にHibernateのSessionFactory のOpenSession()メソッド常に新しいセッションを開きます。我々はを閉じるこのセッションオブジェクトは、すべてのデータベース操作を完了した後に行う必要があります。
    マルチスレッド環境では、リクエストごとに新しいセッションを開く必要があります。


    2.2)openStatelessSessionを(使用してオブジェクトのHibernateのSessionを作成するためのもう一つの方法は、あなたの休止状態ステートレスセッションを与えること)があります。

    データベースに対して一括操作を実行するためのコマンド指向のAPIです。
    ステートレスセッションは、第1レベルのキャッシュを実装したり、第2レベルのキャッシュと対話したり、トランザクショナルな書き込みビハインドや自動ダーティチェックを実装したり、関連するインスタンスに操作をカスケードしたりしません。コレクションはステートレスセッションによって無視されます。ステートレスセッションを介して実行される操作は、Hibernateのイベントモデルとインターセプタをバイパスします。ステートレスセッションは、第1レベルのキャッシュがないためにデータエイリアシングの影響を受け易い。トランザクションの特定の種類の

    は、ステートレスセッションは、ステートフル・セッションよりもわずかに速く実行することができる(例:バッチ処理/一括更新)。このコード例では

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

    、顧客インスタンスが返さクエリによってすぐに切り離されます。それらは永続コンテキストと決して関連付けられません。

    StatelessSessionインタフェースで定義されたinsert()、update()およびdelete()操作は、データベースの直接行レベル操作と見なされます。 SQL INSERT、UPDATEまたはDELETEがそれぞれ即座に実行されます。

    ステートレスセッションステートレスセッションを使用する「org.hibernate.AssertionFailure:セッションに可能非スレッドセーフアクセス」の間の可能な例外が発生し、をスレッドセーフではない


    3)学生レコードプロジェクトはマルチスレッドアプリケーションなので、Hibernateの使用中は注意が必要です。新しいセッションを開いたり、トランザクションを使用したり、コミットしたりロールバックしたり、必要に応じてセッションを閉じたりすることで、最高のプログラミング方法を試してみてください。

    私は個人的に、バックエンドAPIとしてhibernateを介してデータベースにアクセスしている何百万人ものユーザーがいる私たちのプロジェクトでhibernateを使用しました。私たちは、マルチスレッド環境でこのような問題に直面したことはありませんでした。私たちは、休止状態の最高のプログラミング手法を使用していたからです。 DBで例外が発生しても、トランザクション全体がロールバックされます。

    したがって、JDBCと比較して、データベーストランザクションのACIDプロパティ(アトミック性、一貫性、分離性、耐久性)を高い成功率で達成できます。

  • +0

    OKこれで、Hibernateは何千ものWebアプリケーションで安全です。つまり、Hibernateは安全です。ユーザーは一度にアクセスできますか?(はい、開閉セッションとトランザクションロールバックがこれを達成するために必要です)。**あなたの回答で**エラーが発生した場合はロールバックする必要があります**これは 'selectステートメント 'にも当てはまりますが、JDBCでは' select'にロールバックするものはないので、それはしません? –

    +0

    はい、Webアプリケーションの安全です。選択されたクエリは決してデータベースの状態を変更しないためです。 –

    +0

    ありがとうございます。だから私は何を使うべきですか? 'getCurrentSession()'または 'openSession()'?私は 'openSession()'を使用しています –

    関連する問題