java - Java SE 环境中的 JPA : Entity classes loaded without defenition in persistence. xml

标签 java hibernate jpa

我正在准备 Oracle JPAD 认证,所以我在 Java SE 环境中尝试了一些实体(至少,我是这么想的……)。我注意到一些事情,我希望有人能对此有所启发。

Pro JPA2 这本书是我正在阅读的。在第 2 章末尾的某个地方,有一个示例 persistence.xml 文件,其中定义了一个类。好的,这就是在 Java SE 环境中的方式,因为您实际上并没有将整个 shebang 放在一个容器中。但奇怪的是:我有两个用@Entity 注释的实体类,但没有将其中任何一个添加到 persistence.xml 中。但仍在加载!我目瞪口呆。我现在唯一能想到的是,我不在 SE 环境中,或者它是一个新的 hibernate 功能......

持久性.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="employees" transaction-type="RESOURCE_LOCAL">

    <properties>
      <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" />
      <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:." />
      <property name="javax.persistence.jdbc.user" value="SA" />
      <property name="javax.persistence.jdbc.password" value="" />

      <property name="hibernate.show_sql" value="false" />
      <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
      <property name="hibernate.connection.shutdown" value="true" />
      <property name="hibernate.hbm2ddl.auto" value="create-drop" />
    </properties>

  </persistence-unit>
</persistence> 

实体:

@Entity
   @Access(AccessType.FIELD)
   public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private Date startDate;
    private Long salary;

    public Employee() {
    }

    public Employee(String name) {
        this.name = name;
    }

    public Employee(String name, Long salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public Long getSalary() {
        return salary;
    }

    public void setSalary(Long salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee [name=" + name + ", salary=" + salary + ", startDate=" + startDate + "]";
    }
}

一个测试:

public class TestConnection {

    private static EntityManagerFactory entityManagerFactory;
    private static EntityManager entityManager;
    private static final String PERSISTENCE_UNIT_NAME = "employees";

    @BeforeClass
    public static void initEntityManager() throws Exception {
        entityManagerFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
        entityManager = entityManagerFactory.createEntityManager();
        TableStructurePrinter.outputTableStructure(entityManager);
    }

    @AfterClass
    public static void closeEntityManager() {
        entityManager.close();
        entityManagerFactory.close();
    }

    @BeforeMethod
    public void setupDB() throws Exception {
        entityManager.getTransaction().begin();
        LoadEmployees.load(entityManager, 4);
    }

    @AfterMethod
    public void cleanDB() throws Exception {
        entityManager.getTransaction().rollback();
    }

    @Test
    public void testCountEmployees() {
        Query q = entityManager.createQuery("select e from Employee e");
        assertEquals(q.getResultList().size(), 4);
    }

}

以及我的 TableStructurePrinter 的输出(这是来自 INFORMATION_SCHEMA.SYSTEM_TABLES 和 INFORMATION_SCHEMA.SYSTEM_COLUMNS 的简单选择语句):

T.TABLE_TYPE         T.TABLE_NAME           C.ORDINAL_POSITION C.COLUMN_NAME                 C.TYPE_NAME        C.COLUMN_SIZE
===================  ===================   =================== ===================   ===================  ===================
TABLE                EMPLOYEE                                1 ID                                 BIGINT                   64
TABLE                EMPLOYEE                                2 NAME                              VARCHAR                  255
TABLE                EMPLOYEE                                3 SALARY                             BIGINT                   64
TABLE                EMPLOYEE                                4 STARTDATE                       TIMESTAMP                   26

最佳答案

我注意到您在玩 Java SE。基本上在 Java SE 环境中,您必须指定托管类,并且任何其他行为都是不可移植的(查看下面的 8.2.1.6.4 托管类列表)。作为论据,我将添加 JPA 2.0 规范的摘录,这些摘录实际上解释了 Hibernate(或我测试过的 EclipseLink)是如何工作的(尽管不可移植)以及您应该如何工作:

由持久性单元管理的一组托管持久性类是使用以下一个或多个定义的:

8.2.1.6 映射文件、jar 文件、类、排除未列出的类

  • Annotated managed persistence classes contained in the root of the persistence unit (unless the exclude-unlisted-classes element is specified)
  • One or more object/relational mapping XML files
  • One or more jar files that will be searched for classes
  • An explicit list of classes The set of entities managed by the persistence unit is the union of these sources, with the mapping meta- data annotations (or annotation defaults) for any given class being overridden by the XML mapping

The set of entities managed by the persistence unit is the union of these sources[...]

8.2.1.6.1 持久化单元根中的注释类

All classes contained in the root of the persistence unit are searched for annotated managed persistence classes—classes with the Entity, Embeddable, or MappedSuperclass annotation—and any mapping metadata annotations found on these classes will be processed, or they will be mapped using the mapping annotation defaults. If it is not intended that the annotated persistence classes contained in the root of the persistence unit be included in the persistence unit, the exclude-unlisted-classes element must be specified as true. The exclude-unlisted-classes element is not intended for use in Java SE environments.

8.2.1.6.4 托管类列表

[...]

A list of all named managed persistence classes must be specified in Java SE environments to insure portability. Portable Java SE applications should not rely on the other mechanisms described here to specify the managed persistence classes of a persistence unit. Persistence providers may require that the set of entity classes and classes that are to be managed must be fully enumerated in each of the persistence.xml files in Java SE environments.

关于java - Java SE 环境中的 JPA : Entity classes loaded without defenition in persistence. xml,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22686846/

相关文章:

java - 如何将 java.sql.Timestamp 转换为 java.time.OffsetDateTime?

Java Hibernate HQL无法指定目标表

java - 错误 javax.validation.ConstraintViolationException

java - thymeleaf 和 spring boot 应用程序中未显示表单验证错误

java - 由 : org. hibernate.exception.JDBCConnectionException 引起:调用 Driver#connect 时出错

java - 数据库信息 -> 对象 : how should it be done?

java - 如何在 Android 上裁剪四点之间的图像

java - Java 内存模型和 C++11 内存模型有什么相似之处?

java - 集群环境中的 Hibernate session 缓存行为?

java - 使用 JPA 重新创建表结构