Hibernate @AssociationOverride
for References Override in Subclass
@AssociationOverride
is pivotal when an entity inherits mappings from a superclass, but you need to tweak the association details in the subclass. Let's delve into its utility and implications through a practical example involving geometric figures and colors.
@AssociationOverride
annotation for References OverrideHi, this is Paul, and welcome to this article, we explore how to override REFERENCES
in the Hibernate entity in a subclass.
Introduction to the Scenario
Our example involves two geometric entities: Circle
and Square
, both inheriting from a Figure
superclass. Both shapes are associated with a color, but the foreign key column linking to the color differs in each subclass's table. Here's how our database schema looks:
- Colors Table: Holds color data.
- Circles Table: Represents circles, linked to colors.
- Squares Table: Represents squares, also linked to colors.
CREATE TABLE colors
(
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE circles
(
id BIGSERIAL PRIMARY KEY,
circle_color_id BIGINT,
radius DOUBLE PRECISION NOT NULL,
FOREIGN KEY (circle_color_id) REFERENCES colors (id)
);
CREATE TABLE squares
(
id BIGSERIAL PRIMARY KEY,
square_color_id BIGINT,
side_length DOUBLE PRECISION NOT NULL,
FOREIGN KEY (square_color_id) REFERENCES colors (id)
);
MappedSuperclass: Setting the Stage
Figure
is annotated as a @MappedSuperclass
, meaning it provides mapping information to its subclasses but is not an entity itself.
This approach is useful when you want common mappings (like id
and color
) but do not need a table for the superclass.
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@MappedSuperclass
public abstract class Figure {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "color_id")
protected Color color;
}
@AssociationOverride: Customizing Mappings
The subclasses Circle
and Square
override the color
association using @AssociationOverride
. This is crucial because while they inherit the color
mapping from Figure
, the actual foreign key column in their respective tables is different (circle_color_id
for Circle
and square_color_id
for Square
).
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@DiscriminatorValue("Square")
@AssociationOverride(
name="color",
joinColumns=@JoinColumn(name="square_color_id")
)
@Table(name = "squares")
public class Square extends Figure {
@Column(name = "side_length")
private double sideLength;
}
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@DiscriminatorValue("Circle")
@AssociationOverride(
name="color",
joinColumns=@JoinColumn(name="circle_color_id")
)
@Table(name = "circles")
public class Circle extends Figure {
@Column(name = "radius")
private double radius;
}
How @AssociationOverride Works
@AssociationOverride
allows you to redefine how an inherited association is mapped in a subclass. In our case, although both subclasses inherit the color
field from Figure
, each needs it linked to a different column. Without this override, Hibernate would look for a color_id
column by default, as specified in the Figure
class.
Conclusion
@AssociationOverride
is a testament to Hibernate's flexibility in handling complex inheritance structures. By mastering this annotation, developers can ensure their data access layer is both robust and aligned with the nuanced requirements of their domain model. Understanding and leveraging such annotations enhances the maintainability and scalability of applications, allowing them to evolve gracefully alongside business needs.
Thank you for reading until the end. Before you go:
- Please consider clapping and following the writer! 👏
- Follow us on Twitter(X), LinkedIn