Composition vs. Inheritance with JPA and Hibernate
Articles Blog

Composition vs. Inheritance with JPA and Hibernate

October 22, 2019


Hi, I’m Thorben Janssen from thoughts-on-java.org. In today’s video I will compare Composition and inheritance foe JPA entities Like all object-oriented programing languages, Java supports the fundamental concepts of inheritance and composition. There is an important difference between both concepts. Inheritance enables you to model an is-a association between two classes by extending a superclass. Composition models a has-a association by referencing another class in an instance variable. You can use both concepts with JPA and Hibernate. But when should you use which one? and what is the best way to do that? For plain Java classes, there have been hundreds of discussions about this question. And there is a clear winner. In most cases, you should prefer composition
when you design plain Java classes. In his book Effective Java Joshua Bloch describes 2 circumstances in which it’s OK to use inheritance: “It is safe to use inheritance within a package, where the subclass and the superclass implementations are under the control of the same programmers. It is also safe to use inheritancewhen extending classes were specifically designed and documented for extension. In my experience, most classes in most projects were created to solve a specific task but nobody thought about extending them in the future. So, they are not designed for it and you shouldn’t extend them. If you do it anyways, you will most likely experience unexpected side-effects and implementation lock-ins in future releases. But all these discussions and recommendations are for plain Java classes. Is this also valid for entity classes annotated with JPA annotations? and mapped to tables in a relational database? And how should you implement the mapping? The general recommendation to use composition over inheritance is also valid for entity classes. You can apply the same arguments that Joshua Bloch used for plain Java classes to your entities. But these are not the only reasons. When you are working with entities, you always need to keep in mind that your classes will be mapped to database tables. Relational databases don’t support the inheritance concept. You have to use one of JPA’s inheritance strategies to map your inheritance hierarchy to one or more database tables. When you choose one of these strategies, you need to decide: if you want to forgo constraints that ensure data consistency so that you get the best performance, or if you accept inferior performance so that you can use the constraints. As you can see, both approaches have their disadvantages. You don’t run into these problems if you use composition. JPA and Hibernate support 2 basic ways to implement composition: You can reference another entity in your composition by modeling an association to it. Each entity will be mapped to its database table and can be loaded independently. A typical example is a Person entity which has a one-to-many association to an Address entity. Or you can also use an embeddable to include its attributes and their mapping information into your entity mapping. The attributes are mapped to the same table as the other attributes of the entity. The embeddable can’t exist on its own and has no persistent identity. You can use it to define a composition of address attributes which become part of the Person entity. For a lot of developers, associations are the most natural way to use composition in entity mappings. It uses concepts that are
well-established and easy to use in both worlds: the database, and the Java application. Associations between database records are very common and easy to model. The most common ones are one-to-many and many-to-many associations. To model a one-to-many association, you store the primary key of the associated record in one of the fields of the database record that represents the many-side of the association. A typical example is a record in the Book table which contains the primary key of a record in the Publisher table. This enables you to store a reference to the publisher who published the book. If you want to model a many-to-many relationship, you need to introduce an association table. Each record in this table stores the primary key of the associated record. For example, a BookAuthor table stores the primary key records in the Author and Book tables to persist which authors wrote a specific book. One of the main benefits of JPA and Hibernate is that you can easily map these associations in your entities. You just need an attribute of the type of the associated entity or a collection of the associated entities and a few annotations. I explained these mappings in great details in my article Ultimate Guide to Association Mappings with JPA and Hibernate. I will add the link to it to the video description. In this video, I will just show you a quick example, and you can take a look at that post if you want to dive deeper. This code shows the mapping of a many-to-many association between the Book and the Author entity. In this example, the Book entity owns the association and specifies the join table with its foreign key columns. As you can see, the mapping is relatively simple. You just need an attribute of type Set Author, a ManyToMany annotation which specifies the type of the relationship and a JoinTable annotation to define the association table. Modelling the other end of the association is even simpler. The books attribute with its ManyToMany annotation just references the association mapping defined on the Book entity. You can use a similar approach to model one-to-one, one-to-many, and many-to-one associations. Embeddables are another option to use composition when implementing your entities. They enable you to define a reusable set of attributes with mapping annotations. In contrast to the previously discussed association mappings, the embeddable becomes part of the entity and has no persistent identity on its own. Let’s take a look at an example. The 3 attributes of the Address class store simple address information. The Embeddable annotation tells Hibernate and any other JPA implementation that this class and its mapping annotations can be embedded into an entity. In this example, I rely on JPA’s default mappings and don’t provide any mapping information. After you have defined your embeddable, you can use it as the type of an entity attribute. You just need to annotate it with Embedded, and your persistence provider will include the attributes and mapping information of your embeddable in the entity. So, in this example, the attributes street, city and postalCode of the embeddable Address will be mapped to columns of the Author table. If you want to use multiple attributes of the same embeddable type, you need to override the column mappings of the attributes of the embeddable. You can do that with a collection of AttributeOverride annotations. Since JPA 2.2, the AttributeOverride annotation is repeatable, and you no longer need to wrap it in an AttributeOverrides annotation. Lets sum it up, Relational table models don’t support inheritance. JPA offers different strategies to map your inheritance hierarchy to one or more database tables. If you use one of these strategies, you need to decide if you want to ensure data consistency or if you want to get the best performance. Unfortunately, you can’t have both if you use inheritance. You don’t need any of these mappings strategies and you don’t need to choose between consistency and performance if you use composition. You should, therefore, prefer composition over inheritance, when you design your entity model. JPA and Hibernate offer 2 options to map your composed entities to database tables. You can use an embeddable to define a reusable set of attributes and mapping information, which become part of your entity. The embeddable can’t exist on its own and Hibernate maps its attributes to the same database table as it maps the entity. You can also use other entities in your composition. You then need to model an association between the two entities and Hibernate will persist each of them to its own database table. OK, that’s it for today. If you want to learn more about Hibernate, you should join the free Thoughts on Java Library. It gives you free access to a lot of member-only content like a cheat for this video and an ebook about using native queries with JPA and Hibernate. I’ll add the link to it to the video description below. And if you like today’s video, please give it a thumbs up and subscribe below. Bye

Leave a Reply

Your email address will not be published. Required fields are marked *