2011-11-12 19 views
5

ho appena impostato un progetto maven/jpa/hibernate progetto ancora abbastanza minimale, in cui sto cercando di mantenere un oggetto.EntityManager non scrive nel database

La mia classe è piuttosto semplice:

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

mio persistence.xml è molto semplice così:

<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> 

E infine ecco il codice che uso per mantenere l'oggetto:

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

Ora ci sono due cose che mi aspetterei di accadere qui: in primo luogo, mi aspetterei che il tavolo Persona sia cr mangiato (a causa di hibernate.hbm2ddl.auto = aggiornamento). Questo è successo una volta, e in modo corretto ha scritto fuori

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

ma io non può riprodurre affatto. Ogni volta che avvio il mio programma, i file di database hsqldb vengono creati, ma non vengono create tabelle.

In secondo luogo, mi aspetto che l'oggetto persistente venga archiviato nel database, ma non lo è. Inoltre, la creazione manuale dello schema del database non risolve il problema, quindi non è ciò che lo sta causando. Il codice persistente viene eseguito senza eccezioni o avvisi nell'output, tutto sembra perfettamente a posto. Ma l'oggetto non arriva nel database. L'oggetto non viene inoltre trovato quando si esegue una query al gestore di entità con un "da Persona".

L'interrogazione tuttavia sembra essere l'unica cosa che funziona. posso inserire manualmente un dato nel database e la query "from Person" lo recupererà con successo.

quindi, qualche suggerimento su cosa sto facendo male qui?

+1

Hum va bene, quindi vi posterò come un commento, perché io non sono autorizzato a rispondere alla mia domanda (ancora?): ho trovato il mio problema. em.getTransaction() commit().; Thread.sleep (1000); em.close(); ha fatto il trucco. dopo il mio test case, la JVM si spegne così velocemente che hsqldb semplicemente non ha avuto abbastanza tempo per mantenere i dati commessi su disco. Non chiedermi perché la JVM non è mantenuta in vita, non faccio alcuna chiamata a System.exit() o altro, il mio metodo di test di junit finisce semplicemente lì. Per qualche ragione, la JVM non è mantenuta attiva da quello che presumo sia un altro thread che dovrebbe persistere nel mio oggetto. – MisterD

+0

Hai il permesso di rispondere alla tua domanda, infatti incoraggiato a farlo. Leggi le FAQ. La tua domanda è buona, quindi riassumi la risposta in modo che tutti possano trarne beneficio. – Siddharth

risposta

5

Aggiungendo alla buona risposta da axtavt e chiarire come ha funzionato il tuo sonno (1000): per situazioni di sviluppo in cui vuoi la persistenza assolutamente sincrona, disattiva il write_delay predefinito.

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

Questo significa che ogni affermazione viene scritto su disco prima che il risultato viene restituito al chiamante. Naturalmente, nel normale funzionamento, è possibile aumentare questo valore. Il valore predefinito è 500 ms, che richiede sleep (1000). Le informazioni fornite sono per HSQLDB versione 2.2.x.

3

è necessario aggiungere shutdown=true all'URL database (o emettere un explict SHUTDOWN di comando), al fine di chiudere correttamente un database in-process HSQLDB:

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

Vedi anche:

+0

Ah sì, ho dimenticato di dirlo, l'ho fatto prima e l'ho rimosso perché pensavo che potesse contribuire al problema. non funziona con o senza di essa. :( – MisterD

0

Spero che questo aiuti qualcuno. Il suggerimento di impostare il ritardo di scrittura su 0 ms funziona, ma non funziona dall'url a meno che non si stia creando un nuovo db. Per farla applicare, eseguirlo in uno script durante la connessione al database utilizzando l'istruzione SQL di seguito:

set files write delay false 

Così, per esempio, è possibile eseguire utilizzando lo sqltool.vaso in questo modo:

java -jar /path/to/sqltool.jar -sql "set files write delay false;" --inlinerc=<rc spec here> 
Problemi correlati