# Suche ein Hibernate-DAO-Gerüst zum lernen



## Hyperhyper (25. Jul 2006)

Suche ein Gerüst welches die Standart CRUD -Operationen von Hibernate beinhaltet. Also ein kleines Java Programm welches ich dann erweitern kann. Hat da jemand zufällig was?


----------



## AlArenal (25. Jul 2006)

Reicht dir das Hibernate Tutorial auf deren Website nicht?


----------



## HyperHyper (25. Jul 2006)

Welches Tutorial meinst du? Da hats soviele


----------



## AlArenal (25. Jul 2006)

Na das aus der offiziellen Doku zum Bleistift:
http://www.hibernate.org/hib_docs/v3/reference/en/html/tutorial.html#tutorial-firstapp

Vielleicht schauste auch mal bei denen ins Forum. Die haben auch ein deutschsprachiges Unterforum.


----------



## HyperHyper (25. Jul 2006)

Da hats soviele Dokus, da hab ich den Link doch glatt übersehen. Vielen Dank!!

Hab hier ein fieses Problem, hoffe du kannst mir helfen. Habe eine Employee -JavaBean


```
package hibernateproject;

public class Employee {
  private Integer idEmployee;
  private Integer age;
  private String name;
  private String gendre;
  private Double salary;

  public Employee() {
  }

  public void setIdEmployee(Integer idEmployee) {
    this.idEmployee = idEmployee;
  }

  public void setAge(Integer age) {
    this.age = age;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setGendre(String gendre) {
    this.gendre = gendre;
  }

  public void setSalary(Double salary) {
    this.salary = salary;
  }

  public Integer getIdEmployee() {
    return idEmployee;
  }

  public Integer getAge() {
    return age;
  }

  public String getName() {
    return name;
  }

  public String getGendre() {
    return gendre;
  }

  public Double getSalary() {
    return salary;
  }
}
```

In dieser werden halt ein paar Werte eingetragen. Nix besonderes also.


Nachdem dieses Bean mit Daten gefüllt worden ist, wird von einem Servlet die Update, Delete, Post oder Find-Funktion aufgerufen. 


```
package hibernateproject;

import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForward;

import org.apache.struts.action.Action;

public class EmployeeAction
    extends Action {
  public ActionForward execute(ActionMapping actionMapping,
                               ActionForm actionForm,
                               HttpServletRequest servletRequest,
                               HttpServletResponse servletResponse) {

    try {
      EmployeeActionForm employeeForm = (EmployeeActionForm) actionForm;
      Employee employee = new Employee();  // erzeuge neue Instanz
      EmployeeDAO dao = new EmployeeDAO();


      String action = (String) servletRequest.getParameter("action");

      if (action != null) {
        // speichere Werte aus dem Request nun in der hier erzeugten Bean-Instanz
        employee.setIdEmployee(employeeForm.getIdEmployee());
        employee.setName(employeeForm.getName());
        employee.setAge(employeeForm.getAge());
        employee.setGendre(employeeForm.getGendre());
        employee.setSalary(employeeForm.getSalary());
      }
      ;


      // Prüfe nun welche Aktion geklickt worden ist
      if (action.toUpperCase().equals("POST")) {
        System.out.println("Es wurde POST geklickt");
        dao.makePersistent(employee);
        HibernateUtil.commitTransaction();


      }
      else if (action.toUpperCase().equals("UPDATE")) {
        System.out.println("Es wurde UPDATE geklickt");
        HibernateUtil.commitTransaction();

      }
      else if (action.toUpperCase().equals("DELETE")) {
        System.out.println("Es wurde DELETE geklickt");
        dao.makeTransient(employee);
        HibernateUtil.commitTransaction();

      }
      else if (action.toUpperCase().equals("FIND")) {
        System.out.println("Es wurde FIND geklickt");
        employee = (Employee) dao.findByName(employeeForm.getName()).iterator().next();
        servletRequest.setAttribute("employee", employee);
        System.out.println("Ergebnis der Suche:" + employee.getSalary());
        
        
      }

    }
    // Fehlerbehandlung mit der Klasse InfrastructeException
    catch (InfrastructureException ex) {
      // Rethrow as a checked exception

      HibernateUtil.rollbackTransaction();
      throw new Exception(ex);

    }
    finally {
     
      HibernateUtil.closeSession();
      
     
      return actionMapping.findForward("employee");
    }

  }
}
```


Das Problem stellt hier die DELETE und UPDATE -Funktion da. Diese 2 funktionieren einfach nicht.
Hier noch die DAO welche benutzt wird:


