1

Hibernate を使用して、データベース テーブルでCRUD操作を実行する DAO を実装する簡単なサンプル アプリケーションを開発しています。

私のアプリケーションは正常に動作しますが、おそらく Java の使用における私のペルソナのギャップに関連しているのではないかと疑っています。

私のアプリケーション アーキテクチャには、HibernateDAOという名前のインターフェイスがあります。このインターフェイスでは、次のようなCRUD メソッドのみを宣言します。

package org.andrea.myH8.myH8HelloWorld;

public interface HibernateDAO {


    // Operazione di CREATE:
    public Integer addEmployee(String fname, String lname, int salary);

    // Operazione di READ:
    public void listEmployees();

    // Operazione di UPDATE:
    public void updateEmployee(Integer EmployeeID, int salary);

    // Operazione di DELETE:
    public void deleteEmployee(Integer EmployeeID);

}

次に、前のインターフェイスを実装する具体的なクラスを用意し、このクラスの名前をHibernateDAOImplとします。

package org.andrea.myH8.myH8HelloWorld;

import java.util.List;
import java.util.Date;
import java.util.Iterator;

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;

// Classe principale contenente il metodo main():
public class HibernateDAOImpl implements HibernateDAO {


    // Factory per la creazione delle sessioni di Hibernate:
    private static SessionFactory factory;

    /** Registratore di servizzi che contiene, gestisce e fornisce l'accesso
     *  ai servizzi registrati:
     */
    private static ServiceRegistry serviceRegistry;

    public HibernateDAOImpl() {

        try {

            /** Un'istanza di Configuration consente all'applicazione di specificare le 
             *  proprietà ed il documento di mapping tra oggetti da persistere e dabelle
             *  che devono essere utilizzati durante la creazione di una SessionFactory
             */

            Configuration configuration = new Configuration();
            /** Per la configurazione di Hibernate utilizza le proprietà specificate nel
             * file XML di configurazione avente nome standard hibernate.cfg.xml:
             */
            configuration.configure();

            /** ServiceRegistry crea un'istanza di ServiceRegistry (il registratore di servizzi)
             *  alla quale vengono applicati un gruppo di settaggi contenuti dentro le proprietà
             *  dell'oggetto configuration.
             *  Infine il registratore di Service creato viene costruito in base a tutte le
             *  impostazioni specificate.
             */
            serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();

            /** Crea l'istanza della SessionFactory usando le proprietà ed i mapping
             *  definiti in questa configurazione
             */
            factory = configuration.buildSessionFactory(serviceRegistry);

        } catch (Throwable ex) {    // Se viene sollevata un'eccezione la gestisce
            System.err.println("Failed to create sessionFactory object." + ex);
            throw new ExceptionInInitializerError(ex);
        }


    }


    /** Metodo relativo all'operazione CREATE di un record nella tabella EMPLOYEE:
     * 
     * @param fname nome
     * @param lname cognome
     * @param salary salario
     * @return l'identificativo intero univoco che rappresenta l'impiegato
     */

    public Integer addEmployee(String fname, String lname, int salary) {

        // Crea e mette nella connection pool la connessione JDBC:
        Session session = factory.openSession();    

        Transaction tx = null;          // Rappresenta una transazione
        Integer employeeID = null;      // Identificativo univoco impiegato

        try {
            // Inizia un'unità di lavoro e ritorna la transazione ad essa associata:
            tx = session.beginTransaction();

            // Crea un nuovo oggetto Employee:
            Employee employee = new Employee(fname, lname, salary);

            /** Persiste l'istanza transiente data ed in primo luogo gli assegna 
             *  un identificatore univoco  autogenerato
             */
            employeeID = (Integer) session.save(employee);
            tx.commit();                    // Esegue la commit della transazione
        } catch (HibernateException e) {    // Se viene sollevata un'eccezione:
            if (tx != null)                 // Se la transazione non è nulla
                tx.rollback();      // Esegue la rollback e riporta alla situazione iniziale
            e.printStackTrace();
        } finally {                 // Alla fine:
            // Chiude la sessione rilasciando la connessione JDBC e facendo il cleanup:
            session.close();    
        }
        return employeeID;
    }

