简体   繁体   English

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

[英]Some doubts about how implement Hibernate DAO in Spring applications

I am quite new in Spring world and I am trying to develop a DAO integrating Spring with Hibernate. 我在Spring领域还很陌生,我正在尝试开发将Spring和Hibernate集成在一起的DAO。 I have create a working project but I have some architectural doubt about it. 我创建了一个工作项目,但是对此有一些架构上的疑问。

I have create my Spring + Hibernate project basing it on the following standalone Hibernate tutorial (standalone because it don't use Spring or other framework, it is a simple Java + Hibernate project): http://www.tutorialspoint.com/hibernate/hibernate_examples.htm 我已经在以下独立的Hibernate教程的基础上创建了Spring + Hibernate项目(由于它不使用Spring或其他框架,所以是独立的,它是一个简单的Java + Hibernate项目): http : //www.tutorialspoint.com/hibernate /hibernate_examples.htm

In my project I have an interface in which I define all the CRUD method that I need and a concrete implementation of this interface, this one is the code of my concrete class: 在我的项目中,我有一个接口,在其中定义了所需的所有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) The first doubt is related to the fact that in this class, for each CRUD method I open a new session . 1)第一个疑问与以下事实有关:在此类中,对于每个CRUD方法, 我都会打开一个新会话

I have do in this way because in this tutorial: http://www.tutorialspoint.com/hibernate/hibernate_sessions.htm I have read that: 我这样做是因为在本教程中: http : //www.tutorialspoint.com/hibernate/hibernate_sessions.htm我读到了:

The Session object is lightweight and designed to be instantiated each time an interaction is needed with the database. Session对象是轻量级的,旨在在每次需要与数据库进行交互时实例化。 Persistent objects are saved and retrieved through a Session object. 持久对象通过Session对象保存和检索。 The session objects should not be kept open for a long time because they are not usually thread safe and they should be created and destroyed them as needed. 会话对象不应长时间保持打开状态,因为它们通常不是线程安全的,因此应根据需要创建和销毁它们。

But then someone say me that integrating Spring and Hibernate I don't need to open a new session in each CRUD method because if I add the @Transactional annotation to all the CRUD method the session that has been associated to the current transaction by Spring, and that will also be closed by Spring at the end of the transaction. 但是后来有人说我集成了Spring和Hibernate,因此不需要在每个CRUD方法中打开新的会话,因为如果我将@Transactional注释添加到所有CRUD方法中,那么Spring已经将其与当前事务相关联的会话,交易结束时,Spring也将关闭该服务。 It's Spring which will open and close a session each time a transaction is opened/closed. 是Spring,它将在每次打开/关闭交易时打开和关闭会话。

So, if it is true, I have to open a session only one time and then get the current session. 因此,如果是真的,我只需要打开一个会话一次,然后获取当前会话。

Is it true or my concrete class it is right (it work well but I don't know if it work in a stupid way !!!) 是真的还是我的具体班级是对的(它很好用,但我不知道它是否以愚蠢的方式工作!!!)

2) The second doubt is related to the fact that reading the Spring documentation: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#orm-hibernate I find that it use AOP services that tin turn call the DAO... 2)第二个疑问与阅读Spring文档有关: http//static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html# orm-hibernate我发现它使用的AOP服务可以调用DAO ...

So...is it my architecture so bad? 那么...我的建筑真的那么糟糕吗? I have an interface that rappresent my DAO and my concrete class that implement DAO using Hibernate and I call it's method to do CRUD operation on the DB 我有一个接口表示我的DAO和使用Hibernate实现DAO的具体类,我称其为对数据库执行CRUD操作的方法

Regarding #1. 关于#1。 Yes you do not need to explicitly handle the opening and closing of sessions when you use an @Transactional annotation in CRUD operation method of the DAO. 是的,当您在DAO的CRUD操作方法中使用@Transactional批注时,无需显式处理会话的打开和关闭。 Spring does that for you. Spring为您做到了。 All you need to do inside that is call the CRUD method on the current session, which is obtained by calling sessionFactory.getCurrentSession() . 您需要做的所有事情就是在当前会话上调用CRUD方法,该方法是通过调用sessionFactory.getCurrentSession()获得的。 There is no need to explicitly open, commit and rollback the transactions as you have done in the above code. 无需像上面的代码中那样显式打开,提交和回滚事务。 Spring will do that for you when you annotate the method with @Transactional . 当您使用@Transactional注释方法时,Spring会为您完成此操作。

Regarding #2. 关于#2。 Spring has its own way of getting to your DAO implementation. Spring有其自己的方式来实现您的DAO实现。 It might be using AOP. 它可能正在使用AOP。 That doesn't mean that your architecture is wrong. 这并不意味着您的体系结构是错误的。 Your architecture using the Interface and Concrete Class implementation is the correct way to go. 使用接口和具体类实现的体系结构是正确的方法。 What I will do is make all the CRUD operations implemented by a Base Class and then let the subclass implement the DAO Specific method. 我要做的是使所有CRUD操作都由基类实现,然后让子类实现DAO Specific方法。 What I meant is this (giving psuedo-code only): 我的意思是(仅提供伪代码):

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}

This, I feel will be a better arch, so that you can reuse the CRUD operations code. 我觉得这将是一个更好的架构,以便您可以重用CRUD操作代码。 hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM