{"id":635,"date":"2022-12-03T04:13:41","date_gmt":"2022-12-03T04:13:41","guid":{"rendered":"https:\/\/www.canosielabs.com\/blog\/?p=635"},"modified":"2022-12-03T04:17:29","modified_gmt":"2022-12-03T04:17:29","slug":"jpa-with-hibernate-relationship-mapping-using-annotations","status":"publish","type":"post","link":"https:\/\/www.canosielabs.com\/blog\/jpa-with-hibernate-relationship-mapping-using-annotations\/","title":{"rendered":"JPA with Hibernate &#8211; Relationship Mapping using Annotations"},"content":{"rendered":"<div class=\"boldgrid-section\">\n<div class=\"container\">\n<div class=\"row\">\n<div class=\"col-lg-12 col-md-12 col-xs-12 col-sm-12\">\n<div style=\"border-width: 0px\" class=\"\">\n<p class=\"\">In this guide, I&#8217;ll show you how to create all of the common relationship mappings available using the <strong>JPA specification<\/strong>.&nbsp; In my examples, <strong>Hibernate<\/strong> is used as the underlying <strong>implementation<\/strong>.&nbsp; This isn&#8217;t a full tutorial, but instead, this guide can be used as a quick cheat sheet when required to setup future implementations so I keep it updated or add to it as required.&nbsp; In this guide, we&#8217;ll be using only annotation based configurations.&nbsp;<\/p>\n<p class=\"\">This is not a exhaustive list of all possible configurations of the four basic relationships possible but rather a explanation of the common setups.&nbsp; In particular, within each type of relationship, the exact configuration used often depends on the specifics of the use case &#8211; in particular, who should be the <strong>relationship owner<\/strong>.&nbsp; Concepts we will be covering(in summary) are relationship owner, unidirectional and bidirectional relationships and the 4 basic mapping types.<\/p>\n<p class=\"\">We&#8217;ll also present some use cases that, while possible, are not recommended due to various inconsistencies that may crop up.&nbsp; These are discussed for completeness.<\/p>\n<h3 class=\"\">Note:<\/h3>\n<ul class=\"\">\n<li>Getters and setters have been omitted for verbosity.<\/li>\n<li>As primary key column names are used in JPA configurations, to prevent confusing stemming from the proliferation of <strong>&#8220;ID&#8221;<\/strong> or <strong>&lt;TABLE_NAME&gt;_ID<\/strong> column names being used everywhere, foreign key column names have been named <strong>&#8220;&lt;TABLE NAME&gt;_ID_FK&#8221;<\/strong> (instead of just <strong>&lt;TABLE_NAME_ID&gt; <\/strong>or<strong> &#8220;ID&#8221;<\/strong>) to distinguish themselves from the actual table primary key column.<\/li>\n<li><strong>Casecase<\/strong> configurations have been omitted to simplify the code.<\/li>\n<\/ul>\n<h1 class=\"\">Introduction<\/h1>\n<p class=\"\">There are <strong>four basic<\/strong> relationships outlined in the JPA specification.<\/p>\n<ol class=\"\">\n<li>One to one<\/li>\n<li>One to many<\/li>\n<li>Many to one<\/li>\n<li>Many to many<\/li>\n<\/ol>\n<h1 class=\"\">One to One<\/h1>\n<p class=\"\">The one to one relationship is used when one entity is at most associated with one other entity.&nbsp; Since it is one to one, the foreign key can linking the two entities can be on:<\/p>\n<ul class=\"\">\n<li>On either side of the relationship.<\/li>\n<li>Using a third join table.<\/li>\n<\/ul>\n<p class=\"\">Thus, lets use an example <strong>Car<\/strong> and <strong>Engine<\/strong>.&nbsp; A <strong>CAR<\/strong> has one <strong>ENGINE<\/strong> and a <strong>ENGINE<\/strong> is part of one <strong>CAR.<\/strong><\/p>\n<h3 class=\"\">1. Foreign key car_id is on the Engine table.<\/h3>\n<div>\n<p class=\"mod-reset\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full aligncenter\" src=\"https:\/\/canosielabs.com\/img\/articles\/hibernate\/one-to-one-child-side.png\" width=\"405\" height=\"141\"><\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"car\")\r\npublic class Car {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long car_id;\r\n\r\n    @OneToOne(mappedBy = \"car\")\r\n    private Engine engine;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"engine\")\r\npublic class Engine {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n\tprivate long engine_id;\r\n\r\n    @OneToOne\r\n    @JoinColumn(name=\"car_id_fk\")\r\n\tprivate Car car;\r\n}\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"boldgrid-section\">\n<div class=\"container\">\n<div class=\"row\" style=\"padding-bottom: 0px\">\n<div class=\"col-lg-12 col-md-12 col-xs-12 col-sm-12\">\n<p class=\"\">This is a <strong>bidirectional<\/strong> relationship with the <strong>Engine<\/strong> being the <strong>owner<\/strong> of the relationship.&nbsp;&nbsp;<\/p>\n<p class=\"\">In the Car entity:<\/p>\n<ul class=\"\">\n<li>We are using the <strong>mappedBy<\/strong> attribute in the <strong>@OneToOne<\/strong> annotation.&nbsp; &nbsp;We are telling Hibernate that the mapping between <strong>Car<\/strong> and <strong>Engine<\/strong> is found on the <strong>Engine<\/strong>(<strong>owner<\/strong>) side.<\/li>\n<\/ul>\n<p class=\"\">In the Engine (owner) entity:<\/p>\n<ul class=\"\">\n<li>In addition to using the <strong>@OneToOne<\/strong> annotation to denote the relationship, since the <strong>ENGINE<\/strong> table contains the foreign key, it must use the <strong>@JoinColumn<\/strong> to denote the mapping to the <strong>Car<\/strong> entity.&nbsp; &nbsp;<\/li>\n<\/ul>\n<p class=\"\">In this example, it is possible to create a <strong>unidirectional<\/strong> relationship from <strong>Engine<\/strong> to <strong>Car<\/strong>, by omitting the <strong>Engine<\/strong> member in <strong>Car<\/strong> (and associated JPA annotations).&nbsp; It is not possible to create a <strong>unidirectional<\/strong> relationship from <strong>Car<\/strong> to <strong>Engine<\/strong> (in any standard form).&nbsp; &nbsp;I.e. The <strong>mappedBy<\/strong> attribute requires a bidirectional reference&nbsp; (<strong>Engine<\/strong> to <strong>Car<\/strong>), a member of type Car in Engine to complete the mapping&nbsp; and the <strong>@JoinColumn<\/strong> annotation cannot be used since the foreign key is on the <strong>ENGINE<\/strong> table &#8211; not <strong>CAR<\/strong>.<\/p>\n<h3 class=\"\">2. Foreign key engine_id is on the Car table.<\/h3>\n<p class=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full aligncenter\" src=\"https:\/\/canosielabs.com\/img\/articles\/hibernate\/one-to-one-parent-side.png\" width=\"405\" height=\"141\"><\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"car\")\r\npublic class Car {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long car_id;\r\n\r\n    @OneToOne\r\n    @JoinColumn(name=\"engine_id_fk\")\r\n    private Engine engine;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"engine\")\r\npublic class Engine {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n\tprivate long engine_id;\r\n\r\n    \/\/ to create a bidirectional mapping\r\n    @OneToOne(mappedBy = \"engine\")\r\n    private Car car;\t\r\n}\r\n<\/code><\/pre>\n<p class=\"\">The Car entity:<\/p>\n<ol class=\"\">\n<li>Denotes the one-to-one relation via the <strong>@OneToOne<\/strong> annotation.<\/li>\n<li>Is the <strong>owner<\/strong> of the relationship<\/li>\n<li>Uses the <strong>@JoinColumn<\/strong> to denote the existence of the foreign column in the CAR table which will be used to perform the join.&nbsp;<\/li>\n<\/ol>\n<p class=\"\">In the Engine entity, the <strong>mappedBy<\/strong> attribute is used to let Hibernate know the owner of the mapping is controlled by the <strong>engine<\/strong> property in <strong>Car<\/strong>.<\/p>\n<h3 class=\"\">3. A mapping table car_engine is used<\/h3>\n<p class=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full aligncenter\" src=\"https:\/\/canosielabs.com\/img\/articles\/hibernate\/one-to-one-mapping-table.png\" width=\"699\" height=\"141\"><\/p>\n<p class=\"\">First, we&#8217;ll decide on a owning side, <strong>Car<\/strong> in this case.<\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"car\")\r\npublic class Car {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long car_id;\r\n\r\n\t@OneToOne\r\n    @JoinTable(\r\n            name = \"car_engine\", \r\n            joinColumns = { @JoinColumn(name = \"car_id_fk\") }, \r\n            inverseJoinColumns = { @JoinColumn(name = \"engine_id_fk\") }\r\n        )    \r\n\tprivate Engine engine;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"engine\")\r\npublic class Engine {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n\tprivate long engine_id;\r\n\r\n    @OneToOne(mappedBy=\"engine\")\r\n    private Car car;\t\r\n}\r\n<\/code><\/pre>\n<p class=\"\">The Car entity:<\/p>\n<ol class=\"\">\n<li>Denotes the one-to-one relation via the <strong>@OneToOne<\/strong> annotation.<\/li>\n<li>Is the <strong>owner<\/strong> of the relationship<\/li>\n<li>Uses the <strong>@JoinTable <\/strong>with a name attribute to specify the join table name in the database.\n<ol class=\"\">\n<li>The <strong>joinColumns<\/strong> attribute is used to identify the foreign key for this entity (<strong>Car<\/strong>)<\/li>\n<li>The <strong>inverseJoinColumn<\/strong> is used to identify the foreign key for the other entity (<strong>Engine<\/strong>).<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p class=\"\">In the Engine entity, the <strong>mappedBy<\/strong> attribute is used to let Hibernate know the owner of the mapping is controlled by the <strong>engine<\/strong> property in <strong>Car<\/strong>.&nbsp; When creating a new Engine instance, it can be assigned to the Car via the setter method on the Car&#8217;s side. See example below:<\/p>\n<pre class=\"\"><code class=\"language-java\">Car honda = carDao.findById((long) 1).get(); ID=1\r\nEngine e1 = engineDao.findById(1l).get();  \/\/ ID=1\r\n\r\nhonda.setEngine(e1)\r\ncarDao.save(honda);  \t\t\r\n<\/code><\/pre>\n<p class=\"\">It is possible to define both sides as owners.<\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"car\")\r\npublic class Car {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long car_id;\r\n\r\n\t@OneToOne\r\n    @JoinTable(\r\n            name = \"car_engine\", \r\n            joinColumns = { @JoinColumn(name = \"car_id_fk\") }, \r\n            inverseJoinColumns = { @JoinColumn(name = \"engine_id_fk\") }\r\n        )    \r\n\tprivate Engine engine;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"engine\")\r\npublic class Engine {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n\tprivate long engine_id;\r\n\r\n    \/\/ to create a bidirectional mapping\r\n\t@OneToOne\r\n    @JoinTable(\r\n            name = \"car_engine\", \r\n            joinColumns = { @JoinColumn(name = \"engine_id_fk\") }, \r\n            inverseJoinColumns = { @JoinColumn(name = \"car_id_fk\") }\r\n    )   \r\n    private Car car;\t\r\n}\r\n<\/code><\/pre>\n<p class=\"\">&nbsp;<\/p>\n<h1 class=\"\">One to Many and Many to One<\/h1>\n<p class=\"\">Many one-to-many relationships often form a parent-child relationship.&nbsp; Unlike the one-to-one mapping (above), a one-to-many mapping cannot be mapped via a foreign key on the parent side.&nbsp; It can only be mapped via:<\/p>\n<ol class=\"\">\n<li>The foreign key on the child side (usually the case)<\/li>\n<li>The use of a mapping table.&nbsp;<\/li>\n<\/ol>\n<p class=\"\">In this relationship, the <strong>owning<\/strong> side is usually the &#8220;many&#8221; side.&nbsp; &nbsp;In this example, we&#8217;ll use two entities <strong>Car<\/strong> (as above) but introduce another entity called <strong>Wheel<\/strong>.&nbsp; A car has 0 or more wheels and each wheel is associated to only one wheel.&nbsp;<\/p>\n<h3 class=\"\">1. Foreign key CAR_ID is on the WHEEL table.<\/h3>\n<p class=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full aligncenter\" src=\"https:\/\/canosielabs.com\/img\/articles\/hibernate\/one-to-many-child.png\" width=\"405\" height=\"141\"><\/p>\n<p class=\"\">For a <strong>unidirectional<\/strong> Car to Wheel mapping, we need to specify the foreign key column on the <strong>WHEEL<\/strong> table using the <strong>@JoinColumn<\/strong> annotation.<\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"car\")\r\npublic class Car {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long car_id;\r\n\r\n\t@OneToMany\r\n\t@JoinColumn(name = \"car_id_fk\")\r\n\tprivate Set wheels;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"wheel\")\r\npublic class Wheel {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n\tprivate long engine_id;\r\n}\r\n<\/code><\/pre>\n<p>On the Car entity:<\/p>\n<ol class=\"\">\n<li>The <strong>@OneToMany<\/strong> annotation indicates the relationship type.<\/li>\n<li>The <strong>@JoinColumn<\/strong> annotation is interesting.&nbsp; When used with a <strong>@OneToMany<\/strong>, it indicates to Hibernate that this entity is the owner of the relationship and will set the foreign key on the other side.<\/li>\n<\/ol>\n<p class=\"\">For a <strong>bidirectional<\/strong> mapping, we need to choose the owning side.&nbsp; In the standard use case, the many side, <strong>Wheel<\/strong>, is the owner.&nbsp; See below:<\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"car\")\r\npublic class Car {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long car_id;\r\n\r\n\t@OneToMany( mappedBy = \"car\")\r\n\tprivate Set wheels;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"wheel\")\r\npublic class Wheel {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long engine_id;\r\n\r\n    @ManyToOne\r\n    @JoinColumn(name=\"car_id_fk\")\r\n    private Car car;\r\n}\r\n<\/code><\/pre>\n<p class=\"\">On the Car entity:<\/p>\n<ol class=\"\">\n<li>we can replace the annotations used in <strong>Car<\/strong> with the <strong>mappedBy<\/strong> attribute, to tell Hibernate that the relationship is tracked on the <strong>Wheel <\/strong>side (no need to create a third mapping table).&nbsp; In this situation, we can remove the <strong>@JoinColumn<\/strong> annotation used above as the <strong>@ManyToOne<\/strong> and <strong>@JoinColumn<\/strong> provides Hibernate the necessary information to perform the mapping.&nbsp;<\/li>\n<li>This can be omitted if you only want a <strong>unidirectional Wheel<\/strong> to <strong>Car<\/strong> mapping.<\/li>\n<\/ol>\n<p class=\"\">On the Wheel Entity:<\/p>\n<ol class=\"\">\n<li>Using the <strong>@ManyToOne<\/strong> annotation on <strong>Wheel<\/strong> indicates that Wheel is the owner.&nbsp;&nbsp;<\/li>\n<\/ol>\n<p class=\"\">For completeness, it is possible to have a bidirectional relationship where the <strong>Car<\/strong> is the owner.<\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"car\")\r\npublic class Car {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long car_id;\r\n\r\n\t@OneToMany(cascade = {CascadeType.ALL})\r\n\t@JoinColumn(name = \"cart_id_fk\")\r\n\tprivate Set wheels;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"wheel\")\r\npublic class Wheel {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long engine_id;\r\n\r\n    @ManyToOne\r\n    @JoinColumn(name=\"car_id_fk\")\r\n    private Car car;\r\n}\r\n<\/code><\/pre>\n<p class=\"\">In the Car entity:<\/p>\n<ol class=\"\">\n<li>The mapped by attribute in the <strong>@OneToMany<\/strong> annotation has been replaced by the<strong> @JoinColumn<\/strong> annotation.<\/li>\n<\/ol>\n<p class=\"\">In the Wheel entity:<\/p>\n<ol class=\"\">\n<li>Nothing has changed from before.<\/li>\n<\/ol>\n<p class=\"\">While this setup does allow for the setting of the foreign key on Item from both sides of the relationship, unwanted inconsistencies can arise.&nbsp; Consider the case where a new Wheel is added to a Honda&#8217;s collection but the Wheel&#8217;s own reference to Car is set to a Toyota.&nbsp; What happens?<\/p>\n<pre class=\"\"><code class=\"language-java\">Car honda = carDao.findById(1l).get();\r\nCar toyota = carDao.findById(2l).get();\r\n\r\nWheel wheel = new Wheel();\r\n\/\/ set other properties of a wheel \r\n    \r\nhonda.getWheels().add(wheel);\r\nwheel.setCar(toyota);\r\n\t\t\r\nwheelDao.save(wheel);\r\ncarDao.save(honda);  \t\t\r\n<\/code><\/pre>\n<p class=\"\">&nbsp;Well, unlike the example above where the <strong>Wheel<\/strong> was defined as the <strong>owner<\/strong>, in this new example, the <strong>Car<\/strong> side takes precedence.<\/p>\n<h3 class=\"\">2. A mapping table car_engine is used<\/h3>\n<p class=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full aligncenter\" src=\"https:\/\/canosielabs.com\/img\/articles\/hibernate\/one-to-many-mapping-table.png\" width=\"699\" height=\"141\"><\/p>\n<p class=\"\">This is the same table structure used in number 3 of the one-to-one mapping.&nbsp; It can also be used for a one-to-many or even a many-to-many mapping.&nbsp; &nbsp;As expected, we have to use the <strong>@JoinTable<\/strong> annotation specifying the join table and join columns.&nbsp; These can be avoid if the table and column names are default names expected by Hibernate.<\/p>\n<p class=\"\">For the bidirectional setup, we first choose a owning side.&nbsp; In our example, <strong>Wheel<\/strong> will be the owning side.<\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"car\")\r\npublic class Car {\r\n\r\n   @Id\r\n   @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n   private long car_id;\r\n\r\n   @OneToMany (mappedBy=\"car\")\r\n   private Set wheels;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"wheel\")\r\npublic class Wheel {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long engine_id;\r\n\r\n    @ManyToOne\r\n    @JoinTable(\r\n            name = \"car_wheel\", \r\n            joinColumns = { @JoinColumn(name = \"wheel_id_fk\") }, \r\n            inverseJoinColumns = { @JoinColumn(name = \"car_id_fk\") }\r\n   )  \r\n   private Car car;\r\n}\r\n<\/code><\/pre>\n<p class=\"\">In this example, the <strong>Car<\/strong> entity uses the <strong>mappedBy<\/strong> attribute to tell Hibernate that the owning side(<strong>Wheel<\/strong>) is tracked on the <strong>car<\/strong> member of the <strong>Wheel<\/strong> entity.<\/p>\n<p class=\"\">The Wheel entity:<\/p>\n<ol class=\"\">\n<li>Denotes the many-to-one relation via the <strong>@ManyToOne<\/strong> annotation.&nbsp; Remember, this is the inverse of a One-to-Many relationship.<\/li>\n<li>Is the <strong>owner<\/strong> of the relationship<\/li>\n<li>Uses the <strong>@JoinTable <\/strong>with a name attribute to specify the join table name in the database.\n<ol class=\"\">\n<li>The <strong>joinColumns<\/strong> attribute is used to identify the foreign key for this entity (<strong>Wheel<\/strong>)<\/li>\n<li>The <strong>inverseJoinColumn<\/strong> is used to identify the foreign key for the other entity (<strong>Car<\/strong>).<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p class=\"\">This is a <strong>bidirectional<\/strong> setup, but we can make it one <strong>unidirectional<\/strong> from <strong>Wheel<\/strong> to <strong>Car<\/strong> by removing the <strong>Wheel<\/strong> member in <strong>Car<\/strong>.&nbsp; In this setup, because we are using the <strong>mappedBy<\/strong> attribute, we cannot make it <strong>unidirectional<\/strong> <strong>Car<\/strong> to <strong>Wheel<\/strong> by deleting the annotations in <strong>Wheel<\/strong>.&nbsp; To see how to create a <strong>unidirectional<\/strong> <strong>Car<\/strong> to <strong>Wheel<\/strong> setup, see below:<\/p>\n<p class=\"\">A <strong>bidirectional<\/strong> setup with both sides being a owning is shown below but a unidirectional <strong>Car<\/strong> to <strong>Wheel<\/strong> or vice versa simply be removing their corresponding member in the entity and mapping annotations.&nbsp;&nbsp;<\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"car\")\r\npublic class Car {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long car_id;\r\n\r\n\t@OneToMany\r\n    @JoinTable(\r\n            name = \"cart_box\", \r\n            joinColumns = { @JoinColumn(name = \"cart_id_fk\") }, \r\n            inverseJoinColumns = { @JoinColumn(name = \"box_id_fk\") }\r\n        )    \r\n     \r\n   private Set wheels;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"wheel\")\r\npublic class Wheel {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long engine_id;\r\n\r\n    @ManyToOne\r\n    @JoinTable(\r\n            name = \"car_wheel\", \r\n            joinColumns = { @JoinColumn(name = \"wheel_id_fk\") }, \r\n            inverseJoinColumns = { @JoinColumn(name = \"car_id_fk\") }\r\n   )  \r\n   private Car car;\r\n}\r\n<\/code><\/pre>\n<p class=\"\">This is a <strong>bidirectional<\/strong> relationship with two owners defined.&nbsp; It&#8217;s important to understand the inconsistency that may happen if a <strong>Wheel<\/strong> is both added to one <strong>Car<\/strong> collection of wheels but it&#8217;s own <strong>Car<\/strong> member is set to <strong>another Car<\/strong>.<\/p>\n<pre class=\"\"><code class=\"language-java\">Car honda = carDao.findById(1l).get();  \/\/ ID=1\r\nCar toyota = carDao.findById(2l).get();  \/\/ ID=2\r\n\r\nWheel wheel1= wheelDao.findById((long) 1).get(); ID=1\r\n    \r\nhonda.getWheels().add(wheel1);\r\nwheel1.setCar(toyota);\r\n\t\t\r\nwheelDao.save(wheel1);\r\ncarDao.save(honda);  \t\t\r\n<\/code><\/pre>\n<p class=\"\">The Honda is assigned a Wheel via it&#8217;s Wheel collection but the Wheel&#8217;s Car is set to a Toyota.&nbsp; After saving both Car and Wheel, we get <strong>both<\/strong> mappings appearing in the database, which is wrong.<\/p>\n<p class=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full aligncenter\" src=\"https:\/\/canosielabs.com\/img\/articles\/hibernate\/one-to-many-mapping-data-both-owners.png\" width=\"729\" height=\"165\"><\/p>\n<h1 class=\"\">Many to Many<\/h1>\n<p class=\"\">Many-to-many relationships are &#8220;almost&#8221; always implemented with a third join table.&nbsp; In addition, when defining a many-to-many relationship, we need to define a <strong>owning<\/strong> <strong>side<\/strong> of the relationship.&nbsp; Either entity can be a owning side, but not at the same time.<\/p>\n<p class=\"\">For this example, we&#8217;ll introduce a Person entity. A person(or car owner) can own many cars and a car can have many owners.&nbsp; This defines our many-to-many relationship.<\/p>\n<p class=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full aligncenter\" src=\"https:\/\/canosielabs.com\/img\/articles\/hibernate\/many-to-many-mapping-table.png\" width=\"729\" height=\"141\"><\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"person\")\r\npublic class Person{\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long person_id;\r\n\r\n    @ManyToMany\r\n    @JoinTable(\r\n            name = \"person\", \r\n            joinColumns = { @JoinColumn(name = \"person_id_fk\") }, \r\n            inverseJoinColumns = { @JoinColumn(name = \"car_id_fk\") }\r\n   )   \r\n   private Set&lt;Car&gt; cars;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"car\")\r\npublic class Car {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long car_id;\r\n\r\n    @ManyToMany(mappedBy = \"cars\")\r\n    private Set&lt;Person&gt; people;\r\n}\r\n<\/code><\/pre>\n<p class=\"\">In the Person (owner) entity:<\/p>\n<ol class=\"\">\n<li>The <strong>@ManyToMany<\/strong> annotation denotes the type of relationship.<\/li>\n<li>The <strong>@JoinTable<\/strong> denotes the use of a join table and specifies the <strong>name<\/strong>.&nbsp;&nbsp;\n<ol class=\"\">\n<li>The <strong>joinColumns<\/strong> attribute specifies the foreign key column to this entity (Person).<\/li>\n<li>The <strong>inverseJoinColumn<\/strong> attribute specifies the foreign key column to the inverse side of the relationship (I.e. the primary key on <strong>CAR<\/strong>).<\/li>\n<\/ol>\n<\/li>\n<li>Even though we&#8217;re setting up a bidirectional mapping, we can create a unidirectional mapping from only Person to Car by omitting the collection of owners (Person) that a car has had.&nbsp;<\/li>\n<li>We cannot create a <strong>unidirectional<\/strong> mapping from Car to Person simply by removing Car&#8217;s car member since Person is the owner of the relationship and Hibernate depends on it when figuring out the &#8220;<strong>mappedBy<\/strong>&#8221; instruction.&nbsp; Instead, if we want a unidirectional Car to Person mapping, we need to make Person the relationship owner and &#8220;reverse&#8221; the annotations used above.&nbsp;&nbsp;<\/li>\n<\/ol>\n<p class=\"\">In the Car entity, we used the <strong>@ManyToMany<\/strong> annotation to denote the relationship type.&nbsp; &nbsp;The <strong>mappedBy<\/strong> attribute denotes that the people collection is mapped by the <strong>owner<\/strong> entity (<strong>Person<\/strong>).&nbsp; &nbsp;In other words, adding a Car instance to a Person&#8217;s cars will create the mapping regardless of instances may be present in the Car&#8217;s person collection.&nbsp; Consider the code snippet below:<\/p>\n<pre class=\"\"><code class=\"language-java\">Person joe = personDao.findById(1l).get();\r\nPerson peter = personDao.findById(2l).get();\r\n\r\nCar honda = carDao.findById((long) 1).get();\r\n    \r\njoe.getCars().add(honda);\r\nhonda.getPeople().add(peter);\r\n\t\t\r\npersonDao.save(joe);\r\npersonDao.save(peter);\r\ncarDao.save(honda);  \t\t\r\n<\/code><\/pre>\n<p class=\"\">This code is attempting to assign a the Honda(a Car instance) to a person.&nbsp; The code has a inconsistency in mapping as the Honda is being added to Joe&#8217;s list of cars but Peter is being added to his collection of Cars.&nbsp; Because Hibernate will use the owner&#8217;s mapping to save the relationship and Joe will own a Honda and not Peter.<\/p>\n<p class=\"\">As mentioned above, this reverse mapping is to support the <strong>bidirectional<\/strong> mapping.&nbsp; We can also perform a <strong>unidirectional<\/strong> mapping from <strong>Person<\/strong> to <strong>Car<\/strong> by removing the people member in the <strong>Car<\/strong> entity but we cannot remove the cars member in <strong>People<\/strong> as it is the owner of the relationship.<\/p>\n<p class=\"\">Because of the use of the join table, we can reverse the owner side.<\/p>\n<p class=\"\">Just to reiterate the mapping behavior, we can also have mapping a way which has two owners.&nbsp; This method is not recommended:<\/p>\n<pre class=\"\"><code class=\"language-java\">@Entity\r\n@Table(name = \"person\")\r\npublic class Person{\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long person_id;\r\n\r\n    @OneToMany\r\n    @JoinTable(\r\n            name = \"person\", \r\n            joinColumns = { @JoinColumn(name = \"person_id_fk\") }, \r\n            inverseJoinColumns = { @JoinColumn(name = \"car_id_fk\") }\r\n   )   \r\n   private Set&lt;Car&gt; cars;\r\n}\r\n\r\n\r\n@Entity\r\n@Table(name=\"car\")\r\npublic class Car {\r\n\r\n    @Id\r\n    @GeneratedValue(strategy=GenerationType.IDENTITY)\r\n    private long car_id;\r\n\r\n    @ManyToMany\r\n    @JoinTable(\r\n            name = \"person\", \r\n            joinColumns = { @JoinColumn(name = \"car_id_fk\") }, \r\n            inverseJoinColumns = { @JoinColumn(name = \"person_id_fk\") }\r\n   )   \r\n   private Set&lt;Person&gt; people;\r\n}\r\n<\/code><\/pre>\n<p class=\"\">It is important to know in this situation, since both relationships are &#8216;owners&#8217;, the following code:<\/p>\n<pre class=\"\"><code class=\"language-java\">Person joe = personDao.findById(1l).get();  \/\/ ID=1\r\nPerson peter = personDao.findById(2l).get();  \/\/ ID=2\r\n\r\nCar honda = carDao.findById((long) 1).get(); ID=1\r\n    \r\njoe.getCars().add(honda);\r\nhonda.getPeople().add(peter);\r\n\t\t\r\npersonDao.save(joe);\r\npersonDao.save(peter);\r\ncarDao.save(honda);  \t\t\r\n<\/code><\/pre>\n<p class=\"\">The result in the PERSON_CAR table will be:<\/p>\n<p class=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full aligncenter\" src=\"https:\/\/canosielabs.com\/img\/articles\/hibernate\/many-to-many-mapping-data-both-owners.png\" width=\"729\" height=\"165\"><\/p>\n<p class=\"\">Both people will be associated to the Honda, which is probably not what we want.&nbsp;<\/p>\n<h1 class=\"\">Conclusion<\/h1>\n<p class=\"\">This is only a rough outline how the basic relationship types and their configurations.&nbsp; It is important to know configurations will be dependent on the exact use case and other specifics.&nbsp; For example, the addition of <em><strong>nullable=false<\/strong><\/em> on a mapping annotation may cause a particular configuration to no longer persist.&nbsp;&nbsp;<\/p>\n<p class=\"\">&nbsp;<\/p>\n<p class=\"\">&nbsp;<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, I&#8217;ll show you how to create all of the common relationship mappings available using the JPA specification.&nbsp; In my examples, Hibernate is&hellip;<\/p>\n","protected":false},"author":3,"featured_media":667,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"bgseo_title":"","bgseo_description":"","bgseo_robots_index":"index","bgseo_robots_follow":"follow","footnotes":""},"categories":[11],"tags":[16,7,12,3,17,6],"class_list":["post-635","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-interview-coding-questions","tag-hibernate","tag-interview-prep","tag-interview-questions","tag-java","tag-jpa","tag-software-development"],"_links":{"self":[{"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/posts\/635","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/comments?post=635"}],"version-history":[{"count":10,"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/posts\/635\/revisions"}],"predecessor-version":[{"id":690,"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/posts\/635\/revisions\/690"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/media\/667"}],"wp:attachment":[{"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/media?parent=635"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/categories?post=635"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.canosielabs.com\/blog\/wp-json\/wp\/v2\/tags?post=635"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}