JPA + EclipseLink+ HSQLDB 不创建表

Posted

技术标签:

【中文标题】JPA + EclipseLink+ HSQLDB 不创建表【英文标题】:JPA + EclipseLink+ HSQLDB does not create tables 【发布时间】:2016-12-28 14:35:53 【问题描述】:

我正在尝试使用 ORM 功能扩展现有的 Java 工具,并希望将 EclipseLink 与 HSQLDB 结合使用。创建连接本身不是问题(它甚至会在文件系统上创建您期望的 HSQLDB 文件/文件夹结构),但是没有创建数据库方案。当使用 HSQLDB 管理器连接到数据库时,它只会显示数据库属性,否则它是完全空的。据我所知,我采取了所有必要的步骤来创建和初始化数据库,我将我的代码与 JPA/EclipseLink 上的 3 个教程和几个 *** 帖子进行了比较,但找不到问题。任何帮助表示赞赏。

这是我的相关源码:

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>

运行应用程序时的控制台输出:

[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

更新:我能够稍微缩小问题范围。当我重新排列 Start.java 中的代码并创建多个对象时,然后调用 abteilungList.size() 它将返回预期结果(创建的对象数)。现在这显然意味着数据库连接正常并且工作正常,但是应用程序在退出时正在删除表。如果我将 HSQLDB 配置为在 persistence.xml 中写入内存,这将是 HSQLDB 的预期行为,但是我选择写入文件。更奇怪的是,HSQLDB 管理器在尝试访问数据库时会返回一个 SQLException,因为它上面有一个锁。这意味着我的 HSQLDB 实现正在写入文件系统,而不是内存,并且表应该保持不变。 HSQLDB 默认也是创建 MEMORY 表,而不是 TEMPORARY 表(根据http://hsqldb.org/doc/guide/guide.html#sgc_persist_tables),所以这也不应该是问题。

【问题讨论】:

我不熟悉 HSQLDB 及其选项,但如果您在应用程序中没有遇到异常,则表可能正在创建或已经存在,这只是您的方法检查或期望应该有什么问题。将 EclipseLink 日志设置为最好,以查看运行之间完成的操作,并检查您的数据库文档以查看您是否使用选项来获得预期的结果。 根据 HSQLDB 文档,一切都应该没问题(据我所知),如 OP 更新中所述。老实说,我不知道下一步该做什么。 【参考方案1】:

问题是EntityManagerFactory 没有关闭。显然,由于 chaching,HSQLDB 不会在此之前将数据持久化到磁盘(这也使得它在这种情况下非并发)。

添加 factory.close(); 在运行时结束前将代码写入脚本文件。

我确信有一些方法可以禁用缓存并使其立即写入磁盘,但我没有费心去进一步研究它。

我用 Apache Derby 尝试了完全相同的代码(更新了 pom.xml 和 persistence.xml,相同的代码),它的行为符合我的预期,写入持久化对象并提交事务。

【讨论】:

以上是关于JPA + EclipseLink+ HSQLDB 不创建表的主要内容,如果未能解决你的问题,请参考以下文章

JPA 使用指南 /Eclipselink/JPA 实体生成器

JPA - EclipseLink - 如何更改默认模式

JPA/EclipseLink - 计算列

JPA 从 EclipseLink 到哪个提供商?

jpa2/eclipselink 的合适 DAO 结构是啥?

JPA - 使用 EclipseLink 保持单向一对多关系失败