    /* Metodo usato per elencare tutti i record presenti nella tabella EMPLOYEE: */
    public void listEmployees() {

        // Crea e mette nella connection pool la connessione JDBC:
        Session session = factory.openSession();
        Transaction tx = null;                  // Rappresenta una transazione

        try {
            // Inizia un'unità di lavoro e ritorna la transazione ad essa associata:
            tx = session.beginTransaction();

            /** Crea la query usando una stringa HQL per ottenere tutti i record
             *  ed ottiene la lista di tutti i record rappresentati ognuno da un
             *  oggetto Employee 
             */
            List employees = session.createQuery("FROM Employee").list();

            // Stampa i valori delle proprietà di ogni oggett nella lista:
            for (Iterator iterator = employees.iterator(); iterator.hasNext();) {
                Employee employee = (Employee) iterator.next();
                System.out.print("First Name: " + employee.getFirstName());
                System.out.print("  Last Name: " + employee.getLastName());
                System.out.println("  Salary: " + employee.getSalary());
            }
            tx.commit();                    // Esegue la commit della transazione
        } catch (HibernateException e) {    // Se viene sollevata un'eccezione:
            if (tx != null)                 // Se la transazione non è nulla
                tx.rollback();          // Esegue la rollback e riporta alla situazione iniziale
            e.printStackTrace();
        } finally {                 // Alla fine:
            // Chiude la sessione rilasciando la connessione JDBC e facendo il cleanup:
            session.close();
        }
    }

    /** Metodo che aggiorna il salario di un impiegato
     * 
     *  @param EmployeeID l'ID univoco che identifica il record nella tabella EMPLOYEE
     *  @param salary il nuovo salario dell'impiegato rappresentato dal record
     */
    public void updateEmployee(Integer EmployeeID, int salary) {

        // Crea e mette nella connection pool la connessione JDBC:
        Session session = factory.openSession();
        Transaction tx = null;              // Rappresenta una transazione

        try {
            // Inizia un'unità di lavoro e ritorna la transazione ad essa associata:
            tx = session.beginTransaction();

            /**
             * Ritorna l'istanza persistita sul database della classe fornita come
             * parametro di input avente l'identificatore fornito come parametro
             * di input. Se non esiste un tale oggetto persistito nel database 
             * allora ritorna null.
             */
            Employee employee = (Employee) session.get(Employee.class,
                    EmployeeID);

            employee.setSalary(salary);     // Setta il nuovo valore del salario
            session.update(employee);       // Esegue l'update di tale oggetto
            tx.commit();                    // Esegue la commit della transazione
        } catch (HibernateException e) {    // Se viene sollevata un'eccezione:
            if (tx != null)                 // Se la transazione non è nulla
                tx.rollback();          // Esegue la rollback e riporta alla situazione iniziale    
            e.printStackTrace();
        } finally {                     // Alla fine:
            // Chiude la sessione rilasciando la connessione JDBC e facendo il cleanup:
            session.close();
        }
    }

    /** Metodo che elimina un record dalla tabella EMPOLYEE
     * 
     *  @param EmployeeID l'ID univoco che identifica il record nella tabella EMPLOYEE 
     */
    public void deleteEmployee(Integer EmployeeID) {

        // Crea e mette nella connection pool la connessione JDBC:
        Session session = factory.openSession();
        Transaction tx = null;              // Rappresenta una transazione

        try {
            // Inizia un'unità di lavoro e ritorna la transazione ad essa associata:
            tx = session.beginTransaction();

            /**
             * Ritorna l'istanza persistita sul database della classe fornita come
             * parametro di input avente l'identificatore fornito come parametro
             * di input. Se non esiste un tale oggetto persistito nel database 
             * allora ritorna null.
             */
            Employee employee = (Employee) session.get(Employee.class,
                    EmployeeID);


            session.delete(employee);       // Rimuove l'oggetto dalla tabella del database:
            tx.commit();                    // Esegue la commit della transazione
        } catch (HibernateException e) {    // Se viene sollevata un'eccezione:
            if (tx != null)                 // Se la transazione non è nulla
                tx.rollback();          // Esegue la rollback e riporta alla situazione iniziale
            e.printStackTrace();
        } finally {                     // Alla fine:
            // Chiude la sessione rilasciando la connessione JDBC e facendo il cleanup:
            session.close();
        }
    }
}

OK、エンティティ クラス Person を省略します。最後のクラスは、このクラスの動作をテストするために使用する main() メソッドを含むMainAppクラスです。

パッケージ org.andrea.myH8.myH8HelloWorld;

