简体   繁体   English

JPA + EclipseLink + HSQLDB不创建表

[英]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. 我正在尝试扩展具有ORM功能的现有Java工具,并希望将EclipseLink与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. 创建连接本身不是问题(它甚至可以创建您希望在文件系统上使用的HSQLDB文件/文件夹结构),但是不会创建数据库方案。 When connecting to the database using HSQLDB manager it will only show the database properties, it's completely empty otherwise. 使用HSQLDB管理器连接到数据库时,它将仅显示数据库属性,否则将完全为空。 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. 据我所知,我采取了所有必要的步骤来创建和初始化数据库,我将代码与JPA / EclipseLink上的3个教程和一些stackoverflow帖子进行了比较,但是找不到问题。 Any help is appreciated. 任何帮助表示赞赏。

Here is my relevant source code: 这是我的相关源代码:

Start.java: 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: 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: 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). 当我重新排列Start.java中的代码并创建多个对象,然后调用abteilungList.size()时,它将返回预期的结果(创建的对象数)。 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. 如果将HSQLDB配置为写入persistence.xml中的内存,则这将是HSQLDB的预期行为,但是我选择改为写入文件。 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. 更奇怪的是,HSQLDB Manager在尝试访问数据库时将返回SQLException,因为上面有一个锁。 That means that my HSQLDB implementation is writing to the filesystem, not memory, and that the tables should persist. 这意味着我的HSQLDB实现正在写入文件系统,而不是内存,并且表应该持久化。 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. HSQLDB的默认值也是创建MEMORY表,而不是TEMPORARY表(根据http://hsqldb.org/doc/guide/guide.html#sgc_persist_tables ),因此也不应该成为问题。

The issue was that the EntityManagerFactory was not closed. 问题是EntityManagerFactory没有关闭。 Apparently HSQLDB does not persists data to disk before that due to chaching (which also makes it non-concurrent in this instance). 显然,由于高速缓存,HSQLDB不会在此之前将数据持久保存到磁盘(在这种情况下,这也使其并发)。

Adding factory.close(); 添加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. 我用Apache Derby尝试了完全相同的代码(更新的pom.xml和persistence.xml,相同的代码),它的行为与我预期的一样,写了关于持久化对象并提交事务的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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