私はSpringの世界ではまったく新しく、SpringとHibernateを統合するDAOを開発しようとしています。作業中のプロジェクトを作成しましたが、それについて建築上の疑問があります。
次のスタンドアロンの Hibernate チュートリアルに基づいて、Spring + Hibernate プロジェクトを作成しました (Spring や他のフレームワークを使用しないためスタンドアロンであり、単純な Java + Hibernate プロジェクトです): http://www.tutorialspoint.com/hibernate /hibernate_examples.htm
私のプロジェクトでは、必要なすべての CRUD メソッドを定義するインターフェイスと、このインターフェイスの具体的な実装があります。これは私の具体的なクラスのコードです。
package org.andrea.myexample.HibernateOnSpring.dao;
import java.util.List;
import org.andrea.myexample.HibernateOnSpring.entity.Person;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.springframework.transaction.annotation.Transactional;
public class PersonDAOImpl implements PersonDAO {
// Factory per la creazione delle sessioni di Hibernate:
private static SessionFactory sessionFactory;
// Metodo Setter per l'iniezione della dipendenza della SessionFactory:
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/** CREATE CRUD Operation:
* Aggiunge un nuovo record rappresentato nella tabella rappresentato
* da un oggetto Person
*/
@Transactional(readOnly = false)
public Integer addPerson(Person p) {
System.out.println("Inside addPerson()");
Session session = sessionFactory.openSession();
Transaction tx = null;
Integer personID = null;
try {
tx = session.beginTransaction();
personID = (Integer) session.save(p);
tx.commit();
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return personID;
}
// READ CRUD Operation (legge un singolo record avente uno specifico id):
public Person getById(int id) {
System.out.println("Inside getById()");
Session session = sessionFactory.openSession();
Transaction tx = null;
Person retrievedPerson = null;
try {
tx = session.beginTransaction();
retrievedPerson = (Person) session.get(Person.class, id);
tx.commit();
}catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return retrievedPerson;
}
// READ CRUD Operation (recupera la lista di tutti i record nella tabella):
@SuppressWarnings("unchecked")
public List<Person> getPersonsList() {
System.out.println("Inside getPersonsList()");
Session session = sessionFactory.openSession();
Transaction tx = null;
List<Person> personList = null;
try {
tx = session.beginTransaction();
Criteria criteria = session.createCriteria(Person.class);
personList = criteria.list();
System.out.println("personList: " + personList);
tx.commit();
}catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return personList;
}
// DELETE CRUD Operation (elimina un singolo record avente uno specifico id):
public void delete(int id) {
System.out.println("Inside delete()");
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Person personToDelete = getById(id);
session.delete(personToDelete);
tx.commit();
}catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
@Transactional
public void update(Person personToUpdate) {
System.out.println("Inside update()");
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
System.out.println("Insite update() method try");
tx = session.beginTransaction();
session.update(personToUpdate);
tx.commit();
}catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
1) 最初の疑問は、このクラスでは、CRUD メソッドごとに新しいセッションを開くという事実に関連しています。
このチュートリアルでは、 http://www.tutorialspoint.com/hibernate/hibernate_sessions.htmを読んだので、私はこのようにしました:
Session オブジェクトは軽量で、データベースとの対話が必要になるたびにインスタンス化されるように設計されています。永続オブジェクトは、Session オブジェクトを介して保存および取得されます。通常、セッション オブジェクトはスレッド セーフではなく、必要に応じて作成および破棄する必要があるため、セッション オブジェクトを長時間開いたままにしないでください。
しかし、Spring と Hibernate を統合することで、各 CRUD メソッドで新しいセッションを開く必要はないと誰かが私に言いました。@Transactional アノテーションをすべての CRUD メソッドに追加すると、Spring によって現在のトランザクションに関連付けられているセッションこれも、トランザクションの終了時に Spring によってクローズされます。トランザクションが開閉されるたびにセッションを開閉するのはSpringです。
したがって、それが本当なら、セッションを 1 回だけ開いて、現在のセッションを取得する必要があります。
それは本当ですか、それとも私の具象クラスは正しいですか(うまく機能しますが、愚かな方法で機能するかどうかはわかりません!!!)
2) 2 番目の疑問は、Spring のドキュメントを読むという事実に関連しています。 orm-hibernate DAO を順番に呼び出す AOP サービスを使用していることがわかります...
それで...私のアーキテクチャはとても悪いですか?DAO と Hibernate を使用して DAO を実装する具象クラスを rappresent するインターフェイスがあり、そのメソッドを呼び出して DB で CRUD 操作を行います