Table of Contents
Introduction
In this post, we will go over the most popular Spring Data JPA interview questions. We have covered questions ranging from the most basic to the advanced ones, so that even if you are not familiar with what is Spring data JPA as a concept, you will get an idea about it. Every enterprise application developer must know about Spring data JPA because this is the most important section the interviewer likes to focus on.
What is JPA?
JPA also known as Java Persistence API is an interface which defines a mapping between relations and objects. It describes how a Java object is mapped to a database table. JPA gives a mechanism to query the database and returns the results back as a collection of Java objects or Java objects to be store in the database. The ORM implementation converts these API calls to SQL queries.
What is Spring Data?
Spring Data is basically a Spring project which contains many modules. The modules are spring-data-commons, spring-data-jdbc, spring-data-redis, spring-data-mongo etc. Spring data provides a consistent way of accessing different data stores which can be either relational or no-sql databases.
What is Spring Data JPA?
Spring Data JPA eliminates the need to write common queries. This is possible because Spring Data JPA contains JPA repositories which defines query methods. The name of the method declared in the repository interface automatically converts or generates the low level SQL queries. In the below example, it will convert the method name to SQL query as “select * from Employee where empName=”{whatever name is provided}”
List<Employee> findByEmpName(String name)
What is the difference between JPA and Spring Data JPA?
JPA is a specification for accessing database for storing and fetching the data.
Whereas, Spring Data JPA eliminates the need to write common queries. This is possible because Spring Data JPA contains JPA repositories which defines query methods. The name of the method declared in the repository interface automatically converts or generates the low level SQL queries.
What is the difference between CrudRepository and JpaRepository?
Both CrudRepository and JpaRepository are interfaces. As the name suggests, CrudRepository provides CRUD opeartions. JpaRepository also provides CRUD operations, and in addition to that it allows paginations and sorting the records, because JpaRepository extends the PagingAndSortingRepository, which extends the CrudRepository.
Which ORMs are supported by Spring?
Hibernate, Oracle, TopLink, JDO, OJB are the ORMs supported by Spring.
What is Hibernate
Hibernate is the most popular JPA implementation. It makes creating the queries and interacting with the database easy.
What are different types of transaction management supported by Spring
There are two ways in which we can implement transaction management and which is supported by Spring i.e. Declarative and programmatic transaction management.
In case of declarative transaction management, we make use of @Transactional annotation. This approach separates out the business logic and transaction management code.
Which transaction management type is preferred by Spring?
Out of the two transaction management type i.e. declarative and programmatic transaction management, the declarative way of transaction management is most preferred because it can be implemented as cross-cutting concern.
What are the benefits of Spring Transaction?
- Declarative Spring transaction management is implemented using the aspected oriented programming (AOP) programming , hence it does not impact the application code.
- Spring transaction management makes handling transactions across different data access technologies in a consistent way.
What is @Transactional annotation
@Transactional annotation is to handle transactions and it is a declarative way of managing transactions.
What are finder methods in Spring Data JPA
Finder methods are the methods written in specific format or specific naming conventions, so that these methods are then converted into low level SQL queries.
The initial’s of the finder method will be common across all method names, i.e. findBy , followed by the field name of the entity (mapped to the database column). If we want to fetch the details of an Employee by the name, then we can write the method name in the Repository interface as below if the attribute name or column name in the entity is empName
List<Employee> findByEmpName(String name);
Entire tutorial or explanation can be found on this link
Spring Data JPA – @Id annotation
@Id annotation in Spring Data JPA is used to mark a field in entity class as a primary key.
public class Employee {
@Id
private Integer id;
}
Spring Data JPA – @Param annotation
@Param annotation in Spring Data JPA is used to pass parameter to the query in the where clause.
@Query("FROM Employee e WHERE e.name = :name")
Employee findByName(@Param("name") String name);
Spring Data JPA – @Query annotation
If we have a custom query which are not fulfilled by finder methods, then in that case we can use @Query annotation above the method and write a JPQL (Java Pesrsistence query language) or native SQL query. While writing native SQL query, we need to add two attributes i.e. value and nativeQuery. Examples below
//JPQL way
@Query("FROM Employee e WHERE e.name = :name")
Employee findByName(@Param("name") String name);
//Native query way
@Query(value = "SELECT AVG(e.salary) FROM employee e", nativeQuery = true)
int getAverageSalary();
Spring Data JPA – @Transient annotation
@Transient annotation is used at the field level in the model class. The datastore engine will not read or write the field value which is annotated with Transient.
Spring Data JPA – @EnableJpaRepositories annotation
@Configuration
@EnableJpaRepositories(basePackages = "com.springmicroservices.dao")
class JPAConfig {}
@EnableJpaRepositories annotation is used in conjunction with @Configuration annotation. If we want to use JPA repositories, then we need to inform Spring about the usage. The package specified in basePackages attribute contains all the repositories. Spring Boot does this automatically if it finds the Spring Data JPA on the classpath.
Spring Data JPA – @Entity & @Table annotation
@Entity annotation is used to map a Java class with the database table.
@Table Spring Data annotation is used if we want to map the class to a table with a different name. In the below example we have a class named as CricketTeam, but the database table name is Team, so we need to tell Spring JPA about the mapping using @Table annotation. Ideally same name is used for the class as well as database table.
@Entity
@Table(name="Team")
Public class CricketTeam {
}
How to create Spring Data JPA Composite Primary Key?
A Composite primary key also known as composite key is like a primary key with a combination two or more columns. There are two way of implementing a composite primary key by either using @IdClass or @EmbeddedId annotation.
@IdClass annotation
We have made use of two annotation, i.e. @IdClass and @Id
@Entity
@IdClass(EmployeeId.class)
public class Employee{
@Id
private String employeeId;
@Id
private String employeePhoneNumber;
@Column(name = "name")
private String employeeName;
.
.
/* constructors, getters and setters */
}
public class EmployeeId implements Serializable {
private String employeeId;
private String employeePhoneNumber;
}
@EmbeddedId annotation
We have made use of two annotation, i.e. @Embeddable and @EmbeddedId
@Embeddable
public class EmployeeId implements Serializable {
private String employeeId;
private String employeePhoneNumber;
// default constructor
public EmployeeId(String employeeId, String employeePhoneNumber) {
this.employeeId= employeeId;
this.employeePhoneNumber= employeePhoneNumber;
}
/* getters, setter, equals() and hashCode() methods */
}
@Entity
public class Employee{
@EmbeddedId
private EmployeeId employeeId;
@Column(name = "name")
private String employeeName;
.
.
/* constructors, getters and setters */
}
Cascade in Spring Data JPA
Cascading in Spring Data JPA is when we are performing an operation on an entity, then the operation should also be applied to its associated entity. In case of delete operation, then the delete operation must be applied to the associated entity also. For example if we are Employee-Address relationship, when we delete an employee from Employee table, then the associated entry in the Address table should also get deleted. There are Six JPA Cascade types.
- ALL
- PERSIST
- MERGE
- REMOVE
- REFRESH
- DETACH
What is @JoinColumn annotation in Spring DATA JPA
@JoinColumn is used to specify a column for joining an entity association. This annotation indicates that the enclosing entity is the owner of the relationship and the corresponding table has a foreign key column which references to the table of the non-owning side.
@Entity
class Employee { //non-owning side of the relationship
@Id
private String employee_id;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "address")
private Collection<Address> addresses = new ArrayList<Address>();
}
@Entity
class Address { //owning side of the relationship
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="employee_id")
private Employee employee;
}
What is mappedBy attribute
In a bidirectional relationship, one of the sides (entity) has to be the owner. To declare a side as not responsible for the relationship, the attribute mappedBy is used. mappedBy refers to the property name of the association on the owner side.
@Entity
class Employee { //non-owning side of the relationship
@Id
private String employee_id;
@OneToMany(mappedBy = "address")
private Collection<Address> addresses = new ArrayList<Address>();
}
@Entity
class Address { //owning side of the relationship
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="employee_id")
private Employee employee;
}
What are JPA Annotations for establishing Relationships
@OneToOne @OneToMany @ManyToOne @ManyToMany
How to generate Primary Key in Spring JPA
Basically there are 4 options to generate primary keys in spring jpa
GenerationType.AUTO
GenerationType.AUTO is the default generation type which lets the persistence provider choose the generation type. If you talk about Hibernate, then it mostly uses GenerationType.SEQUENCE.
GenerationType.IDENTITY
GenerationType.IDENTITY relies on an auto-incremented database column and lets the database generate a new value with each insert operation. From the database perspective, this is very efficient because the auto-increment columns are highly optimized, and it doesn’t require any additional statements.
GenerationType.SEQUENCE
The GenerationType.SEQUENCE uses a database sequence to generate unique values. It requires additional select statements to get the next value from a database sequence.
GenerationType.TABLE
Most of the developers have stopped using this technique as it slows down the application.
What is the difference between CascadeType.REMOVE and orphanRemoval attribute
CascadeType.REMOVE
@Entity
class Employee {
:
@OneToMany(cascade=CascadeType.REMOVE)
private Collection<Address> addresses = new ArrayList<Address>();
:
}
CascadeType.REMOVE attribute states that when Employee object is deleted then the corresponding Address details also should be deleted. If you invoke setAddresses(null), the related Address entities will NOT be removed in db automatically.
orphanRemoval=true
For orphan removal: If you invoke setAddresses(null), The related Address entities will be removed from the database automatically.
What is One-to-One-Unidirectional Relationship?
A one-to-one relationship is a relationship where we can traverse to the child object from the parent object. But the child object does not refer back to the parent entity.
For example there is a one-to-one Relationship between a Booking and Payment. Whenever we book a movie ticket, we make a payment against the booking. Booking entity will contain the Payment entity, Payment cannot refer back to the parent i.e. Booking. The id column in the payment table is present in the Book table as a foreign key i.e. payment_id
@Entity
@Table(name="BOOK")
@Data
public class Book {
private Integer id;
private String name;
@OneToOne(cascade=CascadeType.ALL, orphanRemoval=true)
@JoinColumn(name="payment_id")
private Payment payment;
@Entity
@Table(name="PAYMENT")
@Data
public class Payment {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private BigDecimal amount;
private PaymentStatus status;
What is One-to-One Bidirectional Relationship
A One-to-One Bidirectional relationship is a relationship where the traversing between the parent and child object is possible in both ways.
@Entity
@Table(name="CUSTOMER")
@Data
public class Customer {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id",length=50)
private Integer id ;
private String name;
@OneToOne(cascade=CascadeType.ALL, orphanRemoval=true)
@JoinColumn(name="CART_ID")
private Cart cart ;
}
@Entity
@Table(name="CART")
@Data
public class Cart {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id",length=50)
private Integer id;
private Double amount;
@OneToOne(mappedBy="cart")
private Customer customer ;
What is One-to-One Self Referencing Relationship
A one-to-one self-referencing relationship is a relationship that refers to its own instance.
Example: Lets say we have a Student and each Student present in the class will have their class representative. The Class representative is also a Student. In this case we can use Self Referencing Relationship.
@Entity
@Table(name="STUDENT")
@Data
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID",length=50)
private Integer id;
private String name;
@OneToOne(cascade=CascadeType.ALL, orphanRemoval=true)
@JoinColumn(name="representative_id",nullable=true)
private Student representative;
What is One-to-Many Uni-directional Relationship
One-to-Many Uni-directional relationship is a relationship in which there is a reference between parent to the child but the other way round is not possible. In the below example, we can traverse from Person to Phone list, but the opposite is not allowed.
@Entity
@Table(name="PERSON")
public class Person {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID",length=20)
private Integer id;
private String name;
@OneToMany(cascade=CascadeType.ALL,orphanRemoval=true)
@JoinColumn(name="PERSON_ID",referencedColumnName="ID")
private List<Phone> phones ;
}
@Entity
@Table(name="PHONE")
@Data
public class Phone {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID",length=20)
private Integer id;
private String number;
}
What is One-to-Many Bi-directional Relationship
A One-to-Many Bi-directional relationship is a relation where there is reference from parent to child and also vice versa i.e. from child to parent also.
@Entity
@Table(name = "tutor")
@Data
public class Tutor{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int id;
private String name;
private String email;
@OneToMany(mappedBy = "tutor", cascade = CascadeType.ALL, ,orphanRemoval=true)
private List<Course> courses;
}
@Entity
@Table(name = "course")
@Data
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int id;
private String title;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "tutor_id")
private Tutor tutor;
}
What is One-to-Many Self-Referencing Relationship
One-to-Many Self-Referencing relationship is a relationship which has a reference to itself. On one-to-many self-referencing relationship, the parent can be shared by many children.
What is Many-to-Many Uni-directional relationship
Many-to-Many Uni-directional relationship is a relationship in which we can traverse from parent to the child, but vice versa is not possible. Consider an example of User and a Group, a particular user can be part of multiple groups and a group can contain multiple users. We can traverse from User to the list of Group’s , but the other way round is not possible.
@Entity
@Table(name = "USER")
@Data
public class User {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID")
private Integer id;
private String name;
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinTable( name = "USER_GROUP",
joinColumns = @JoinColumn(name = "USER_ID", referencedColumnName="ID"),
inverseJoinColumns = @JoinColumn(name = "GROUP_ID", referencedColumnName="ID"))
private Set<Group> groups = new HashSet<Group>();
}
@Entity
@Table(name="GROUPS")
@Data
public class Group {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID")
private Integer id;
private String name;
}
What is Many-to-Many Bi-directional relationship
In a many-to-many bi directional relationship, one entity owns the relationship and the other is mapped to the relationship. Bidirectional relationship provides navigational access in both directions, so that you can access the other side entity without explicit queries.
Conclusion
I hope you enjoyed the post, thanks for reading this post. If you found this Spring Data JPA Interview questions and answers helpful then feel free to share. If you have any questions on the content then please comment or send me an email.
Leave a Reply