简体   繁体   中英

JPA + EclipseLink+ HSQLDB does not create tables

I am trying to extend an existing Java tool with ORM functionality and want to use EclipseLink in conjunction with HSQLDB. Creating the connection itself is not a problem (it even creates the HSQLDB file/folder structure you'd expect on the filesystem), however no database scheme is being created. When connecting to the database using HSQLDB manager it will only show the database properties, it's completely empty otherwise. As far as I can tell I took all the necessary steps to create and initialize the database, I compared my code with 3 tutorials on JPA/EclipseLink and several stackoverflow posts, but could not find the issue. Any help is appreciated.

Here is my relevant source code:

Start.java:

package start;

import java.util.List;

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

import DBmodel.Abteilung;

public class Start {

    private Start() {
    }

    private static final String PERSISTENCE_UNIT_NAME = "LNDB";
    private static EntityManagerFactory factory;

    public static void main(String[] args) {

        factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
        EntityManager em = factory.createEntityManager();

        Query q = em.createQuery("select a from Abteilung a");
        List<Abteilung> abteilungList = q.getResultList();
        for (Abteilung abt : abteilungList) {
            System.out.println(abt);
        }

        System.out.println("Elements: " + abteilungList.size());
        em.getTransaction().begin();
        Abteilung abt = new Abteilung();
        abt.setName("test1");
        em.persist(abt);
        em.getTransaction().commit();

        em.close();
    }
}

Abteilung.java:

package DBmodel;

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

@Entity
@Table(name = "ABTEILUNG")
public class Abteilung {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private int id;
    @Column(name = "Name")
    private String name;

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

persistence.xml:

<?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="LNDB" transaction-type="RESOURCE_LOCAL">
           <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
                <class>DBmodel.Abteilung</class>
 <properties>
  <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" />
  <property name="javax.persistence.jdbc.url"
        value="jdbc:hsqldb:file:C:\tmpD\LN" />
  <property name="javax.persistence.jdbc.user" value="sa" />
  <property name="javax.persistence.jdbc.password" value="" />

  <!-- EclipseLink should create the database schema automatically -->
  <property name="eclipselink.target-database" value="hsql"/>
  <property name="eclipselink.ddl-generation" value="create-tables" />
  <property name="eclipselink.ddl-generation-mode" value="ddl_database_generation" />
  <property name="eclipselink.ddl-generation.output-mode" value="database" />
 </properties>

        </persistence-unit>
</persistence>

Console output when running the application:

[EL Info]: 2016-12-28 15:33:11.299--ServerSession(375741537)--EclipseLink, version: Eclipse Persistence Services - 2.3.2.v20111125-r10461
[EL Info]: 2016-12-28 15:33:18.79--ServerSession(375741537)--file:/C:/LN_Erfassung/target/classes/_LNDB login successful
Elements: 0

Update: I was able to narrow down the problem a bit. When I rearrange the code in Start.java and create multiple objects, then call abteilungList.size() it will return the expected result (number of objects created). Now this obviously means that the database connection is fine and working, but that the application is dropping tables when exiting. This would be expected behaviour for HSQLDB if I had it configured to write to memory in the persistence.xml, however I chose to write to a file instead. The thing that makes this even weirder is that HSQLDB Manager will return a SQLException while trying to access the database because there is a lock on it. That means that my HSQLDB implementation is writing to the filesystem, not memory, and that the tables should persist. HSQLDB default is also to create MEMORY tables, not TEMPORARY tables (according to http://hsqldb.org/doc/guide/guide.html#sgc_persist_tables ), so that shouldn't be the issue either.

The issue was that the EntityManagerFactory was not closed. Apparently HSQLDB does not persists data to disk before that due to chaching (which also makes it non-concurrent in this instance).

Adding factory.close(); to the code before the end of runtime will make it write to the script file.

I am sure there is some way to disable caching and make it immediately write to disk, but I haven't bothered to look any further into it.

I tried the exact same code with Apache Derby (updated pom.xml and persistence.xml, same code) and it behaved as I expected, writing on persisting the object and committing the transaction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM