2011-11-12 18 views
5

Właśnie ustawiłem do tej pory jeszcze dość minimalny projekt projektu maven/jpa/hibernate, w którym próbuję utrwalić obiekt.EntityManager nie zapisuje do bazy danych

Moja klasa jest dość prosta:

@Entity 
public class Person { 
    @Id @GeneratedValue 
    private int id; 
    private String name; 
} 

Moja persistence.xml jest bardzo prosty, a także:

<persistence 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_2_0.xsd" 
    version="2.0"> 
    <persistence-unit name="Fahrplan_v2"> 
     <class>model.Person</class> 
     <properties> 
      <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" /> 
      <property name="hibernate.connection.url" value="jdbc:hsqldb:file:data/db/db" /> 
      <property name="hibernate.connection.username" value="sa" /> 
      <property name="hibernate.connection.password" value="" /> 
      <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" /> 
      <property name="hibernate.hbm2ddl.auto" value="update" /> 
     </properties> 
    </persistence-unit> 
</persistence> 

I wreszcie oto kod używam utrzymują się obiekt:

EntityManager em = entityManagerFactory.createEntityManager(); 
em.getTransaction().begin(); 
em.persist(person); 
// em.flush(); <- does not effect outcome. 
em.getTransaction().commit(); 
em.close(); 

Teraz są dwie rzeczy, których oczekiwałbym tutaj: Po pierwsze, spodziewam się, że stół Person będzie eated (z powodu hibernate.hbm2ddl.auto = update). To zdarzyło się raz, i to poprawnie wypisało

CREATE MEMORY TABLE PUBLIC.PERSON(
    ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY, 
    NAME VARCHAR(255) 
) 

ale nie mogę tego odtworzyć w ogóle. Za każdym razem, gdy uruchamiam program, tworzone są pliki bazy danych hsqldb, ale nie są tworzone żadne tabele.

Po drugie, oczekuję, że utrwalony obiekt będzie przechowywany w bazie danych, ale tak nie jest. Ponadto ręczne tworzenie schematu bazy danych nie rozwiązuje problemu, więc nie jest to przyczyną. Ciągły kod działa bez żadnych wyjątków lub ostrzeżeń na wyjściu, wszystko wygląda doskonale. Ale obiekt po prostu nie dociera do bazy danych. Obiekt nie zostanie znaleziony podczas sprawdzania menedżera encji za pomocą "od osoby".

Zapytanie wydaje się jednak jedyną rzeczą, która działa. mogę ręcznie wstawić dane do bazy danych, a zapytanie "od osoby" z powodzeniem je pobierze.

tak, wszelkie wskazówki dotyczące tego, co robię źle tutaj?

+1

Hum w porządku, więc będę pisać go jako komentarz, bo nie wolno mi odpowiedzieć na moje własne pytanie (jeszcze?): znalazłem mój problem. em.getTransaction(). commit(); Thread.sleep (1000); em.close(); załatwił sprawę. po moim przypadku testowym JVM wyłączyła się tak szybko, że hsqldb po prostu nie miał wystarczająco dużo czasu, aby utrwalić przesłane dane na dysk. Nie pytaj mnie, dlaczego JVM nie jest utrzymywana przy życiu, nie wykonuję żadnych wywołań System.exit() ani nic takiego, moja metoda testów jednostkowych po prostu się kończy. Z jakiegoś powodu JVM nie jest utrzymywana przy życiu przez to, co zakładam, jest kolejnym wątkiem, który powinien upierać się przed moim obiektem. – MisterD

+0

Możesz odpowiedzieć na swoje pytanie, zachęcić do tego. Przeczytaj FAQ. Twoje pytanie jest dobre, więc dobrze podsumuj odpowiedź, aby wszyscy mogli z niej skorzystać. – Siddharth

Odpowiedz

5

Dodanie do dobrej odpowiedzi i wyjaśnienia przez axtavt Jak wyglądał twój sen (1000): W sytuacjach, gdy potrzebujesz absolutnie synchronicznej trwałości, wyłącz domyślną metodę write_delay.

<property name="hibernate.connection.url" 
     value="jdbc:hsqldb:file:data/db/db;shutdown=true;hsqldb.write_delay_millis=0"/>    

Oznacza to, że każda instrukcja jest zapisywana na dysku, zanim wynik zostanie zwrócony do osoby dzwoniącej. Oczywiście podczas normalnej pracy można zwiększyć tę wartość. Wartość domyślna to 500 ms, która wymaga uśpienia (1000). Podane informacje dotyczą HSQLDB w wersji 2.2.x.

3

Trzeba dodać shutdown=true do adresu URL bazy danych (lub wydać explict polecenia SHUTDOWN) w celu prawidłowego zamykania bazy danych w procesie HSQLDB:

<property name="hibernate.connection.url" 
    value="jdbc:hsqldb:file:data/db/db;shutdown=true" />    

Zobacz także:

+0

Ach tak, zapomniałem o tym wspomnieć, miałem to wcześniej i usunąłem, ponieważ myślałem, że może przyczynić się do tego problemu. nie działa z lub bez niego. :( – MisterD

0

Mam nadzieję, że to komuś pomaga. Sugestia ustawienia opóźnienia zapisu na 0 ms działa, ale nie działa z adresu URL, chyba że tworzysz nową bazę danych. Mieć to zastosowanie, należy uruchomić go w skrypcie podczas połączenia z bazą danych za pomocą poniższego sql:

set files write delay false 

Tak na przykład, można go uruchomić za pomocą sqltool.jar tak:

java -jar /path/to/sqltool.jar -sql "set files write delay false;" --inlinerc=<rc spec here> 
Powiązane problemy