Dave
Dave

Reputation: 21924

Hibernate best approach for one Java class and multiple tables?

Put another way: How do you model/map a heavily reused child class/table to many different parent entities?

I have several entity types each being persisted into its own table:

class A --> table A class B --> table B ....

Now I need to make each of these classes the parent of a 1:M unidirectional child collection. The collection is a history of approvals the entity has gained over time. The Child domain class is called "ApprovalItem". The Approval class is exactly the same for all types of parents.

What is the best way to map this? If I create a single table to hold all ApprovalItems, then I can't enforce a FK relation to the PK of the entity and/or I am left with a bad database design.

On the other hand, I could create an ApprovalIems table for each entity type (e.g. A_ApprovalItems, B_ApprovalItems, etc.). This seems like a good schema on the database side, but then it seems I need to create a separate domain classes in Java for each entity approval (e.g. AAprrovalItem class, BApprovalItem class, etc.). This seems like a lot of hassle and complexity to create so many new classes in Java that do nothing other than allow me to put in different JPA mapping annotations.

Is there a mapping technique in Hibernate that will allow me to have one class in Java map to several different tables depending on who the parent owner of the collection is?

Upvotes: 4

Views: 5693

Answers (2)

Arthur Ronald
Arthur Ronald

Reputation: 33783

I could create an ApprovalItem table for each entity type (e.g. A_ApprovalItem, B_ApprovalItem, etc.). This seems like a good schema on the database side

But

It seems i need to create a separate domain classes in Java for each entity approval (e.g. AAprrovalItem class, BApprovalItem class, etc.).

You do not need it. you can create a single ApprovalItem class and create a @OneToMany relationship between your parent classes and your ApprovalItem. Hibernate takes care to create a linked table for each relationship.

@Entity
public class ClassA {

    @Id
    @GeneratedValue 
    private Integer id;

    // Hibernate will create CLASSA_APPROVALITEM to link both class
    @OneToMany
    private List<ApprovalItem> approvalItemList;

}

@Entity
public class ClassB {

    @Id
    @GeneratedValue 
    private Integer id;

    // Hibernate will create CLASSB_APPROVALITEM to link both class
    @OneToMany
    private List<ApprovalItem> approvalItemList;

}

And your ApprovalItem class

@Entity
public class ApprovalItem {

    @Id
    @GeneratedValue 
    private Integer id;

    // Nothing else

}

But Let's see what Java Persistence with Hibernate book talks about it

You may have shared references to the Bid objects. As suggested earlier, a User may have a collection of references to the Bid instances they made. You can’t delete an item and all its bids without removing these references first. You may get an exception if you try to commit this transaction, because a foreign key constraint may be violated.

So keep it in mind when dealing with shared references.

In order to see how the target schema looks like, you can use the following

AnnotationConfiguration configuration = new AnnotationConfiguration();

configuration
    .addAnnotatedClass(ClassA.class)
    .addAnnotatedClass(ClassB.class)
    .addAnnotatedClass(ApprovalItem.class)
    .setProperty(Environment.USER, <TYPE_YOUR_USER>)
    .setProperty(Environment.PASS, <TYPE_YOUR_PASSWORD>)
    .setProperty(Environment.URL, <TYPE_YOUR_URL>)
    .setProperty(Environment.DIALECT, <TYPE_YOUR_DIALECT>)
    .setProperty(Environment.DRIVER, <TYPE_YOUR_DRIVER>);

SchemaExport schema = new SchemaExport(configuration);
schema.setOutputFile("schema.sql");

schema.create(<DO_YOU_WANT_TO_PRINT_TO_THE_CONSOLE>, <DO_YOU_WANT_TO_EXPORT_THE_SCRIPT_TO_THE_DATABASE>);

It will generate a file called schema.sql, which contains your target schema

regards,

Upvotes: 3

Will Marcouiller
Will Marcouiller

Reputation: 24132

Chapter 8. Inheritance Mapping of Hibernate Documentation might help.

Otherwise, I see no problem having multiple ApprovalItem derived class that "do nothing", like you say, since it does differentiate the Approval, it's like having a type of approval. Seeing your model like so, I would recommend using multiple classes, even if they only inherit from your base ApprovalItem class.

Have I well understood your question or am I missing something else more subtle?

Upvotes: 2

Related Questions