The best way to map @OneToOne


@OneToOne

The best approach to bidirectional @OneToOne is to use @MapsId

Student entity

@Entity
@Data
@Table(name = "students")
public class Student implements Serializable {

    @Id
    @GeneratedValue
    private Integer id;
    private String name;
    private String email;

    @OneToOne(mappedBy = "student", cascade = CascadeType.ALL)
    private StudentDetails studentDetails;
}

StudentDetails entity

@Entity
@Data
@Table(name = "student_details")
public class StudentDetails implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String studentDetailsInfo;

    @OneToOne
    @JoinColumn(name = "student_id")
    @MapsId
    private Student student;
}

The best way to map @ManyToMany


@ManyToMany

Many to many relationships can be easily mapped by creating another table using @JoinTable as follows.

Student entity

@Data
@Table(name = "Student")
@Entity
public class Student implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String studentName;

    @ManyToMany
    @JoinTable(
        name = "student_task",
        joinColumns = @JoinColumn(name = "task_id"),
        inverseJoinColumns = @JoinColumn(name = "student_id")
    )
    private Set<Task> tasks = new HashSet<>();
}


Task entity

@Entity
@Data
@Table(name = "tasks")
public class Task implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String taskName;

    @ManyToMany(mappedBy = "tasks")
    private Set<Student> students = new HashSet<>();
}

How to avoid NullPointerException


java.lang.NullPointerException

When can it be thrown?

According to the JavaDoc, the following scenarios can be found.
  • Calling the instance method of a null object.
  • Accessing or modifying the field of a null object.
  • Taking the length of null as if it were an array.
  • Accessing or modifying the slots of null as if it were an array.
  • Throwing null as if it were a Throwable value.

How to avoid it?

  • Use Optional in Java 8
  • Call equals() and equalsIgnoreCase() methods on known objects.
  • Use valueOf() over toString()
public class NullCheckDemo {
   public static void main(String args[]){
       Integer i = null;
       System.out.println(i.toString());      //This throws NullPointerException
       System.out.println(String.valueOf(i)); //This returns null
   }
}
  • Use null-safe methods and libraries. Ex: Apache Commons StringUtils.
  • Use @NotNull and @Nullable annotations
  • Always check for nulls.
public class NullDemo {
    public static void main(String args[]){
        Integer i = null;

        if(i != null)
            System.out.println(i);
        else
            System.out.println("error occurred");
    }
}


Thread pool in Java


The Thread pool

Introduction

  • Executor implementations use thread pools.
  • The thread pool is a collection of worker threads that are ready to serve.
  • Creating new threads and manage them uses a big amount of data.
  • Worker threads in the thread pool will help to reduce this overhead of creating threads.
  • Tasks are submitted to the pool via an internal queue called blocking queue.
  • If there are more tasks than active threads, these tasks will be inserted into a blocking queue until a thread becomes available.
  • A common type of thread pool is the fixed thread pool.

Fixed thread pool

  • This has a specific number of running threads.
  • If a thread stops, this will replace with a new thread.
  • The main advantage of the fixed thread pool is it will limit the threads of an application.
  • It won't let the application exceed the limit of threads that the application handles.

Java ExecutorService


Java ExecutorService

Introduction

  • If an application has few threads, it can be used threads very easily using the above methods.
  • But if an application has many threads, it will be not easy to handle this.
  • Executors can be used to avoid this complexity.
  • The executor framework is a framework that can be used for creating, managing and executing threads.
  • This provides an asynchronous feature to Java applications.

Features of Executor service

  • Thread creation
    • Provides thread pool and various methods to create threads.
  • Thread Management
    • The thread pool will manage the life cycle of threads.
  • Thread Execution
    • Various methods will be provided
    • Thread schedulers can be used.

Executor interfaces in the Java Concurrency API

  • Executor
    • Provides a single method execute() to create a thread.
    • (new Thread(r)).start() can be replaced with e.execute(r)
  • ExecutorService
    • Also provides execute() method but this accepts both Runnable and Callable objects.
  • ScheduledExecutorService
    • This can be used to act as the asynchronous manner in Java
    • It can be used periodically and after a specific timeout.
    • Runnable and Callable tasks can be executed


Thread priority


Thread priority

  • Each thread has a priority.
  • It starts from 1 to 10 and the highest priority is 10 while the lowest is 1.
  • The default priority of the main thread is 5.
  • If you set the thread priority out of 10, it will give a compile-time error
Exception in thread "main" java.lang.IllegalArgumentException

List vs Queue vs Set vs Map


 List vs Queue vs Set vs Map


ListQueueSetMap
DuplicatesYesYesNoNo(Allow duplicate values not keys)
OrderYesYesNoNo
Null valuesYesPriority queue doesn't allow, but queue using LinkedList allows nullSingle nullSingle null key and many null values