```
package hibernateproject;

import org.hibernate.*;

import java.util.Collection;
import org.hibernate.criterion.Expression;


public class EmployeeDAO {

  public EmployeeDAO() {
    HibernateUtil.beginTransaction();
  }

  // ********************************************************** //

  public Employee getEmployeeById(Long employeeId, boolean lock) throws

      InfrastructureException {

    Session session = HibernateUtil.getSession();

    Employee employee = null;
    try {
      if (lock) {
        employee = (Employee) session.load(Employee.class, employeeId,
                                           LockMode.UPGRADE);
      }
      else {
        employee = (Employee) session.load(Employee.class, employeeId);
      }
    }
    catch (HibernateException ex) {
      System.out.println("EmployeeDAO: getEmployeeByIde: Fehler:" + ex.toString());
      throw new InfrastructureException(ex);
    }
    return employee;
  }

  // ********************************************************** //

  public Collection findAll() throws InfrastructureException {

    Collection employees;
    try {

      employees = HibernateUtil.getSession().createCriteria(Employee.class).
          list();

    }
    catch (HibernateException ex) {
      System.out.println("EmployeeDAO: findAll: Fehler:" + ex.toString());
      throw new InfrastructureException(ex);
    }
    return employees;
  }

  // ********************************************************** //

  public Collection findByName(String employeeName) throws
      InfrastructureException {

    Collection employees;
    try {
      Criteria crit = HibernateUtil.getSession().createCriteria(Employee.class);
      employees = crit.add(Expression.like("name", employeeName)).list();
      
      
    }
    catch (HibernateException ex) {
      System.out.println("EmployeeDAO: findByName: Fehler:" + ex.toString());
      throw new InfrastructureException(ex);
    }
    return employees;
  }

  // ********************************************************** //

  public void makePersistent(Employee employee) throws InfrastructureException {
    // Speichere die Java-Bean "Employee" in die Datenbank ab
    try {
      HibernateUtil.getSession().save(employee);
    }
    catch (HibernateException ex) {
      System.out.println("EmployeeDAO: makePersistent: Fehler:" + ex.toString());
      throw new InfrastructureException(ex);
    }
  }

  // ********************************************************** //

  public void makeTransient(Employee _employee) throws InfrastructureException {
    // Datensatz löschen aus der Datenbank
    System.out.println("EmployeeDao: makeTransient - erreicht");
    try {
      HibernateUtil.getSession().delete(_employee);
    }
    catch (HibernateException ex) {
      System.out.println("EmployeeDAO: makeTransient: Fehler:" + ex.toString());
      throw new InfrastructureException(ex);
    }
  }

}
```

und nun die Problem-Klasse HibernateUtil. Laut Debug-Infos scheitert alles in der Methode "commitTransaction()" beim Befehl "tx.commit();" (zeile 172). Dieser wird fehlerhaft abgearbeitet und schon verschwindet alles im darauf folgendem "catch".


