I'm generating POJO from Derby 10.14.2.0 database in NetBeans IDE 11.3, Hibernate ORM 5.4.31.
It does not generate any relationship-mappings
in hbm.xml
or in entity classes like many-to-one/one-to-one
).
I used Derby sample project for mcve.
I've used two tables from Derby sample database.
Product and PurchaseOrder
Product table is referenced in PurchaseOrder.
Table PurchaseOrder
has FOREIGN_KEY_PRODUCT_ID.
can see in image below.
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>
I also tried defining hibernate properties
<property name="hibernate.default_catalog">app</property>
and
<property name="hibernate.default_schema">app</property>
But no, it won't help.
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>
In above PurchaseOrder.hbm.xml
file, relationship mapping
should be generated but you can see it is missing.
Why relationship mapping
doesn't generating even for sample database of Derby?
With MySQL it is working fine.
Doesn't Hibernate support Derby properly?
What is solution?
You were close to solving it. The short answer is: just add this line to your hibernate.cfg.xml
config file (add empty catalog):
<property name="hibernate.default_catalog"/>
My hibernate.cfg.xml
looks like this:
<?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>
With this configuration, the NetBeans Hibernate POJO wizard generates relationship mappings nicely. See the generated PurchaseOrder.hbm.xml
file:
<?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>
Just for clarification, the NetBeans 11.3 POJO wizard uses the following versions of hibernate:
The NetBeans wizard uses these libraries for the generation of POJO from databases. The basic workflow is:
DatabaseMetaData
[catalog].[schema].[table]
. The Derby database returns an empty string (not null but empty ) for the catalog parameter. Hibernate nicely handle it, but we can see that different databases behave differently here. As you can see here there is even comment about it.[catalog].[schema].[table]
but this time not so nicely and it ends up with the table name .APP.CUSTOMER (see the dot before app). See here. The qualify method checks for the catalog!=null
but getExportedKeys
returns it as empty string not null.The workaround works because we say to the Hibernate that catalog is not null but empty. See this lines.
So the reason Hibernate doesn't work with derby because the derby JDBC client behaves differently when returning info about foreign keys. It returns an empty string for the catalog parameter but MySQL apparently returns null.
The hibernate orm framework has special treatment for this case when parsing info about tables but lacks it when working with foreign keys. So I suppose it could be considered a bug in Hibernate tools 4.3.1