Friday, 26 September 2014

Spring data : Execute the query without even writing it!

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:


@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

2 comments:

  1. Good one Darshan!

    The Spring Data is useful tool for rapid development. The Cross-store (Database Like MySQL and MongoDB) support is very useful in Modern Enterprise.

    ReplyDelete