Bird
Raised Fist0
Spring Bootframework~10 mins

@OneToOne relationship in Spring Boot - Step-by-Step Execution

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - @OneToOne relationship
Define Entity A
Define Entity B
Add @OneToOne in Entity A
Add @OneToOne in Entity B (optional)
Save Entity A with Entity B
Database stores linked records
Fetch Entity A retrieves Entity B automatically
This flow shows how two entities are linked one-to-one by adding @OneToOne annotations and saving them, so fetching one gets the other.
Execution Sample
Spring Boot
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity
public class Person {
  @Id
  private Long id;

  @OneToOne
  private Passport passport;

  // getters and setters
}

@Entity
public class Passport {
  @Id
  private Long id;

  @OneToOne(mappedBy = "passport")
  private Person person;

  // getters and setters
}
Defines two classes Person and Passport linked by a one-to-one relationship using @OneToOne.
Execution Table
StepActionEntity StateDatabase StateResult
1Create Person objectPerson(passport=null)EmptyPerson created with no passport linked
2Create Passport objectPassport(person=null)EmptyPassport created with no person linked
3Set Person.passport = PassportPerson(passport=Passport)EmptyPerson now references Passport
4Set Passport.person = PersonPassport(person=Person)EmptyPassport now references Person
5Save Person to DBPerson(passport=Passport)Person and Passport saved with linkDatabase stores linked records
6Fetch Person from DBPerson(passport=Passport)Person and Passport in DBPerson fetched with Passport linked
7Fetch Passport from DBPassport(person=Person)Person and Passport in DBPassport fetched with Person linked
8EndEntities linkedDatabase consistentOne-to-one relationship established
💡 Entities saved and linked; fetching one entity retrieves the other automatically.
Variable Tracker
VariableStartAfter Step 3After Step 4After Step 5Final
Person.passportnullPassport objectPassport objectPassport objectPassport object
Passport.personnullnullPerson objectPerson objectPerson object
Key Moments - 3 Insights
Why do we set both sides of the relationship (Person.passport and Passport.person)?
Setting both sides keeps the Java objects in sync; execution_table steps 3 and 4 show this. Without both, one side may not reflect the link.
What happens if we save only Person without setting Passport.person?
The database will save the link from Person to Passport, but Passport.person may be null in Java until refreshed. See step 5 and 6 in execution_table.
Is the @OneToOne annotation required on both entities?
No, only one side needs @OneToOne; the other can use mappedBy to indicate the owner. This is shown in the sample code and steps 3 and 4.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 4, what is the value of Passport.person?
Anull
BPerson object
CPassport object
DUndefined
💡 Hint
Check the 'Entity State' column at step 4 in execution_table.
At which step does the database first store the linked entities?
AStep 5
BStep 6
CStep 3
DStep 7
💡 Hint
Look for 'Database State' changes in execution_table rows.
If we skip setting Passport.person, what changes in the execution_table?
ADatabase does not save Passport
BPerson.passport becomes null
CPassport.person remains null after step 4
DPerson object is not created
💡 Hint
Refer to variable_tracker and step 4 in execution_table.
Concept Snapshot
@OneToOne links two entities so each has exactly one related entity.
Use @OneToOne on one side and optionally mappedBy on the other.
Set both sides in Java objects to keep them in sync.
Saving the owning side stores the link in the database.
Fetching one entity loads the linked entity automatically.
Full Transcript
The @OneToOne relationship in Spring Boot links two entities so each has exactly one related entity. You define two classes, for example Person and Passport, and add @OneToOne annotations to connect them. One side owns the relationship, the other uses mappedBy to point back. When you create objects, you set both sides to keep them in sync. Saving the owning entity stores both linked records in the database. Later, fetching one entity automatically loads the linked entity. This trace shows each step from creating objects, setting links, saving to the database, and fetching linked data. Key points are setting both sides and understanding which side owns the relationship.

Practice

(1/5)
1. What does the @OneToOne annotation represent in Spring Boot JPA?
easy
A. A relationship where one entity is linked to exactly one other entity
B. A relationship where one entity is linked to many entities
C. A relationship where many entities are linked to many entities
D. A relationship where entities are not linked at all

Solution

  1. Step 1: Understand the meaning of @OneToOne

    The @OneToOne annotation defines a direct one-to-one link between two entities in JPA.
  2. Step 2: Compare with other relationship types

    Unlike @OneToMany or @ManyToMany, @OneToOne means exactly one entity matches exactly one other entity.
  3. Final Answer:

    A relationship where one entity is linked to exactly one other entity -> Option A
  4. Quick Check:

    @OneToOne = one-to-one link [OK]
Hint: One entity matches exactly one other entity [OK]
Common Mistakes:
  • Confusing @OneToOne with @OneToMany
  • Thinking it allows multiple linked entities
  • Ignoring the uniqueness of the relationship
