Hibernateで「1セッションあたりのHTTPリクエスト」パターンを実装しようとしていて、1回目のリクエストで機能します:サーブレットのdoGetいくつかのものを取得し、セッションを閉じます。シングルトンのDAOインスタンスは、HTTPトランザクション間で古いクローズドセッションを維持します
しかし、ブラウザを更新すると、My DAO Singletonインスタンス(そのコンストラクタがSessionFactoryからセッションを取得します)が2回目に呼び出されますが、古いセッションオブジェクト(シングルトンコンストラクタはまだ呼び出されません)が使用されます。私は "セッションが閉じている"エラーを取得します。
シングルトンのインスタンスをHTTPリクエスト間でキャッシュに保存する必要があると思います。どうすればDAOシングルトンコンストラクタを再度呼び出すことができますか? (または別のエレガントな解決策は、新鮮なSessionFactoryのセッションオブジェクトを持っている?)
が
サーブレットありがとうございました:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
// Gets the session, eventually creates one
Session s = HibernateUtil.currentSession();
// Gets data from singleton DAO instance
MySingletonDAO o = MySingletonDAO.getInstance();
List<Stuff> stuff = o.getAllTheStuff();
// send it to the view
request.setAttribute("foo",stuff);
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(vue);
dispatcher.forward(request, response);
}
/* error handling blah blah */
finally {
// closing the session
HibernateUtil.closeSession();
}
MySingletonDAO.java:
public class MySingletonDAO {
// Usual singleton syntax
private static MySingletonDAO INSTANCE = new MySingletonDAO();
public static MySingletonDAO getInstance() { return INSTANCE;}
private Session session;
private MySingletonDAO() {
session = HibernateUtil.currentSession();
System.out.println("This constructor is called only on the first HTTP transaction");
}
public List<Stuff> getAllTheStuff() {
try {
session.beginTransaction();
Query q = session.createQuery("FROM StuffDBTable");
session.getTransaction().commit();
return (List<Stuff>) q.list();
}
}
}
古典スレッド-safe HibernateUtil.java:
public class HibernateUtil {
private static final SessionFactory sessionFactory;
public static final ThreadLocal session = new ThreadLocal();
static {
try {
// Creates the SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (HibernateException he) {
throw new RuntimeException("Conf problem : "+ he.getMessage(), he);
}
}
public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
// Opens a new Session, if this Thread has none
if (s == null || !s.isOpen()) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}
}
サービスレイヤーは私が必要としていた手がかりで、なぜモデルがトランザクションとセッションを管理しなければならないのかわかりませんでした。 私はあなたの役に立つ指示を(ブラウジングの少し後に)正確に得ると、サーブレットとDAOメソッド間の中間層として働き、トランザクション、エラー、返されたオブジェクトの扱いといった二次懸念を管理します。 将来の読者の皆様には、大きな写真を手に入れるためのこのリンクを提案してください: https://msdn.microsoft.com/en-us/library/ee658090.aspx – Yow