Implementing Object-Relational Mapping
1. Implementing Entity Mappings
Example: JPA entity
@Entity
@Table(name = "orders")
public class Order {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false) private String status;
@Column(name = "placed_at", nullable = false) private Instant placedAt;
}
2. Implementing Relationships
| Relationship | Annotation |
|---|---|
| 1:1 | @OneToOne |
| 1:N | @OneToMany (mappedBy on owning side) |
| N:1 | @ManyToOne (owns FK) |
| M:N | @ManyToMany + @JoinTable |
3. Implementing Fetch Strategies
| Type | Default | Recommendation |
|---|---|---|
| @ManyToOne | EAGER | Set LAZY explicitly |
| @OneToOne | EAGER | LAZY |
| @OneToMany | LAZY | Keep LAZY |
| @ManyToMany | LAZY | Keep LAZY |
Note: Use JPQL
JOIN FETCH or entity graphs to avoid N+1 selects.4. Implementing Cascade Operations
| Cascade | Effect |
|---|---|
| PERSIST | Save children with parent |
| MERGE | Update children |
| REMOVE | Delete children with parent |
| DETACH/REFRESH | Propagate to children |
| ALL | Everything |
| orphanRemoval=true | Delete orphaned children |
5. Implementing Inheritance Strategies
| Strategy | Tables | Trade-off |
|---|---|---|
| SINGLE_TABLE | One per hierarchy | Fast; sparse columns |
| JOINED | One per class + join | Normalized; slower reads |
| TABLE_PER_CLASS | One per concrete class | No FK from base |
6. Implementing Embedded Objects
Example: Embeddable value object
@Embeddable
public class Address {
private String street; private String city; private String zip;
}
@Entity
public class Customer {
@Embedded
@AttributeOverride(name="city", column=@Column(name="billing_city"))
private Address billing;
}
7. Implementing Entity Listeners
| Callback | Trigger |
|---|---|
@PrePersist | Before insert |
@PostPersist | After insert |
@PreUpdate | Before update |
@PostUpdate | After update |
@PreRemove/@PostRemove | Delete |
@PostLoad | After fetch |
8. Implementing Named Queries
Example: Named JPQL
@NamedQuery(name = "Order.findOpen",
query = "select o from Order o where o.status = 'OPEN'")
@Entity
public class Order { ... }
em.createNamedQuery("Order.findOpen", Order.class).getResultList();
9. Implementing Custom Type Converters
Example: AttributeConverter
@Converter(autoApply = true)
public class MoneyConverter implements AttributeConverter<Money, Long> {
public Long convertToDatabaseColumn(Money m) { return m == null ? null : m.cents(); }
public Money convertToEntityAttribute(Long c) { return c == null ? null : Money.usd(c); }
}
10. Implementing ID Generation Strategies
| Strategy | Trade-off |
|---|---|
| IDENTITY | Simple; defeats batch insert |
| SEQUENCE | Best for batch; PG/Oracle |
| TABLE | Portable; slower |
| UUID | Distributed-friendly |
| Application-assigned | Domain controls; ULID/UUIDv7 |
11. Implementing Composite Primary Keys
Example: @EmbeddedId
@Embeddable
public record OrderLineId(Long orderId, int lineNo) implements Serializable {}
@Entity
public class OrderLine {
@EmbeddedId private OrderLineId id;
}