Korrupte Datenbank nach insert mit JPA

Hallo,

ich versuche Daten über JPA auf eine H2 Datenbank zu schreiben.
Das klappt auch soweit, ich kann die Daten auch auslesen.
Wenn ich dann jedoch über die Web-Kosole auf die DB zugreifen möchte erscheint folgende Meldung


Datei fehlerhaft beim Lesen des Datensatzes: "type: 134". Mögliche Lösung: Recovery Werkzeug verwenden
File corrupted while reading record: "type: 134". Possible solution: use the recovery tool [90030-153] 90030/90030 (Hilfe)
org.h2.jdbc.JdbcSQLException: Datei fehlerhaft beim Lesen des Datensatzes: "type: 134". Mögliche Lösung: Recovery Werkzeug verwenden
File corrupted while reading record: "type: 134". Possible solution: use the recovery tool [90030-153]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:327)
    at org.h2.message.DbException.get(DbException.java:167)
    at org.h2.message.DbException.get(DbException.java:144)
    at org.h2.store.Data.readValue(Data.java:759)
    at org.h2.index.PageDataLeaf.readRow(PageDataLeaf.java:598)
    at org.h2.index.PageDataLeaf.getRowAt(PageDataLeaf.java:329)
    at org.h2.index.PageDataLeaf.getLastKey(PageDataLeaf.java:383)
    at org.h2.index.PageDataIndex.<init>(PageDataIndex.java:81)
    at org.h2.table.RegularTable.<init>(RegularTable.java:92)
    at org.h2.store.PageStore.addMeta(PageStore.java:1621)
    at org.h2.store.PageStore.readMetaData(PageStore.java:1553)
    at org.h2.store.PageStore.recover(PageStore.java:1351)
    at org.h2.store.PageStore.openExisting(PageStore.java:351)
    at org.h2.store.PageStore.open(PageStore.java:275)
    at org.h2.engine.Database.getPageStore(Database.java:2040)
    at org.h2.engine.Database.open(Database.java:547)
    at org.h2.engine.Database.openDatabase(Database.java:218)
    at org.h2.engine.Database.<init>(Database.java:213)
    at org.h2.engine.Engine.openSession(Engine.java:56)
    at org.h2.engine.Engine.openSession(Engine.java:159)
    at org.h2.engine.Engine.createSessionAndValidate(Engine.java:138)
    at org.h2.engine.Engine.createSession(Engine.java:121)
    at org.h2.engine.Engine.createSession(Engine.java:28)
    at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:285)
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:114)
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:98)
    at org.h2.Driver.connect(Driver.java:72)
    at org.h2.server.web.WebServer.getConnection(WebServer.java:642)
    at org.h2.server.web.WebApp.login(WebApp.java:892)
    at org.h2.server.web.WebApp.process(WebApp.java:205)
    at org.h2.server.web.WebApp.processRequest(WebApp.java:164)
    at org.h2.server.web.WebThread.process(WebThread.java:137)
    at org.h2.server.web.WebThread.run(WebThread.java:93)
    at java.lang.Thread.run(Unknown Source) 

Hier mal hoffentlich alles was ihr braucht:

import java.util.Date;

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

import de.klemens.stadt.spk_main.data.pojos.User;


