# Persistenz mit JPA oder Hibernate



## peez (9. Okt 2009)

Ich habe gerade eine Desktop Anwendung, wo ich mich mal in einem der Persistenz-Frameworks versuchen möchte.
Leider komme ich weder mit JPA noch mit Hibernate derzeit zum Ziel ;-)

Bei JPA scheitert es schon am Runterladen der entspr. Implementierung. Der Download-Link im Tutorial von Sun (Using the Java Persistence API in Desktop Applications) passt nicht und sonst finde ich keine Infos darüber im Netz. Wisst ihr, wo man die offizielle Implementierung bekommen kann?

Mit Hibernate scheitert es an slf4j, der auch irgendeine Implementierung erwartet, ich möchte aber auf keinen Fall auch noch log4j mit in die Anwendung aufnehmen...

Diese Fehlermeldung gibts:

```
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: See [url=http://www.slf4j.org/codes.html#StaticLoggerBinder]SLF4J Error Codes[/url] for further details.
Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder
```

Binde ich die Implementierung slf4j-nop-1.5.8.jar in den Classpath ein, kommt diese Exception:

```
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/collections/map/LRUMap
```

Was mache ich falsch?
Mir ist egal welches der Frameworks ich benutze. Hauptsache endlich eines ;-)


----------



## maki (9. Okt 2009)

> Bei JPA scheitert es schon am Runterladen der entspr. Implementierung.


Scherzkeks 
Eine Implementierung von JPA ist Hibernate, eine andere EclipseLink (mein Favourit), noch eine andere ist Datanucleus...



> Mit Hibernate scheitert es an slf4j, der auch irgendeine Implementierung erwartet, ich möchte aber auf keinen Fall auch noch log4j mit in die Anwendung aufnehmen...


Allein für Hibernate brauchst du fast 2 dutzend JArs, da kommt es auf log4j nicht mehr an, dazu kommt das log4j wohl das beste Loggingframework ist, also vergiss deine vorbehalte gegenüber log4j.

Würde die EclipseLink empfehelen, ist imho einfacher zu konfigurieren, ach ja, EclipseLink wird die Referenzimplementierung für JPA 2.0.


----------



## peez (9. Okt 2009)

Ah - man lernt nie aus ;-)

Also ich habe mir jetzt Eclipselink geladen und versucht, eine ganz einfache Klasse zu speichern. Leider bekomme ich folgende Exception:

```
Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named db
```

Die Einstellungen etc. dürften korrekt sein.

persistence.xml (liegt in src/META-INF)
[XML]<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
    http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="db" transaction-type="RESOURCE_LOCAL">

    <provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
 <class>de.jpaTest.Person</class>
    <properties>

      <property name="toplink.jdbc.user" value="peez"/>
      <property name="toplink.jdbc.password" value=""/>
      <property name="toplink.jdbc.url" value="jdbc:mysql://192.168.0.10/test"/>

      <property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
      <property name="toplink.ddl-generation" value="create-tables"/>
    </properties>

  </persistence-unit>
</persistence>
[/XML]

POJO:

```
package de.jpaTest;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Person {
  
  @Id
  @GeneratedValue
  private int id;
  
  private String vorname;
  private String nachname;
  
  public Person() {
    
  }
  
  
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getVorname() {
    return vorname;
  }
  public void setVorname(String vorname) {
    this.vorname = vorname;
  }
  public String getNachname() {
    return nachname;
  }
  public void setNachname(String nachname) {
    this.nachname = nachname;
  }
}
```

Main-Klasse:

```
package de.jpaTest;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Test {

  /**
   * @param args
   */
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("db");
    EntityManager em = emf.createEntityManager();
    
    em.getTransaction().begin();
    
    Person p = new Person();
    p.setVorname("Philipp");
    
    em.persist(p);
    
    em.getTransaction().commit();
    
    em.close();
    emf.close();


  }

}
```


----------



## maki (9. Okt 2009)

Der Provider sollte
[xml]<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>[/xml]
lauten, TopLink ist tot, heisst jetzt EclipseLink 

Nachtrag: Das gilt auch die die Properties.


----------



## peez (9. Okt 2009)

Cool jetzt funktionierts. Tausend Dank! :toll:


----------



## -MacNuke- (9. Okt 2009)

peez hat gesagt.:


> Mit Hibernate scheitert es an slf4j, der auch irgendeine Implementierung erwartet, ich möchte aber auf keinen Fall auch noch log4j mit in die Anwendung aufnehmen...



Dann kannst du slf4j-jdk4 nutzen. Das nutzt die, ziemlich beschränkten, Logging-Funktionalitäten von Java direkt (so wie auch EclipseLink).

