In this article, we will quickly learn to implement one-to-one relationships between entities in Spring Boot JPA.
There are mainly three types of relationship between the entities:
- One-to-One
- One-to-Many/Many-to-One
- Many-to-Many
One-to-One Relationship
A one-to-one relationship is a relationship where a record in one table is associated with exactly one record in another table
Let's take an example of Person entity which has one-to-one
mapping with passport entity.
The person and passport classes are using Lombok
to reduce boilerplate code, I suggest you to go through Lombok article .
PersonEntity.java
@Entity
@Table(name = "person")
@Getter @Setter @Builder
@NoArgsConstructor
@AllArgsConstructor
public class PersonEntity {
@Id
@Column(name = "person_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer personId;
@Column(name = "person_name")
private String personName;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "passport_number", unique = true)
private PassportEntity passport;
}
PassportEntity.java
@Entity
@Table(name = "passport")
@Getter @Setter @Builder
@NoArgsConstructor
@AllArgsConstructor
public class PassportEntity {
@Id
@Column(name = "passport_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer passportId;
@Column(name = "passport_number")
private String passportNumber;
@Column(name = "country")
private String country;
@Column(name = "passport_type")
private String passportType;
@OneToOne(mappedBy = "passport")
private PersonEntity person;
}
The relationship in database ER Diagram is represented as follow.
In the above example, the meaning of CascadetType.ALL
is that the persistence will propagate (cascade) all EntityManager operations (PERSIST, REMOVE, REFRESH, MERGE, DETACH) to the relating entities.
@JoinColumn(name = "passport_number", unique = true)
specifies the column to join the entity association.
name
attribute specifies the name of the foreign key column.
unique
attribute specifies that the foreign key column is a unique attribute.
mappedBy
attribute specifies the field that owns the relationship.
Testing
Let's see a test case to test the bidirectional one-to-one relationship between Person and Passport.
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class EntityMappingApplicationTests {
@Autowired
private PersonRepository personRepo;
@Autowired
private PassportRepository passportRepository;
private PersonEntity person = null;
private PassportEntity passport = null;
private Integer personId;
@BeforeAll
public void setup() {
passport = PassportEntity.builder()
.passportNumber("A1234567")
.country("India")
.passportType("Diplomatic")
.build();
person = PersonEntity.builder()
.personName("John Doe")
.passport(passport)
.cards(cards)
.build();
person = personRepo.save(person);
personId = person.getPersonId();
}
@Test
public void testOneToOne() {
PersonEntity person = personRepo.findById(personId).orElse(null);
assertNotNull(person.getPassport());
assertEquals("A1234567", person.getPassport().getPassportNumber());
PassportEntity passport = passportRepository.findByPassportNumber("A1234567");
assertNotNull(passport.getPerson());
assertEquals("John Doe", passport.getPerson().getPersonName());
}
}
On running this test case, we will find all these test cases runs successfully and verifies that our implementation is correct.
Summary
In this article, we learnt about implementation of one-to-one mapping relationship in Spring Data JPA. The other mapping relationship in Spring Data JPA will be discussed in further post.
You can find the source code of this post @ Github