2. Which annotation is used on the owning side of a @OneToOne relationship to specify the foreign key column?
easy
A. @MappedBy
B. @Column
C. @JoinColumn
D. @Entity

Solution

  1. Step 1: Identify the owning side annotation

    The owning side uses @JoinColumn to specify the foreign key column in the database.
  2. Step 2: Differentiate from mappedBy

    @MappedBy is used on the inverse side, not the owning side.
  3. Final Answer:

    @JoinColumn -> Option C
  4. Quick Check:

    Owning side uses @JoinColumn [OK]
Hint: Owning side uses @JoinColumn for foreign key [OK]
Common Mistakes:
  • Using @MappedBy on owning side
  • Confusing @Column with @JoinColumn
  • Forgetting to specify @JoinColumn
3. Given the following code snippet, what will be the output when fetching Person and accessing person.getPassport().getNumber()?
@Entity
class Person {
  @Id
  private Long id;

  @OneToOne
  @JoinColumn(name = "passport_id")
  private Passport passport;

  // getters and setters
}

@Entity
class Passport {
  @Id
  private Long id;
  private String number;

  // getters and setters
}
medium
A. Throws NullPointerException because passport is not initialized
B. Returns the passport number linked to the person
C. Returns null because @OneToOne is missing mappedBy
D. Compilation error due to missing @MappedBy

Solution

  1. Step 1: Analyze the @OneToOne mapping

    The Person entity owns the relationship with @JoinColumn, so passport is linked properly.
  2. Step 2: Understand the data fetching

    When fetching Person, accessing person.getPassport().getNumber() returns the linked Passport's number if data exists.
  3. Final Answer:

    Returns the passport number linked to the person -> Option B
  4. Quick Check:

    Proper @OneToOne with @JoinColumn returns linked entity [OK]
Hint: Owning side with @JoinColumn returns linked entity [OK]
Common Mistakes:
  • Assuming mappedBy is required on owning side
  • Expecting NullPointerException without data check
  • Confusing compilation errors with runtime behavior
4. Identify the error in this @OneToOne mapping:
@Entity
class User {
  @Id
  private Long id;

  @OneToOne(mappedBy = "user")
  private Profile profile;
}

@Entity
class Profile {
  @Id
  private Long id;

  @OneToOne
  private User user;
}
medium
A. Missing @JoinColumn on Profile entity owning side
B. mappedBy should be on Profile, not User
C. User entity should not have @OneToOne annotation
D. Profile entity must use mappedBy instead of @OneToOne

Solution

  1. Step 1: Check owning side annotations

    Profile is the owning side but lacks @JoinColumn to specify the foreign key.
  2. Step 2: Understand mappedBy usage

    mappedBy is correctly on User side, indicating inverse side.
  3. Final Answer:

    Missing @JoinColumn on Profile entity owning side -> Option A
  4. Quick Check:

    Owning side needs @JoinColumn [OK]
Hint: Owning side must have @JoinColumn [OK]
Common Mistakes:
  • Placing mappedBy on owning side
  • Omitting @JoinColumn on owning side
  • Confusing owning and inverse sides
5. You want to create a bidirectional @OneToOne relationship between Employee and Desk. Which is the correct way to define the relationship so that Employee owns the relationship and the foreign key is in the Desk table?
hard
A. In Employee: @OneToOne(mappedBy = "desk") Desk desk; In Desk: @OneToOne @JoinColumn Employee employee;
B. In Employee: @OneToOne @JoinColumn Desk desk; In Desk: @OneToOne(mappedBy = "desk") Employee employee;
C. ;eeyolpme eeyolpmE nmuloCnioJ@ enOoTenO@ :kseD nI ;ksed kseD )"eeyolpme" = yBdeppam(enOoTenO@ :eeyolpmE nI
D. In Employee: @OneToOne(mappedBy = "employee") Desk desk; In Desk: @OneToOne @JoinColumn Employee employee;

Solution

  1. Step 1: Determine owning side and foreign key location

    The foreign key is in Desk table, so Desk owns the relationship.
  2. Step 2: Correct annotation placement

    Desk must have @JoinColumn and no mappedBy; Employee uses mappedBy to point to Desk's field.
  3. Step 3: Match option with correct annotations

    In Employee: @OneToOne(mappedBy = "employee") Desk desk; In Desk: @OneToOne @JoinColumn Employee employee; matches this.
  4. Final Answer:

    In Employee: @OneToOne(mappedBy = "employee") Desk desk; In Desk: @OneToOne @JoinColumn Employee employee; -> Option D
  5. Quick Check:

    Foreign key side owns with @JoinColumn, other side uses mappedBy [OK]
Hint: Foreign key side owns with @JoinColumn, other side uses mappedBy [OK]
Common Mistakes:
  • Assigning owning side incorrectly
  • Placing mappedBy on owning side
  • Confusing which table holds foreign key