关于如何在Spring应用程序中实现Hibernate DAO的一些疑问

And*_*ili 1 java spring hibernate spring-mvc

我是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();
        }   

    }

}
Run Code Online (Sandbox Code Playgroud)

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和我的具体类,我调用它的方法在数据库上进行CRUD操作

Dha*_*ath 5

关于#1.是的,当您@Transactional在DAO的CRUD操作方法中使用注释时,不需要显式处理会话的打开和关闭.春天为你做到了.你需要做的就是在当前会话中调用CRUD方法,这是通过调用获得的sessionFactory.getCurrentSession().没有必要像在上面的代码中那样显式地打开,提交和回滚事务.当您使用注释方法时,Spring将为您执行此操作@Transactional.

关于#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}
Run Code Online (Sandbox Code Playgroud)

这样,我觉得将是一个更好的拱门,以便您可以重用CRUD操作代码.希望这可以帮助.