Stage 9: JDBC, JPA and Hibernate, lesson 3 of 6

Entity mapping and relationships

Intermediate3 min read@since 17Code runs on your Java 25
Explain it forThe essentials plus production detail and pitfalls.

Key mapping annotations:

  • @Entity and @Table(name = ...)
  • @Id with @GeneratedValue: prefer SEQUENCE on PostgreSQL, because IDENTITY disables JDBC insert batching
  • @Column(nullable = false, unique = true) and @Enumerated(EnumType.STRING)
  • @Embedded value objects, and @Version for optimistic locking

Relationships:

  • @ManyToOne: the side holding the foreign key, called the owning side.
  • @OneToMany(mappedBy = ...): the inverse side.
  • @OneToOne and @ManyToMany (usually better modelled as an explicit join entity).

Fetch defaults: @ManyToOne and @OneToOne are EAGER; collections are LAZY. Set fetch = LAZY on every @ManyToOne and fetch explicitly when you need the data.

Example

Java
@Entity
@Table(name = "course")
public class Course {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    @Column(nullable = false, length = 150)
    private String title;

    @Enumerated(EnumType.STRING)
    private Level level;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "author_id")
    private Author author;

    @OneToMany(mappedBy = "course", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Lesson> lessons = new ArrayList<>();

    @Version
    private int version;

    protected Course() {}                        // required by JPA

    public void addLesson(Lesson l) {            // keep both sides in sync
        lessons.add(l);
        l.setCourse(this);
    }
}

Common mistake

Calling course.getLessons().add(lesson) without lesson.setCourse(course). The foreign key stays null. Use helper methods that set both sides.

Under the hood

Only the owning side (the @ManyToOne, the side without mappedBy) is used to write the foreign key; changing only the inverse collection does nothing in the database. Avoid CascadeType.REMOVE on @ManyToMany, which can delete shared rows. orphanRemoval = true deletes children that you remove from the collection.

Check yourself

In Course and Lesson, which side owns the foreign key?

How this connects

Part of Job-ready backend developer.

Was this lesson helpful?

Finished reading? Mark it complete to track your progress.