public class UserService
{
  public static void main(String args[])
  {
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("spk");
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    EntityTransaction transaction = entityManager.getTransaction();
    try
    {
      transaction.begin();
      java.io.BufferedReader FileReader =
        new java.io.BufferedReader(new java.io.FileReader(new java.io.File("D:\\User.csv")));
      String zeile = "";
      while (null != (zeile = FileReader.readLine()))
      {
        System.out.println(zeile);
        String[] split = zeile.split(";");
        User u = new User();
        u.setVname(split[1]);
        u.setNname(split[2]);
        u.setPasswort(split[3]);
        u.setWerkhofId(Integer.valueOf(split[4]));
        u.setBerechtigung(split[5]);
        u.setNeuDatum(new Date());
        u.setAendDatum(new Date());
        u.setNeuUser(Integer.valueOf(split[8]));
        u.setAendUser(Integer.valueOf(split[9]));
        entityManager.merge(u);
      }
      transaction.commit();
      System.out.println("Fertig");

      User find = entityManager.find(User.class, 1);
      System.out.println(find.getNname());
    }
    catch (Exception e)
    {
      e.printStackTrace();
      if (transaction.isActive())
      {
        transaction.rollback();
      }
    }
    finally
    {
      entityManager.clear();
      entityManager.close();
      entityManagerFactory.close();
      System.out.println("ende");
    }
  }
}
import java.util.Date;

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


@Entity
@Table(name = "USER")
public class User
{
  /**
   *
   */
  @Id
  @GeneratedValue
  @Column(name = "ID")
  private int id;

  /**
   *
   */
  @Column(name = "VNAME")
  private String vname;

  /**
   *
   */
  @Column(name = "NNAME")
  private String nname;

  /**
   *
   */
  @Column(name = "PASSWORT")
  private String passwort;

  /**
   *
   */
  @Column(name = "WERKHOF_ID")
  private int werkhofId;

  /**
   *
   */
  @Column(name = "RIGHTS")
  private String berechtigung;

  /**
   *
   */
  @Column(name = "NEUDATUM")
  private Date neuDatum;

  /**
   *
   */
  @Column(name = "AENDDATUM")
  private Date aendDatum;

  /**
   *
   */
  @Column(name = "NEUUSER")
  private int neuUser;

  /**
   *
   */
  @Column(name = "AENDUSER")
  private int aendUser;


  /**
   * @return the id
   */
  public int getId()
  {
    return id;
  }


  /**
   * @param id
   *          the id to set
   */
  public void setId(int id)
  {
    this.id = id;
  }


  /**
   * @return the vname
   */
  public String getVname()
  {
    return vname;
  }


  /**
   * @param vname
   *          the vname to set
   */
  public void setVname(String vname)
  {
    this.vname = vname;
  }


  /**
   * @return the nname
   */
  public String getNname()
  {
    return nname;
  }


  /**
   * @param nname
   *          the nname to set
   */
  public void setNname(String nname)
  {
    this.nname = nname;
  }


  /**
   * @return the passwort
   */
  public String getPasswort()
  {
    return passwort;
  }


  /**
   * @param passwort
   *          the passwort to set
   */
  public void setPasswort(String passwort)
  {
    this.passwort = passwort;
  }


  /**
   * @return the werkhofId
   */
  public int getWerkhofId()
  {
    return werkhofId;
  }


  /**
   * @param werkhofId
   *          the werkhofId to set
   */
  public void setWerkhofId(int werkhofId)
  {
    this.werkhofId = werkhofId;
  }


  /**
   * @return the berechtigung
   */
  public String getBerechtigung()
  {
    return berechtigung;
  }


  /**
   * @param berechtigung
   *          the berechtigung to set
   */
  public void setBerechtigung(String berechtigung)
  {
    this.berechtigung = berechtigung;
  }


  /**
   * @return the neuDatum
   */
  public Date getNeuDatum()
  {
    return neuDatum;
  }


  /**
   * @param neuDatum
   *          the neuDatum to set
   */
  public void setNeuDatum(Date neuDatum)
  {
    this.neuDatum = neuDatum;
  }


  /**
   * @return the aendDatum
   */
  public Date getAendDatum()
  {
    return aendDatum;
  }


  /**
   * @param aendDatum
   *          the aendDatum to set
   */
  public void setAendDatum(Date aendDatum)
  {
    this.aendDatum = aendDatum;
  }


  /**
   * @return the neuUser
   */
  public int getNeuUser()
  {
    return neuUser;
  }


