JPA + EclipseLink+ HSQLDB 不建表
JPA + EclipseLink+ HSQLDB does not create tables
我正在尝试使用 ORM 功能扩展现有的 Java 工具,并希望将 EclipseLink 与 HSQLDB 结合使用。创建连接本身不是问题(它甚至会创建您在文件系统上期望的 HSQLDB file/folder 结构),但是没有创建数据库方案。当使用 HSQLDB 管理器连接到数据库时,它只会显示数据库属性,否则完全是空的。据我所知,我采取了所有必要的步骤来创建和初始化数据库,我将我的代码与 JPA/EclipseLink 上的 3 个教程和几个 Whosebug 帖子进行了比较,但找不到问题所在。感谢任何帮助。
这是我的相关源代码:
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() 它将 return 预期结果(创建的对象数)。现在这显然意味着数据库连接正常并且工作正常,但是应用程序在退出时正在删除表。如果我将 HSQLDB 配置为写入 persistence.xml 中的内存,这将是 HSQLDB 的预期行为,但我选择写入文件。更奇怪的是,HSQLDB 管理器在尝试访问数据库时会 return SQLException,因为它上面有锁。这意味着我的 HSQLDB 实现正在写入文件系统,而不是内存,并且表应该持久存在。 HSQLDB 默认也是创建 MEMORY 表,而不是 TEMPORARY 表(根据 http://hsqldb.org/doc/guide/guide.html#sgc_persist_tables),所以这也不应该是问题。
问题是 EntityManagerFactory
没有关闭。显然,HSQLDB 在此之前不会将数据持久保存到磁盘,因为缓存(在这种情况下也使它成为 non-concurrent)。
正在添加
factory.close();
运行结束前的代码将使其写入脚本文件。
我确信有一些方法可以禁用缓存并使其立即写入磁盘,但我没有费心去进一步研究它。
我用 Apache Derby 尝试了完全相同的代码(更新 pom.xml 和 persistence.xml,相同的代码)并且它的行为符合我的预期,写入持久化对象和提交事务。
我正在尝试使用 ORM 功能扩展现有的 Java 工具,并希望将 EclipseLink 与 HSQLDB 结合使用。创建连接本身不是问题(它甚至会创建您在文件系统上期望的 HSQLDB file/folder 结构),但是没有创建数据库方案。当使用 HSQLDB 管理器连接到数据库时,它只会显示数据库属性,否则完全是空的。据我所知,我采取了所有必要的步骤来创建和初始化数据库,我将我的代码与 JPA/EclipseLink 上的 3 个教程和几个 Whosebug 帖子进行了比较,但找不到问题所在。感谢任何帮助。
这是我的相关源代码:
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() 它将 return 预期结果(创建的对象数)。现在这显然意味着数据库连接正常并且工作正常,但是应用程序在退出时正在删除表。如果我将 HSQLDB 配置为写入 persistence.xml 中的内存,这将是 HSQLDB 的预期行为,但我选择写入文件。更奇怪的是,HSQLDB 管理器在尝试访问数据库时会 return SQLException,因为它上面有锁。这意味着我的 HSQLDB 实现正在写入文件系统,而不是内存,并且表应该持久存在。 HSQLDB 默认也是创建 MEMORY 表,而不是 TEMPORARY 表(根据 http://hsqldb.org/doc/guide/guide.html#sgc_persist_tables),所以这也不应该是问题。
问题是 EntityManagerFactory
没有关闭。显然,HSQLDB 在此之前不会将数据持久保存到磁盘,因为缓存(在这种情况下也使它成为 non-concurrent)。
正在添加
factory.close();
运行结束前的代码将使其写入脚本文件。
我确信有一些方法可以禁用缓存并使其立即写入磁盘,但我没有费心去进一步研究它。
我用 Apache Derby 尝试了完全相同的代码(更新 pom.xml 和 persistence.xml,相同的代码)并且它的行为符合我的预期,写入持久化对象和提交事务。