Wednesday, August 12, 2020

Java Technical Interview @ Wipro: Round-2

 Hi friends,

In this post, I am sharing java technical interview questions and answers in Wipro : Round-2.


Question 1:

What is N+1 problem in hibernate?

Answer:

N+1 problem is a performance issue in object relational mapping that fires multiple select queries (N+1 to be exact , where N = number of records in table) in database for a single select query at application layer.

Hibernate provides multiple ways to catch and prevent this problem.


What is N+1 problem?

To understand N+1 problem, lets consider a scenario. Let's say we have a collection of user objects mapped to tab_users table in database and each user has collection of roles mapped to tab_roles table using a joining table tab_user_roles. At the ORM level , a user has many to many relationship with role.


@Entity

@Table(name="tab_users")

public class User{

    @Id

    @GeneratedValue(strategy=GenerationType.AUTO)

    private long id;

    private String name;

    @ManyToMany(fetch=FetchType.LAZY)

    private Set<Role> roles;

}


@Entity

@Table(name="tab_roles")

public class Role{

    @Id

    @GeneratedValue(strategy = GenerationType.AUTO)

    private long id;

    private String name;

}


Now let's say we want to fetch all users from users table and print roles for each one. Very naive Object Relational implementation will be:

First get All users:

select * from tab_users;

Then get roles for each user:

select * from tab_user_roles where user_id=<userid>;


So, we need one select for user and N additional selects for fetching roles for each user, where N is total number of users. This is a classic N+1 problem in ORM.

How to identify it?

Hibernate provides tracing option that enables SQL logging in the console/logs. Using logs, we can easily see if hibernate is issuing N+1 queries for a given call.

Enabling SQL logging in application.yml:

spring:

    jpa:

        show-sql: true

        database-platform: org.hibernate.dialect.H2Dialect

        hibernate:

            ddl-auto:create

            use-new-id-generator-mappings: true

        properties:

            hibernate:

                type: trace


Enables SQL logging in trace.

We have to enable this too in order to show sql queries in logs.


N+1 Resolution:

Hibernate and spring data provide mechanism to solve the N+1 ORM issue.

At SQL level, what ORM needs to achieve to avoid N+1 is to fire a query that joins the two tables and get the combined results in single query.


Spring data JPA approach:

If we are using spring data JPA, then we have two options to achieve this - using EntityGraph or using select query with fetch join.


public interface UserRepository extends CrudRepository<User, long>{

    List<User> findAllByRolesIn(List<Role> roles);

    @Query("select p from User p Left Join Fetch p.roles")

     List<User> findWithoutNPlusOne();

    @EntityGraph(attributePaths= {"roles"})

    List<User> findAll();


N+1 queries are issued at database level.

Using left join fetch , we resolve the N+1 problem.

Using attributePaths, Spring data JPA avoids N+1 problem.



Hibernate approach:

If it is pure hibernate, then the following solution will work.

HQL Query:

"from User u join fetch u.roles  roles roles"

Hibernate Criteria API:

Criteria criteria = session.createCriteria(User.class);

criteria.setFetchMode("roles", FetchMode.EAGER);


Under the hood, all these approaches work similar and they issue a similar database query with left join fetch.



Question 2:

Write code to implement ThreadPool in java.

Answer:

 import java.util.concurrent.LinkedBlockingQueue;

public class ThreadPool{

    private final int nThreads;

    private final PoolWorker[] threads;

    private final LinkedBlockingQueue queue;


    public ThreadPool(int nThreads){

        this.nThreads = nThreads;

        queue = new LinkedBlockingQueue();

        threads = new PoolWorker[nThreads];

        for(int i = 0; i < nThreads; i++){

            threads[i] = new PoolWorker();

            threads[i].start();

        }

    }


    public void execute(Runnable task){

        synchronized(queue){

            queue.add(task);

            queue.notify();

        }

    }

    private class PoolWorker extends Thread{

        public void run(){

            Runnable task;

            while(true){

                synchronized(queue){

                    while(queue.isEmpty()){

                        try{

                            queue.wait();   

                        }

                        catch(InterruptedException ie){

                            

                        }

                    }

                    task = queue.poll();

                }

                try{

                    task.run();

                }

                catch(RuntimeException e){

                }

            

            }

        }

    }

}  



Question 3:

What is CountDownLatch?

Answer:

CountDownLatch is used to make sure that a task waits for other threads to finish before it starts.

e.g.

Consider a server where the main task can only start when all the required services have started.

Working of CountDownLatch:

When we create an object of CountDownLatch, we specify number of threads it should wait for.  All such threads are required to countdown by calling CountDownLatch.countDown(), once they are completed or ready to do the job. As soon as count reaches 0, the waiting task starts running.


Question 4:

What is CyclicBarrier?

Answer:

java.util.concurrent.CyclicBarrier

CyclicBarrier is used to make threads wait for each other. It is used when different threads process a part of computation and when all threads have completed the execution, the result needs to be combined in the parent thread.

In other words, a CyclicBarrier is used when multiple threads carry out different subtasks and the output of these subtasks need to be combined to form the final output.

After completing it's execution, threads call await() method and wait for other threads to reach the barrier. Once all the threads have reached, the barriers then give the way for threads to proceed.



That's all for this post.

Thanks for reading!!

No comments:

Post a Comment

CAP Theorem and external configuration in microservices

 Hi friends, In this post, I will explain about CAP Theorem and setting external configurations in microservices. Question 1: What is CAP Th...