  /**
   * @param neuUser
   *          the neuUser to set
   */
  public void setNeuUser(int neuUser)
  {
    this.neuUser = neuUser;
  }


  /**
   * @return the aendUser
   */
  public int getAendUser()
  {
    return aendUser;
  }


  /**
   * @param aendUser
   *          the aendUser to set
   */
  public void setAendUser(int aendUser)
  {
    this.aendUser = aendUser;
  }
}


<?xml version="1.0" encoding="UTF-8"?>
<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_2_0.xsd"
  version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">

	<persistence-unit name="spk" transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
		<class>de.klemens.stadt.spk_main.data.pojos.User</class>
		<properties>
			<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
			<property name="javax.persistence.jdbc.url" value="jdbc:h2:F:\spk	est" />
			<property name="javax.persistence.jdbc.user" value="xxxx" />
			<property name="javax.persistence.jdbc.password" value="yyyyy" />
			<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
			<property name="show_sql" value="true" />
			<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
		</properties>
	</persistence-unit>
</persistence>

Wie? Im Programm?

Schon mal die csv-Datei genau angeschaut - komische Zeilen usw.?

Die csv Datei ist ok.

Im Programm kann ich mit
User find = entityManager.find(User.class, 1);
die eben eingefügten Nutzer auslesen -> heißt für mich Daten da = insert und commit sind ok.

Ich habe nur keine Idee warum die Datenbank korrupt sein sollte nachdem ich den EntityManager und die EntityManagerFactory geschlossen habe.

Hast du mal debuggt und geschaut ob auch alle Felder der User richtig gefüllt sind?

Wann genau bekommst du den Fehler wenn du per WebConsole in die DB schaust? Bist du dir sicher, das der Fehler durch deinen Code verursacht wurde? Kannst du eventuell die CSV-Datei per WebConsole in die DB importieren? Taucht dort der gleiche Fehler auf?

Am Code selber kann ich nichts erkennen.

Ja, Ich bekomme einen vollständigen User, sogar das Datum hat automatisch das gewünschte Format.

Sofort nach dem Klick auf „Verbinden“.

Nein. Aber ich habe auch keine Ahnung was es sonnst sein könnte.

Das war mein erster Versuch. Endete in der Meldung das die Anzahl der Spalten nicht übereinstimmen würde.

Edit: Ich habe die DB im „Embedded“ Modus. Soll ich das mal auf „Server“ umstellen?

du host doch nur einen User - den ersten. Also prüfst du nur eine Zeile??

Irgendwo ein ; zu wenig oder ;;; oder sowas? Ein ; in einem String usw.

Mach mal den EntityManager zu, hol dir einen neuen und such dann nach einem User im Java-Code: klappt das?

funktioniert es, auf die mit dem main-Programm erstelle DB wieder mit dem main-Programm zuzugreifen, dort nicht als corrupted angesehen?
vielleicht irgendwelche unterschiedlichen Dateiformate/ Encoding usw.,

keine Problemlösungsfindung aber Fehlervermeidung könnte es sein, möglichst nur ein Grundsystem den Zugang zu gestatten,
kann nicht die ‘Web-Konsole’ auch die CSV-Datei verarbeiten, wenn bestimmtes Kommando bekommen?

gleiche H2-Version/ -Library usw. versichert?


sind die DB-Datei(en) menschenlesbar oder zumindest von überschaubarer Länge?
kannst du mit beiden Programmen eine möglichst simple Test-DB anlegen, so dass untereinander corruptet
und die Datei(en) vergleichend analysieren?

mit etwas oder viel Glück einfache Unterschiede erkennbar, wahrscheinlich aber nur Datenmüll, eben unterschiedlicher…