slf4j ist an sich eine schöne Sache, in Verbindung mit log4j. Weil spätestens wenn die Anwendungen auf anderen Rechnern laufen soll, fragst du dich wo deine ganzen Programmausgaben (u.a. die Logs, falls mal eine Abfrage/Aktualisierung der Datenbank schief geht) hin sollen. Oder warum die Anwendung auf dem einen Rechner plötzlich abschmiert.

Wenn du jetzt sagst, alles in eine Datei, dann fragst du dich später, wie du verhindern kannst, dass sich die Datei nach 1 Monat Nutzung auf >100MB aufbläst.

Für all das hat log4j eine schöne Lösung und dank slf4j programmiert man nicht mal direkt gegen log4j.


----------



## peez (9. Okt 2009)

-MacNuke- hat gesagt.:


> Weil spätestens wenn die Anwendungen auf anderen Rechnern laufen soll, fragst du dich wo deine ganzen Programmausgaben (u.a. die Logs, falls mal eine Abfrage/Aktualisierung der Datenbank schief geht) hin sollen. Oder warum die Anwendung auf dem einen Rechner plötzlich abschmiert.



Genau dafür habe ich mir vor längerer Zeit schon eine eigene Logger-Klasse gebaut, die auch System.out / System.err abgreifen kann und so alles, was irgendwie ausgegeben wird, auch mitschreibt. Um die Dateigröße kümmert sie sich auch.
Und da die schon alles tut was ich brauche, bin ich immer froh, wenn ich mir log4j sparen kann.


----------



## byte (9. Okt 2009)

Nur blöd, dass die meistens Libraries gegen die Apache Commons Logging API oder gegen die SLF4J API implementieren, statt Sysouts zu machen. Loggt das Dein Logger auch? Wenn nicht, ist es unbrauchbar.


----------



## maki (9. Okt 2009)

Diese ganze Java "Logging Framework Szene" ist lächerlich, eine richtige Implementierung reicht, kein Grund seine eigene schlechtere nochmals zu schreiben.

Werde nie nachvollziehen können warum log4j nicht der Standard geworden ist, was ich aber noch weniger verstehe ist, warum Leute ihre eigene schreiben müssen die weniger kann...


----------



## -MacNuke- (9. Okt 2009)

peez hat gesagt.:


> Genau dafür habe ich mir vor längerer Zeit schon eine eigene Logger-Klasse gebaut, die auch System.out / System.err abgreifen kann und so alles, was irgendwie ausgegeben wird, auch mitschreibt.



Du weißst aber schon, dass man auch so einfach System.out und System.err umleiten kann?  Kein Grund deswegen gleich eine komplette Logging-Funktionalität zu bauen.


----------



## peez (9. Okt 2009)

maki hat gesagt.:


> Diese ganze Java "Logging Framework Szene" ist lächerlich, eine richtige Implementierung reicht, kein Grund seine eigene schlechtere nochmals zu schreiben.
> 
> Werde nie nachvollziehen können warum log4j nicht der Standard geworden ist, was ich aber noch weniger verstehe ist, warum Leute ihre eigene schreiben müssen die weniger kann...



Das Teil habe ich noch gebaut lange bevor ich von log4j etc. gewusst habe... Ich benutze es eben weil ich es schon immer benutzt habe ;-)
Aber wenn ihr schon so drüber herzieht, überlege ich mir vielleicht doch mal, log4j zu benutzen ;-)

Lässt sich mit log4j denn auch der Sysout abgreifen? Alle meine Klassen schreiben nämlich normal auf die Konsole...


----------



## maki (9. Okt 2009)

Wir haben alle schon mal das Rad neu erfunden, aber eckig.. 
Deswegen erst suchen bevor man etwas selber neu erfindet



> Alle meine Klassen schreiben nämlich normal auf die Konsole...


Aua.. ist nicht empfehlenswert, aus mehreren Gründen.


----------



## -MacNuke- (9. Okt 2009)

peez hat gesagt.:


> Lässt sich mit log4j denn auch der Sysout abgreifen?



Von PrintStream erben und die entsprechenden Methoden implementieren und das dann auf Out und Err setzen.



peez hat gesagt.:


> Alle meine Klassen schreiben nämlich normal auf die Konsole...



Das ist schon mal schlecht. 

Bei slf4j und log4j kannst du beim loggen eine Klasse übergeben und dann zeigt er dir im Log sogar die Zeilennummer an. Toll was? 

Nimm einfach slf4j und gut ist. Dann hast du alles unter einem Hut.


----------