```
package hibernateproject;

import org.hibernate.*;
import org.hibernate.cfg.Configuration;
import org.apache.commons.logging.*;

import javax.naming.*;

public class HibernateUtil {

  private static Log log = LogFactory.getLog(HibernateUtil.class);

  private static Configuration configuration;
  private static SessionFactory sessionFactory;
  private static final ThreadLocal threadSession = new ThreadLocal();
  private static final ThreadLocal threadTransaction = new ThreadLocal();
  private static final ThreadLocal threadInterceptor = new ThreadLocal();

  // Create the initial SessionFactory from the default configuration files

  static {
    try {
      configuration = new Configuration();
      sessionFactory = configuration.configure().buildSessionFactory();
      // We could also let Hibernate bind it to JNDI:

      // configuration.configure().buildSessionFactory()
    }
    catch (Throwable ex) {
      // We have to catch Throwable, otherwise we will miss
      // NoClassDefFoundError and other subclasses of Error
      log.error("Building SessionFactory failed.", ex);
      throw new ExceptionInInitializerError(ex);
    }
  }

  /**
   * Returns the SessionFactory used for this static class.
   *
   * @return SessionFactory
   */

  public static SessionFactory getSessionFactory() {
    /* Instead of a static variable, use JNDI:
                     SessionFactory sessions = null;
                     try {
            Context ctx = new InitialContext();
            String jndiName = "java:hibernate/HibernateFactory";
            sessions = (SessionFactory)ctx.lookup(jndiName);
                     } catch (NamingException ex) {
            throw new InfrastructureException(ex);
                     }
                     return sessions;
     */
    return sessionFactory;
  }

  /**
   * Returns the original Hibernate configuration.
   *
   * @return Configuration
   */

  public static Configuration getConfiguration() {
    return configuration;
  }

  /**
   * Rebuild the SessionFactory with the static Configuration.
   *
   */
  public static void rebuildSessionFactory() throws InfrastructureException {
    synchronized (sessionFactory) {
      try {
        sessionFactory = getConfiguration().buildSessionFactory();
      }
      catch (Exception ex) {
        throw new InfrastructureException(ex);
      }
    }
  }

  /**
   * Rebuild the SessionFactory with the given Hibernate Configuration.
   *
   * @param cfg
   */

  public static void rebuildSessionFactory(Configuration cfg) throws
      InfrastructureException {
    synchronized (sessionFactory) {
      try {
        sessionFactory = cfg.buildSessionFactory();
        configuration = cfg;
      }
      catch (Exception ex) {
        throw new InfrastructureException(ex);
      }
    }
  }

  /**
   * Retrieves the current Session local to the thread.
   * 



   * If no Session is open, opens a new Session for the running thread.
   *
   * @return Session
   */
  public static Session getSession() throws InfrastructureException {
    Session s = (Session) threadSession.get();
    try {
      if (s == null) {
        log.debug("Opening new Session for this thread.");
        if (getInterceptor() != null) {
          log.debug("Using interceptor: " + getInterceptor().getClass());
          s = getSessionFactory().openSession(getInterceptor());
        }
        else {
          s = getSessionFactory().openSession();
        }
        threadSession.set(s);
      }
    }
    catch (HibernateException ex) {
      throw new InfrastructureException(ex);
    }
    return s;
  }

  /**
   * Closes the Session local to the thread.
   */

  public static void closeSession() throws InfrastructureException {
    try {
      Session s = (Session) threadSession.get();
      threadSession.set(null);
      if (s != null && s.isOpen()) {
        log.debug("Closing Session of this thread.");
        s.close();
      }
    }
    catch (HibernateException ex) {
      throw new InfrastructureException(ex);
    }
  }

  /**
   * Start a new database transaction.
   */

  public static void beginTransaction() throws InfrastructureException {
    Transaction tx = (Transaction) threadTransaction.get();
    try {
      if (tx == null) {
        log.debug("Starting new database transaction in this thread.");
        tx = getSession().beginTransaction();
        threadTransaction.set(tx);
      }
    }
    catch (HibernateException ex) {
      throw new InfrastructureException(ex);
    }
  }

  /**
   * Commit the database transaction.
   */

  public static void commitTransaction() throws InfrastructureException {
    Transaction tx = (Transaction) threadTransaction.get();
    try {
      if (tx != null && !tx.wasCommitted()
          && !tx.wasRolledBack()) {
        log.debug("Committing database transaction of this thread.");
        tx.commit();
      }
      threadTransaction.set(null);
    }
    catch (HibernateException ex) {
      rollbackTransaction();
      System.out.println("HibernateUtil: commitTransaction: " + ex.toString());
      throw new InfrastructureException(ex);
    }
  }

  /**
   * Commit the database transaction.
   */

  public static void rollbackTransaction() throws InfrastructureException {
    Transaction tx = (Transaction) threadTransaction.get();
    try {
      threadTransaction.set(null);
      if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
        log.debug(
            "Tyring to rollback database transaction of this thread.");
        tx.rollback();
      }
    }
    catch (HibernateException ex) {
      throw new InfrastructureException(ex);
    }
    finally {
      closeSession();
    }
  }

  /**
   * Reconnects a Hibernate Session to the current Thread.
   *
   * @param session The Hibernate Session to be reconnected.
   */

  public static void reconnect(Session session) throws
      InfrastructureException {
    try {
      session.reconnect();
      threadSession.set(session);
    }
    catch (HibernateException ex) {
      throw new InfrastructureException(ex);
    }
  }

  /**
   * Disconnect and return Session from current Thread.
   *
   * @return Session the disconnected Session
   */

  public static Session disconnectSession() throws InfrastructureException {

    Session session = getSession();
    try {
      threadSession.set(null);
      if (session.isConnected() && session.isOpen()) {
        session.disconnect();
      }
    }
    catch (HibernateException ex) {
      throw new InfrastructureException(ex);
    }
    return session;
  }

  /**
   * Register a Hibernate interceptor with the current thread.
   * 



   * Every Session opened is opened with this interceptor after
   * registration. Has no effect if the current Session of the
   * thread is already open, effective on next close()/getSession().
   */
  public static void registerInterceptor(Interceptor interceptor) {
    threadInterceptor.set(interceptor);
  }

  private static Interceptor getInterceptor() {
    Interceptor interceptor =
        (Interceptor) threadInterceptor.get();
    return interceptor;
  }

}
```