...```
Wahrscheinlich von Dir beabsichtigt, aber zur Sicherheit die Frage: Was ist mit split[0]?

```entityManager.merge(u);```
Wenn Du neue Entities der DB hinzufügen willst, nutze lieber persist anstatt merge. Für das "Warum" z.B. siehe hier: [JPA EntityManager: Why use persist() over merge()? - Stack Overflow](http://stackoverflow.com/questions/1069992/jpa-entitymanager-why-use-persist-over-merge)

Ich habe die csv Datei zum Testen auch nur auf eine Zeile ruduziert.

Nö, das ist korrekt.

Das muss ich nochmal ausprobieren.

[QUOTE=nillehammer;123985]u.setVname(split[1]);
Wahrscheinlich von Dir beabsichtigt, aber zur Sicherheit die Frage: Was ist mit split[0]?[/QUOTE]
Da steht ne ID drin. Die wird aber automatisch generiert, daher lass ich das weg.

[QUOTE=SlaterB;123984]
sind die DB-Datei(en) menschenlesbar oder zumindest von überschaubarer Länge?
kannst du mit beiden Programmen eine möglichst simple Test-DB anlegen, so dass untereinander corruptet
und die Datei(en) vergleichend analysieren?

mit etwas oder viel Glück einfache Unterschiede erkennbar, wahrscheinlich aber nur Datenmüll, eben unterschiedlicher…[/QUOTE]

Das muss ich alles nochmal überprüfen…

Ich hab meinen letzten Post per Edit noch um einen Hinweis ergänzt. War evtl etwas ungeschickt. Aber check das auch noch mal.

Und dann noch was zu Deiner Entity. Du verwendest Primitives. Das ist im Zusammenhang mit JPA ungünstig. Der Schluss “Darf in der DB nicht null sein, also in der Entity auch nicht, deswegen nehme ich Primitives.” ist unkorrekt. Für JPA ist es ggf. sehr entscheidend, dass z.B. Ids in der Entity null sind. Daran erkennt es nämlich, dass die Entity neu ist. Kann man auch umkonfigurieren, aber muss nicht sein… Nimm in Entities immer Wrapper Types.

Ja das klappt tatsächlich…

Kann ich nicht feststellen das das anders wäre…

Ja ist gleich.

[QUOTE=SlaterB;123984]
sind die DB-Datei(en) menschenlesbar oder zumindest von überschaubarer Länge?
kannst du mit beiden Programmen eine möglichst simple Test-DB anlegen, so dass untereinander corruptet
und die Datei(en) vergleichend analysieren?

mit etwas oder viel Glück einfache Unterschiede erkennbar, wahrscheinlich aber nur Datenmüll, eben unterschiedlicher…[/QUOTE]
Die teile die lesbar sind sind nahezu identisch

[QUOTE=nillehammer;123985]
entityManager.merge(u);
Wenn Du neue Entities der DB hinzufügen willst, nutze lieber persist anstatt merge. Für das „Warum“ z.B. siehe hier: JPA EntityManager: Why use persist() over merge()? - Stack Overflow[/QUOTE]
Danke dafür, werd ich mir merken

[QUOTE=nillehammer;123988]
Und dann noch was zu Deiner Entity. Du verwendest Primitives. Das ist im Zusammenhang mit JPA ungünstig. Der Schluss „Darf in der DB nicht null sein, also in der Entity auch nicht, deswegen nehme ich Primitives.“ ist unkorrekt. Für JPA ist es ggf. sehr entscheidend, dass z.B. Ids in der Entity null sind. Daran erkennt es nämlich, dass die Entity neu ist. Kann man auch umkonfigurieren, aber muss nicht sein… Nimm in Entities immer Wrapper Types.[/QUOTE]
Auch dafür Danke.

Aber insgesamt… DB scheint ja in Ordnung zu sein, nur meint die Konsole das das nicht der Fall wäre. Java kann damit aber immer noch arbeiten.
Wenn noch jemand Ideen hat - immer her damit :slight_smile:
Ansonsten muss ich wohl damit leben.

Mal ganz doof gefragt, hast du schon mal geschaut ob das eventuell ein (bekannter) Bug der WebConsole ist?