我在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,每次打开/关闭一个事务时都会打开和关闭一个会话。
所以,如果是真的,我只需要打开一次会话然后获得当前会话。
这是真的还是我的具体课程是对的(它运作良好,但我不知道它是否以愚蠢的方式运作!!!)
2)第二个疑问与阅读Spring文档的事实有关:http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#orm-hibernate我发现它使用的AOP服务可以调用DAO ......
所以...我的架构是如此糟糕?我有一个接口,可以使用Hibernate来实现DAO和我使用Hibernate实现DAO的具体类,我称之为在数据库上进行CRUD操作的方法
答案 0 :(得分:5)
关于#1。是的,当您在DAO的CRUD操作方法中使用@Transactional
注释时,不需要显式处理会话的打开和关闭。春天为你做到了。你需要做的就是在当前会话中调用CRUD方法,这是通过调用sessionFactory.getCurrentSession()
获得的。没有必要像在上面的代码中那样显式地打开,提交和回滚事务。当您使用@Transactional
注释方法时,Spring会为您执行此操作。
关于#2。 Spring有自己的DAO实现方式。它可能正在使用AOP。这并不意味着您的架构是错误的。使用Interface和Concrete Class实现的架构是正确的方法。我要做的是让所有CRUD操作由Base Class实现,然后让子类实现DAO Specific方法。我的意思是这个(仅给出伪代码):
interface BaseDAO {//declare all the CRUD methods}
interface PersonaDAO extends BaseDAO {//declare all Person related methods like getPersonsList}
class BaseDAOImpl implements BaseDAO {//CRUD method implementations }
class PersonaDAOImpl extends BaseDAOImpl implements PersonDAO {//implementation of Person related methods}
这样,我觉得这将是一个更好的拱门,以便您可以重用CRUD操作代码。希望这有帮助。