Hast du eine Idee woran das liegt das mein Programm das Objekt "employee" nicht löschen und updaten kann?


----------



## AlArenal (25. Jul 2006)

Gibts ne Exception und einen zugehörigen Stacktrace?


----------



## HyperHyper (25. Jul 2006)

Also beim DELETE steht folgende Meldung in Klasse "HibernateUtil", Funktion "commitTransaction": 

org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1


Beim UPDATE erscheint keine Meldung, der Code wird anscheinend einwandfrei ausgeführt, allerdings werden keine Veränderungen in die DB geschrieben noch irgendwas anderes verändert.


Soll ich das ganze Beispiel mal irgendwo hochladen damit du dir das ansehen kannst?

Vielen Dank übrigens das du mir hilfst!


----------



## AlArenal (25. Jul 2006)

Bzgl. des DELETE liest es sich doch ganz so, als würdest du einen Eintrag löschen wollen, der in der DB nicht existiert. Ich weiß nicht, ob es helfen würde mir das direkt anzuschauen, weil ich mit Webkram in Java nix zu tun habe, ich bin ein Client Guy 

Gib dich mal dort, wo der DELETE ausgeführt wird, den Primärschlüssel (ID) des Objekts aus und prüfe, obs das Ding tatsächlich gibt.


----------



## HyperHyper (25. Jul 2006)

Die zu löschenden Einträge existieren aber 
Wenn ich FIND benutze findet der ja auch den gewünschten Eintrag, allerdings klappt halt das DELETE & UPDATE nicht.

Der Webkram ist nur nebensache, da die Datenbank-Operationen immer dieselben sind. Nur werden diese halt von anderen Funktionen aufgerufen.

Hier mal der Inhalt von meiner "hibernate.cfg.xml"-Datei:

```
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD//EN"
	"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
  <session-factory>

    
    
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>

    <property name="connection.url">jdbc:mysql://localhost:3306/employeecatalog</property>
    <property name="connection.username">root</property>

    <property name="connection.password">root</property>
    <!--
      Use the C3P0 connection pool.
      <property name="c3p0.min_size">3</property>
      <property name="c3p0.max_size">5</property>

      <property name="c3p0.timeout">1800</property>
    -->
    
    <property name="connection.pool_size">3</property>

    
    <property name="show_sql">false</property>
    
    <mapping resource="hibernateproject/Employee.hbm.xml"/>

  </session-factory>
</hibernate-configuration>
```


Und noch der Inhalt meiner "Employee.hbm.xml"

```
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM
			"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >

<hibernate-mapping package="hibernateproject">
  <class name="Employee" table="employee" lazy="true">

    
    <id name="idEmployee" column="idEmployee" type="java.lang.Integer">

      <generator class="identity"/>
    </id>
    <property name="name" column="name" type="java.lang.String" update="true" not-null="true"/>

    <property name="age" column="age" type="java.lang.Integer" update="true" not-null="true"/>

	 <property name="gendre" column="gendre" type="java.lang.String" update="true" not-null="true"/>

    <property name="salary" column="salary" type="java.lang.Double" update="true" not-null="true"/>

  </class>
</hibernate-mapping>
```


Auf meiner Datenbank sieht es so aus:





Und das Beispiel selber habe ich von hier klick


----------



## HyperHyper (25. Jul 2006)

AlArenal hat gesagt.:
			
		

> Gib dich mal dort, wo der DELETE ausgeführt wird, den Primärschlüssel (ID) des Objekts aus und prüfe, obs das Ding tatsächlich gibt.



Hm hab jetzt mal bei EmployeeAction die "IdEmployee" auf 1 gesetzt und siehe da mein Datensatz wurde gelöscht.


```
else if (action.toUpperCase().equals("DELETE")) {
        System.out.println("Es wurde DELETE geklickt");
        System.out.println("DELETE: employee inhalt: " + employee.getIdEmployee());
        employee.setIdEmployee(1);
        dao.makeTransient(employee);
        HibernateUtil.commitTransaction();

      }
```

Liegt also doch an der IdEmployee! Vielen Dank für deinen Vorschlag. Hm muss das nun mal genauer überdenken.  :###  ???:L


Nur ein Problem bleibt noch, das UPDATE funktioniert immer noch nicht   Ne Idee?


----------

