(Spring+Hibernate) Verwendung von HibernateTemplate und persistentes Objekt?

Kann man mit Deinem Hades auch in bezug auf Spring und Hibernate etwas anfangen, oder werde ich nur glücklich, wenn ich ne reine JPA Implementation und Dein Hades verwende?
Hades funktioniert grundsätzlich mit jeder JPA Anwendung. Spring macht das Leben leichter und wird auch zur Laufzeit benötigt, jedoch wirklich zwingend nur als Bibliothek. D.h. man muss nciht unbedingt Springkonfiguration oder Springs Dependency Injection nutzen. Einen Teil der Funktionalität kann man nur mit bestimmten Persistenzprovidern nutzen. Hierzu zählen Hibernate und Eclipselink/Toplink. Darüber hinaus integriert sich Hades prima in eine App, in der bereits ein DAO Layer auf Basis von reinem Hibernate (wie in deinem Fall) existiert.

Ich weiß nicht, ob ich JPA schon richtig verstehe - es gibt da also mehrere Implementierungen? Auch welche, die nicht im Rahmen eines Applikations-Servers laufen?
Ja. Referenzimplementierung ist EclipseLink (früher Toplink). Wurde von Oracle gestiftet und liegt jetzt bei der Eclipse Foundation. Hat mit der IDE allerdings nichts zu tun. Darüber hinaus gibt es halt noch Hibernate (IMHO sogar die bessere Implementierung) und einen recht unbekannten Anbieter namens DataNucleus, der z.B. in der Google AppEngine läuft (frag mich nicht, warum Google den ausgewählt hat). Von Apache gibt es noch OpenJPA, das aber wirklich nur den JPA Standard implementiert und kein Feature mehr (was in vielen Fällen ein Problem ist). JavaEE 5 zertifizierte Appserver bringen also eine solche Implementierung mit. In JBoss läuft logischerweise Hibernate, im Glassfish eher TopLink.

Gruß
Ollie
 
Hallo,

Weiterhin glaube ich, dass du das Persistenzverhalten von Hibernate mit dem von JPA verwechselst. JPA persistiert Änderungen am Objektgraphen beim commit der Transaktion, so dass kein explizites save notwendig ist. Dass Hibernate das auch tut wäre mir neu. Du kommst also um einen zweiten saveOrUpdate Call nit herum.

Ich glaube schon, dass Hibernate das macht. Insbesondere dann, wenn man die entites mit saveOrUpdate(...) persistiert und eine entsprechende Transaktion "drumherum" gespannt ist.

Hier ein kleines minimal Beispiel dazu:
Java:
package de.tutorials.persistence;
import de.tutorials.domain.Person;

public interface IPersonDao {
    void save(Person person);
    Person getBy(int id);
}

Java:
package de.tutorials.persistence.internal;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import de.tutorials.domain.Person;
import de.tutorials.persistence.IPersonDao;

public class PersonDao extends HibernateDaoSupport implements IPersonDao {
    public Person getBy(int id) {
        return (Person) getHibernateTemplate().get(Person.class, id);
    }

    public void save(Person person) {
        getHibernateTemplate().saveOrUpdate(person);
    }
}

Java:
package de.tutorials.services;

import de.tutorials.domain.Person;

public interface IPersonService {
    void register(Person person);
    Person getBy(int id);
}

Java:
package de.tutorials.services.internal;

import org.springframework.transaction.annotation.Transactional;

import de.tutorials.domain.Person;
import de.tutorials.persistence.IPersonDao;
import de.tutorials.services.IPersonService;

public class PersonService implements IPersonService {

    IPersonDao personDao;

    @Transactional
    public void register(Person person) {
        personDao.save(person);
        
        //Nach dem Speichern (attachen der Entity mit einer Session) verändern wir die Entity.
        //die Änderung werden beim verlassen der Methode durch das committen der transaktion und flushen der Session 
        //entsprechend an die Datenbank übergeben.
        person.setName("Furz");
    }

