NetBeans > Hibernate Wizards > Create POJOs from database" (Derby) 在 hbm.xml 中不生成任何关系映射

NetBeans > Hibernate Wizards > Create POJOs from database" (Derby) does not generate any relationship-mappings in hbm.xml

我正在从 Derby 10.14.2.0 数据库中生成 POJO NetBeans IDE 11.3, 休眠 ORM 5.4.31.

它不会在 hbm.xml 或像 many-to-one/one-to-one 这样的实体 类 中生成任何 relationship-mappings

我将 Derby 示例项目 用于 mcve

我使用了 Derby 示例数据库中的两个 table。

产品和采购订单

采购订单中引用了产品 table。

Table PurchaseOrderFOREIGN_KEY_PRODUCT_ID. 可以在下图中看到。

hibernate.cfg

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.DerbyTenSevenDialect</property>
        <property name="hibernate.connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
        <property name="hibernate.connection.url">jdbc:derby://localhost:1527/sample</property>
        <property name="hibernate.connection.username">app</property>
        <property name="hibernate.connection.password">app</property>
       
        <mapping resource="com/pojo/Product.hbm.xml"/>
        <mapping resource="com/pojo/PurchaseOrder.hbm.xml"/>
    </session-factory>
</hibernate-configuration>  

我也试过定义休眠属性

<property name="hibernate.default_catalog">app</property>

<property name="hibernate.default_schema">app</property>  

但是不行,这没用。

hibernate.reveng.xml

<hibernate-reverse-engineering>
  <schema-selection match-schema="APP"/>
  <table-filter match-name="PRODUCT"/>
  <table-filter match-name="PURCHASE_ORDER"/>
</hibernate-reverse-engineering>

PurchaseOrder.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.pojo.PurchaseOrder" table="PURCHASE_ORDER" schema="APP" optimistic-lock="version">
        <id name="orderNum" type="int">
            <column name="ORDER_NUM" />
            <generator class="assigned" />
        </id>
        <property name="customerId" type="int">
            <column name="CUSTOMER_ID" not-null="true" />
        </property>
        <property name="productId" type="int">
            <column name="PRODUCT_ID" not-null="true" />
        </property>
        <property name="quantity" type="java.lang.Short">
            <column name="QUANTITY" />
        </property>
        <property name="shippingCost" type="big_decimal">
            <column name="SHIPPING_COST" precision="12" />
        </property>
        <property name="salesDate" type="date">
            <column name="SALES_DATE" length="10" />
        </property>
        <property name="shippingDate" type="date">
            <column name="SHIPPING_DATE" length="10" />
        </property>
        <property name="freightCompany" type="string">
            <column name="FREIGHT_COMPANY" length="30" />
        </property>
    </class>
</hibernate-mapping>  

在上面的 PurchaseOrder.hbm.xml 文件中,应该会生成 relationship mapping 但您可以看到它 缺失

为什么 relationship mapping 即使是 Derby 的示例数据库也不生成?

使用 MySQL 它工作正常。

Hibernate 不正确支持 Derby 吗?
什么是解决方案?

简答

您快要解决它了。简短的回答是:只需将此行添加到您的 hibernate.cfg.xml 配置文件(添加空目录):

<property name="hibernate.default_catalog"/>

我的 hibernate.cfg.xml 看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.DerbyDialect</property>
    <property name="hibernate.connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
    <property name="hibernate.connection.url">jdbc:derby://localhost:1527/sample</property>
    <property name="hibernate.connection.username">app</property>
    <property name="hibernate.connection.password">app</property>
    <property name="hibernate.default_catalog"/>
  </session-factory>
</hibernate-configuration>

使用此配置,NetBeans Hibernate POJO 向导可以很好地生成关系映射。查看生成的 PurchaseOrder.hbm.xml 文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated 13.06.2021 12:06:13 by Hibernate Tools 4.3.1 -->
<hibernate-mapping>
    <class name="pojo.PurchaseOrder" table="PURCHASE_ORDER" schema="APP" optimistic-lock="version">
        <id name="orderNum" type="int">
            <column name="ORDER_NUM" />
            <generator class="assigned" />
        </id>
        <many-to-one name="customer" class="pojo.Customer" fetch="select">
            <column name="CUSTOMER_ID" not-null="true" />
        </many-to-one>
        <many-to-one name="product" class="pojo.Product" fetch="select">
            <column name="PRODUCT_ID" not-null="true" />
        </many-to-one>
        <property name="quantity" type="java.lang.Short">
            <column name="QUANTITY" />
        </property>
        <property name="shippingCost" type="big_decimal">
            <column name="SHIPPING_COST" precision="12" />
        </property>
        <property name="salesDate" type="date">
            <column name="SALES_DATE" length="10" />
        </property>
        <property name="shippingDate" type="date">
            <column name="SHIPPING_DATE" length="10" />
        </property>
        <property name="freightCompany" type="string">
            <column name="FREIGHT_COMPANY" length="30" />
        </property>
    </class>
</hibernate-mapping>

长答案

特此说明,NetBeans 11.3 POJO 向导使用以下休眠版本:

NetBeans 向导使用这些库从数据库生成 POJO。基本工作流程是:

  1. 从数据库中获取所有table,它使用方法getTablesDatabaseMetaData
  2. 创建所有 table 的完全限定名称的列表。完全限定名称是 [catalog].[schema].[table] 形式的 table 的名称。 Derby 数据库 returns catalog 参数的空字符串(不是 null 而是空的)。 Hibernate 很好地处理了它,但我们可以看到不同的数据库在这里表现不同。正如您在这里看到的,甚至还有 comment
  3. 在第 2 步之后,我们有一个包含所有 table 的 Map 集合,这些集合具有 APP.CUSTOMER、APP.PRODUCT 等键。到目前为止,还不错。
  4. Hibernate 使用 getExportedKeys 方法获取特定 table 的所有外键,例如 APP.CUSTOMER。
  5. Hibernate 工具再次尝试以 [catalog].[schema].[table] 的形式形成 table 的完全限定名称,但这次不太好,它以 table 名称结尾 .APP.CUSTOMER(见应用前的点)。参见 here。 qualify 方法检查 catalog!=nullgetExportedKeys returns 它是空字符串而不是 null。
  6. Hibernate 工具尝试使用在第 3 步创建的映射从外键映射 table,但失败了(因为点)。

解决方法有效,因为我们告诉 Hibernate 目录不是空的而是空的。看到这个 lines.

结论

所以 Hibernate 不能与 derby 一起工作的原因是因为 derby JDBC 客户端在返回有关外键的信息时表现不同。它 returns 目录参数的空字符串但 MySQL 显然 returns null.

hibernate orm 框架在解析有关 tables 的信息时对这种情况有特殊处理,但在处理外键时却没有。所以我想它可以被认为是 Hibernate 工具 4.3.1

中的一个错误