Hi there, I am writing after a long time, couldn’t
write for last few months due to various circumstances. Anyway, I am back now
and I am also celebrating ‘no guffs in the blogs day’ today. So, let’s come
straight to the point. We will discuss about the newly released spring data
framework. The framework which has made database interaction a piece of cake.
Spring data provides support for almost all kinds of databases which exist in this world. We will discuss about relational and non-relational (mongodb) databases in this blog. First, let us discuss a bit of theory of how spring data works. We will then see some examples. Spring data mainly relies on two things for database communication namely Bean class and repository. Bean class is the mapper class for the database table (or mongo collection) and repository is just an interface. Spring data provides many types of repositories, e.g. Crud Repository, Mongo repository to name a few. It uses the reflection and methods defined in user repositories to build and execute the queries. Well, this may seem a bit complicated. Let’s see the whole process step by step.
Suppose we have an Employee bean, defined as follows:
Spring data provides support for almost all kinds of databases which exist in this world. We will discuss about relational and non-relational (mongodb) databases in this blog. First, let us discuss a bit of theory of how spring data works. We will then see some examples. Spring data mainly relies on two things for database communication namely Bean class and repository. Bean class is the mapper class for the database table (or mongo collection) and repository is just an interface. Spring data provides many types of repositories, e.g. Crud Repository, Mongo repository to name a few. It uses the reflection and methods defined in user repositories to build and execute the queries. Well, this may seem a bit complicated. Let’s see the whole process step by step.
Suppose we have an Employee bean, defined as follows:
@Entity
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String
getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Remember that, it is essential to have setter
and getter methods in order for spring data to work properly. And, the setters
and getters should abide java bean standards as well.
In above example, @Entity annotation tells us
that this is an entity, @Id indicates id and @GeneratedValue is self
explanatory (more on annotations here). Apart from this, we should tell spring where to search for
entities and repository in configuration file. Examples of which are shown here.
Now let us see the the repository.
public interface
EmployeeRepository extends CrudRepository(Employee, Integer){
}
Please note that Repository is always an
interface. We create our own interface which extends Spring’s interface
(CrudRepository in our example). Spring will implement our interface and will
provide support for different db operations. Methods supported by Crud
repository are listed here.
Now, let’s see how we can persist the record. Below is the code.
Employee employee = new Employee();
employee.setName("abcd");
EmployeeRepository repository = context.getBean(EmployeeRepository.class);
int id = repository.save(employee);
See the magic, we haven’t defined save method
anywhere and still, we are able to save employee record. Save() will return the
id of newly created record which we can use further. Context is the reference
of spring application context.
Now comes the most exciting part. Suppose we
want to find the employees whose name is ‘MyName’. How should we do it? Should we
write a query? Should we create criteria? Should we create a prepared
statement? Well, as I told you earlier, we do NOT need to create any of these.
All we need to write is, well, a mere line. Yes, just a line. We will modify
our repository so that it includes a mehod. The modified repository will look
like this:
public interface
EmployeeRepository extends CrudRepository(Employee, Integer){
public List<Employee>
findByName(String name);
}
Observe the name of the method very carefully.
It says findByName (B and N are capital). It has to be declared EXACTLY like
this. There is no relaxation here. Spring starts scanning the method name from
the right, uses reflection and string manipulations to locate member variables
of entity class and relations between conditions. It then generates the query.
However, all we need to do is JUST to define the method. This is it. Spring
will take care of the rest. So, the code to execute the query or to fetch the
employees with given name I should say, will look like this:
EmployeeRepository repository = context.getBean(EmployeeRepository.class);
List<Employee> list =
repository.findByName("MyName");
Voila! We are done. Where is the query? Where is
a criterion? Where is prepared statement? Where is result set? They are nowhere
to be seen. Spring data saves us from these burdens and takes care of them. So, we have
just executed query without even writing it! Isn’t it magic? It indeed is.
However, we need to be extra careful when
defining the methods in repository. As I mentioned earlier, order, case and
arguments and return type DO matter A LOT (i.e. above method returns only one
employee if a return type is Employee object). Let’s see some example methods
for different queries:
1. Find Employees whose name is ‘Name’ and id is
greater than 100:
public List<Employee>
findByNameAndIdGreaterThan(String name, int id);
2. Find Employees whose age is greater than 25, in
an ascending order of age:
Interface method:
public List<Employee>
findByAgeGreaterThan(int age, Sort sort);
Implementation:
List<Employee>
list = repository.findByAgeGreaterThan(25, new Sort(Sort.Direction.ASC, "age"));
See? There is a Sort object which defines the
sort direction and field. Similarly, there is a class for pagination. Let’s see
an example of the same.
3. Find Employees whose age is greater than 25, in
ascending number of age, show first 10.
Interface method:
public List<Employee>
findByAgeGreaterThan(int age, Pageable pageable);
Implementation:
PageRequest
request =
new
PageRequest(1, 10, Sort.Direction.ASC, "age");
List<Employee> list =
repository.findByAgeGreaterThan(25, pageRequest);
For pagination, Spring data defines Pageable
interface which in turn is implemented by PageRequest class.
This was overview of spring data and how
repositories work. For mongo database (non reational), spring has
MongoRepository which helps in inserting and querying the data. For in-depth
knowledge of spring data and how the methods should be named, I would recommend
to go through this
and this
links.
That is your lot for this time. Hope you have
liked it. Will be back with a new topic as soon as I can.
Happy Coding.
~ Cheers