Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foreign key creation in one-to-one table-per-concrete-class structure

Tags:

TL;DR How can I enforce the Hibernate schema creation to create a foreign key constraint in a table-per-concrete-class setup from AbstractProperty.ownerId to Owner.ownerId for the structure displayed below, without adding a Owner property to the AbstractProperty?

I'm working on a project where I have the following class structure:

Class structure sample

The Owner has a one-to-one mapping to an AbstractProperty, which is extended by the ConcreteProperty class (and others like AnotherProperty, but that's not really relevant for the rest of this question).

The AbstractProperty really has only one property, the abstractPropertyId. Therefor, we want to use the table-per-concrete-class structure, ending up with the tables Owner, ConcreteProperty, and tables for the other AbstractProperty extending classes (AnotherProperty).

To this end, I created the following mapping for Owner:

<?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 package="com.example">     <class name="Owner">         <id name="ownerId">             <generator class="identity"/>         </id>         <property name="ownerProperty"/>         <one-to-one name="abstractProperty"/>     </class> </hibernate-mapping> 

And for the AbstractProperty:

<?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 package="com.example">     <class name="AbstractProperty" abstract="true">         <id name="ownerId">             <generator class="foreign">                 <param name="property">ownerId</param>             </generator>         </id>         <union-subclass name="ConcreteProperty">             <property name="concreteProperty"/>         </union-subclass>         <union-subclass name="AnotherProperty">             <property name="anotherProperty"/>         </union-subclass>     </class> </hibernate-mapping> 

This works.

However, and here is my question, using this mapping and having Hibernate create the schema for me (<property name="hbm2ddl.auto">create</property>), it does not create a foreign key constraint from the ConcreteProperty.ownerId database field to the Owner.ownerId field. It does when I create the inverse constrained one-to-one field from the AbstractProperty to Owner using this mapping for AbstractProperty (where the owner field is of type Owner in the AbstractProperty java class):

<?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 package="com.example">     <class name="AbstractProperty" abstract="true">         <id name="ownerId">             <generator class="foreign">                 <param name="property">ownerId</param>             </generator>         </id>         <one-to-one name="owner" constrained="true"/>         <union-subclass name="ConcreteProperty">             <property name="concreteProperty"/>         </union-subclass>         <union-subclass name="AnotherProperty">             <property name="anotherProperty"/>         </union-subclass>     </class> </hibernate-mapping> 

How can I enforce the creation of a foreign key from AbstractProperty.ownerId to Owner.ownerId without this Owner field in my AbstractProperty?

like image 214
drvdijk Avatar asked Jul 30 '13 14:07

drvdijk


People also ask

How many foreign keys we can create in a single table?

A table with a foreign key reference to itself is still limited to 253 foreign key references. Greater than 253 foreign key references are not currently available for columnstore indexes, memory-optimized tables, Stretch Database, or partitioned foreign key tables.

Can a single table have foreign key?

There is no problem having a table that consists of foreign keys only. In your particular example it would be OK to remove the OrderID. Relational theory states that each table should have a candidate key so, ideally, the business rule you mention would be in place to make the foreign key only table a "good" table.

Does each table need a foreign key?

Note that foreign keys are not mandatory, and a table may have no foreign keys. Conversely, every column in a table may have a foreign key constraint.

Can you have two foreign keys to the same table?

A table can have multiple foreign keys based on the requirement.


1 Answers

Simple answer: Never let Hibernate create the schema for real applications.

Hibernate is an object relational mapper and one should treat it as this.

That Hibernate additionally creates schemas is at most kind for the first time. But in environments after the first release you don't want to have Hibernate control over the schema. After all you have to handle SQL to have migrations scripts (manually or tool support). After the first release you will have data in the database. To ensure data migration on the production system with less problems you should consider schema and data migration the same way in the production environment as you do in your development environment.

Exceptions of that can be any application that has rarely changing data that may be reconstructable fast on data loss.

like image 199
oopexpert Avatar answered Oct 07 '22 17:10

oopexpert