パブリッククラス MainApp {

public static void main(String[] args) {

    // Creo una nuova istanza dell'oggetto DAO per interagire con il database:
    HibernateDAO ME = new HibernateDAOImpl();

    System.out.println("CREAZIONE DEI RECORD:");
    // Inserisce 3 record nella tabella EMPLOYEE sul DB:
    Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
    Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
    Integer empID3 = ME.addEmployee("John", "Paul", 10000);


    // Elenca tutti i record della tabella EMPLOYEE:
    System.out.println("ELENCA TUTTI I RECORD:");
    ME.listEmployees();

    // Update del record avente id corrispondente al valore della variabile empID1
    System.out.println("Update del record avente id corrispondente al valore: " + empID1);
    ME.updateEmployee(empID1, 5000);

    /* Elimina dalla tabella EMPLOYEE il record avente id corrispondente al valore
     * della variabile empID2 */
    System.out.println("Eliminazione del record avente id corrispondente al valore: " + empID2);
    ME.deleteEmployee(empID2);

    // Elenca tutti i record della tabella EMPLOYEE:
    System.out.println("ELENCA TUTTI I RECORD:");
    ME.listEmployees();

}

}

今、私はこの最後のクラスについて疑問を持っています...このクラスのmain()メソッドで、DAO オブジェクトをインターフェース型 ( HibernateDAO ) として宣言しますが、このインターフェース ( HibernateDAOImpl )を実装する具象型を使用して構築する必要があります。、 この上:

HibernateDAO ME = new HibernateDAOImpl();

これが私が使用しなければならないベストプラクティスなのか、それとも Java を HibernateDAO タイプとして作成するより良い方法が存在するのか、そして自動的に、実装しかないことを自動的に検出して使用する Java であるかどうかを知ることができます。

このことについて説明してもらえますか?

TNX

アンドレア

4

3 に答える 3

2

まず、HibernateDAOの名前をEmployeeDAOのような名前に変更してから、具象クラスにHibernateEmployeeDAOという名前を付けることをお勧めします。インターフェイスのポイントは、実装の詳細を非表示にして、後で変更できるようにすることです。たとえば、Hibernateを使用しないことにした場合は、具象クラスのみを変更することになり、実装でHibernateを使用しない場合にHibernateDAOというインターフェイスを使用すると混乱します。

Javaは、使用する実装を自動的に認識できないため、具象コンストラクターを使用する必要があります。DAOをインターフェースとして宣言すると、依存性注入に役立ちます。

public class ServiceLogic {
    private final EmployeeDAO dao;
    public ServiceLogic(EmployeeDAO dao){
        this.dao = dao;
    }
    //some logic code
}

上記のクラスを使用して、new ServiceLogic(new HibernateEmployeeDao());Hibernateを使用したい場合、またはnew ServiceLogic(new MyBatisEmployeeDAO());MyBatisを使用したい場合に呼び出すことができます。

于 2013-03-07T19:47:43.497 に答える
1

デフォルトでは、Javaには実行時に使用可能なクラスのレジストリがありません。さらに、クラス定義は、ネットワークからでも、実行時に動的にロードされる場合があります。つまり、Javaに「インターフェースXを実装する具体的なクラスは何ですか?」と尋ねる方法はありません。

演算子のnew後には非抽象型を続ける必要があるため、コードは正しく、オブジェクトをインスタンス化する唯一の正当な方法です。

クラスレジストリとリフレクションを使用することもできます。つまり、コンパイル時に具体的なサブクラス名を知らなくても、実行時にオブジェクトを動的に構築できます。この手法では、実行時にクラス名が構成ファイルで使用可能である必要があります。次のものがあるとします。

<!-- In configuration.xml -->
<database>
  <className>org.andrea.myH8.myH8HelloWorld.HibernateDAOImpl</className>
</database>

内部main()で、構成ファイルからクラス名を読み取り、次のようにします。

// Note, this is unchecked
Class<HibernateDAO> daoClass = (Class<HibernateDAO>) Class.forName(name);
HibernateDAO me = daoClass.getConstructor().newInstance();

をスキャンするなど、他の方法でレジストリを構築することもできますがCLASSPATH、これはもちろん効率が低く、アプリの起動が遅くなる可能性があります。

于 2013-03-07T19:48:53.603 に答える
1

これは、実際にはインターフェイスを使用するが具象クラスをインスタンス化するベスト プラクティスです (明らかに選択肢はありません)。これは、最終的に実装を置き換えるための最良の方法です (非常に近い将来ORM、上司があいまいなフレームワークに関する記事を読んだために変更することを決定したため、休止状態以外のものを使用する可能性があるとしましょう。一言で言えば (このケースは、明らかに、実際には決して起こりません)、インターフェイスの新しい実装を作成し、インスタンス化を変更するだけで完了です)。

次に尋ねているのは、フレームワークがクラ​​スパス上のクラスの正しい実装を選択できる場合、特にクラスパスが 1 つしかない場合、答えは「はい」です。IOCフレームワークはそれを実行でき、私が最もよく知っているものです。 :Spring特にこういうのが得意です。

于 2013-03-07T19:45:56.117 に答える