    @Transactional
    (
            //readOnly=true //wird das gesetzt werden die Änderungen natürlich nicht an die Datenbank weitergegeben
    )
    public Person getBy(int id) {
        Person p = personDao.getBy(id);
        
         //p.setName("Bubu" + System.currentTimeMillis());
        //Nach dem verlassen der getBy Methode wird die aktive Transaktion comitted und dabei ein flush der Hibernate Session gemacht.
        //Dabei deshalb sieht man in der Datenbank nach dem verlassen dieser Methode die Änderungen die man an der Attachedten Entity gemacht hat.

        return p;
    }

    public IPersonDao getPersonDao() {    return personDao; }
    public void setPersonDao(IPersonDao personDao) { this.personDao = personDao; }
}

Person Pojo:
Java:
package de.tutorials.domain;

import java.util.Date;

public class Person {

    int id;
    String name;
    Date birthday;

    public Person() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
    @Override
    public String toString() {
        return this.id + " " + this.name +" " + this.birthday;
    }

}

XML:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="de.tutorials.domain">
    <class name="Person">
        <id name="id" type="int">
            <generator class="assigned" />
        </id>
        <property name="name"/>
        <property name="birthday"/>
    </class>
</hibernate-mapping>

Das Beispiel
Java:
package de.tutorials;

import java.util.Date;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import de.tutorials.domain.Person;
import de.tutorials.services.IPersonService;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ApplicationContext context = new FileSystemXmlApplicationContext("conf/context.xml");
        IPersonService personService = (IPersonService)context.getBean("personService");
        Person p = new Person();
        p.setId(0);
        p.setName("Test0");
        p.setBirthday(new Date());
        personService.register(p);
        
        Person p1 = personService.getBy(0);
        
        System.out.println(p1);
    }
}

Ausgabe:
Code:
0 Furz 2009-08-04 23:49:43.0

Die Spring Config:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    ">

    <bean id="dataSource" destroy-method="close"
        class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@localhost:1521:XE" />
        <property name="username" value="tutorials" />
        <property name="password" value="tutorials" />
    </bean>


    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mappingResources">
            <list>
                <value>de/tutorials/domain/Person.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
      </value>
        </property>
    </bean>


    <bean id="personDao" class="de.tutorials.persistence.internal.PersonDao">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <bean id="personService" class="de.tutorials.services.internal.PersonService">
        <property name="personDao" ref="personDao" />
    </bean>


    <bean id="txManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="txManager" />
</beans>
Gruß Tom
 

Anhänge

Zuletzt bearbeitet von einem Moderator:
Hallo Oliver,

ich danke Dir für die vielen hilfreichen Informationen. Deine Bibliothek werde ich mir auf jeden fall ansehen, ich habe heute auch den von Dir verlinkten Artikel (Don't repeat your DAO) gelesen.
 
Hey Thomas,

danke für das Beispiel. Ich denke man kann nun festhalten, dass das Autopersistieren in JPA und Hibernate gleich erfolgt. Jedoch ist wichtig, dass dies nur innerhalb des Lebenszyklus der Session (die normalerweise an eine Transaktion gebunden ist) passiert. Wird keine Transaktion aufgemacht ist direkt nach dem Aufruf des HibernateTemplates die Session zu und damit kein Autopersist mehr möglich.

Gruß
Ollie
 
Hallo,

danke für das Beispiel.

Immer wieder gerne :)

Ich denke man kann nun festhalten, dass das Autopersistieren in JPA und Hibernate gleich erfolgt. Jedoch ist wichtig, dass dies nur innerhalb des Lebenszyklus der Session (die normalerweise an eine Transaktion gebunden ist) passiert. Wird keine Transaktion aufgemacht ist direkt nach dem Aufruf des HibernateTemplates die Session zu und damit kein Autopersist mehr möglich.

Hui Theserverside... kommst ja ganz schön rum in der letzten Zeit ;-)

Gruß Tom
 

Neue Beiträge

Zurück