Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Thursday, June 26, 2025

Virtual Threads in Java

In this tutorial we'll see what are virtual threads in Java which are added in Java 21.

Platform threads

Traditional threads which we created till now by implementing Runnable, extending Thread class or by using Executor Service to create thread pools are now known as Platform threads. So, you can say now we have two types of threads which you can create.

  1. Platform Thread
  2. Virtual Thread

When a thread is started, it is scheduled by JVM to run (Thread goes to runnable state) but actual execution of the thread is done by the underlying OS by mapping the platform thread to OS thread. A platform thread is implemented as a thin wrapper around an operating system (OS) thread which means number of available platform threads is limited to the number of OS threads. In other words, you can say scalability of platform threads is limited by the number of available OS threads.

Virtual threads in Java

Virtual threads are also an instance of java.lang.Thread so that way these threads are similar to platform threads. How they differ from platform thread is that virtual threads are implemented by the Java runtime rather than the OS.

Unlike platform thread a virtual thread isn't tied to a specific OS thread which means number of virtual threads is not limited by OS threads. You can have a lot of active virtual threads, even millions, running in the same Java process.

That is the advantage of virtual threads, they provide scale (higher throughput).

How does Virtual thread execute

A virtual thread still runs code on an OS thread, whole process goes as explained below-

  1. The Java runtime schedules a virtual thread
  2. Java runtime assigns or mounts the virtual thread on a platform thread. This platform thread is called a carrier
  3. The underlying OS schedules that platform thread by mapping it to OS thread.
  4. Virtual thread starts its execution. If the mounted virtual thread is performing a blocking I/O operation it can unmount from its carrier.
  5. Now the carrier is free and Java runtime scheduler can mount a different virtual thread on it.

When to use Virtual threads

Platform threads generally have a large thread stack and other resources that are maintained by the OS whereas virtual threads typically have a shallow call stack which means virtual threads are light weight but that doesn't mean they are any faster than platform threads.

What virtual threads provide is scale not speed. Virtual threads are suitable for running tasks that spend most of the time blocked, often waiting for I/O operations to complete. However, they aren't intended for long-running CPU-intensive operations.

How to create Virtual threads in Java

1. Using startVirtualThread(Runnable task) method

In Thread class there is a static method startVirtualThread(Runnable task) which creates a virtual thread to execute a task and schedules it to execute.

public class VTDemo {
  public static void main(String[] args) {
    Runnable r = () -> System.out.println("Running a task"); 

    Thread virtualThread = Thread.startVirtualThread(r);
    
    try {
      virtualThread.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

2. Using ofVirtual() method of Thread class

This method returns a builder for creating a virtual Thread or ThreadFactory that creates virtual threads.

public class VTDemo {
  public static void main(String[] args) {
    Runnable r = () -> System.out.println("Running a task"); 
    Thread virtualThread = Thread.ofVirtual().start(r);
    try {
      virtualThread.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

Thread.Builder interface has two subinterfaces

  1. Thread.Builder.OfPlatform- Builder of platform threads.
  2. Thread.Builder.OfVirtual- Builder of virtual threads.

Thread.Builder example

public class VTDemo {
  public static void main(String[] args) {
    Runnable r = () -> System.out.println("Running a task"); 
    Thread.Builder builder = Thread.ofVirtual();
    // set the name for threads
    builder.name("worker-", 0);
    Thread t1 = builder.start(r);   
    Thread t2 = builder.start(r);   
    try {
      t1.join();
      t2.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    
    System.out.println(t1.getName() + " terminated");
    System.out.println(t2.getName() + " terminated");
  }
}

ThreadFactory of virtual thread example

Thread.Builder has a factory() method that returns a ThreadFactory to create threads from the current state of the builder.

Executors class has methods like newFixedThreadPool(), newCachedThreadPool() which take ThreadFactory as parameter.

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;

public class VTFactoryDemo {
  public static void main(String[] args) {
    ThreadFactory virtualThreadFactory = Thread.ofVirtual().factory();
    ExecutorService es = Executors.newFixedThreadPool(5, virtualThreadFactory);
    Callable<String> c = () -> "Call from thread";
    Future<String> f =  es.submit(c);
    try {
      System.out.println(f.get());
    } catch (InterruptedException | ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    es.shutdown();
  }
}

3. Executors.newVirtualThreadPerTaskExecutor() Method

This method creates an Executor that starts a new virtual Thread for each task. The number of threads created by the Executor is unbounded.

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class VTFactoryDemo {
  public static void main(String[] args) throws InterruptedException, ExecutionException {
    try (ExecutorService es = Executors.newVirtualThreadPerTaskExecutor()) {
      Callable<String> c = () -> "Call from thread";
      Future<String> f =  es.submit(c);
      System.out.println(f.get());  
    }
  }
}

Source: https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html

That's all for this topic Virtual Threads in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java ThreadLocal Class With Examples
  2. Volatile Keyword in Java With Examples
  3. Lock Striping in Java Concurrency
  4. CompletableFuture in Java With Examples
  5. Java ArrayBlockingQueue With Examples

You may also like-

  1. Java Nested Class And Inner Class
  2. CopyOnWriteArrayList in Java With Examples
  3. Java Sealed Classes and Interfaces
  4. Why no Multiple Inheritance in Java
  5. Nested Route in React Router With Example
  6. String Slicing in Python
  7. ServiceLocatorFactoryBean in Spring
  8. Angular Event Binding With Examples

Sunday, November 3, 2024

Java Stream - min() With Examples

In Java Stream API there is a min() method that is used to get the minimum element of this stream according to the provided Comparator. In this post we’ll see some examples of the min() method.

Syntax of the Stream.min() method

min is a terminal operation and its syntax is as given below-

Optional<T> min(Comparator<? super T> comparator)

Here comparator argument is an implementation of the Comparator to compare elements of this stream.

Method returns an Optional describing the minimum element of this stream, or an empty Optional if the stream is empty.

Stream.min is considered a special case of a reduction operation as it takes a sequence of input elements and combines them into a single summary result.

min() method Java examples

1. Finding min value from a stream of numbers.

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class StreamMin {
  public static void main(String[] args) {
    List<Integer> numList = Arrays.asList(7, 9, 14, 1, 59, 23, 77, 10, 12, 4);
      Optional<Integer> minElement = numList.stream().min(Integer::compare);
      if(minElement.isPresent()){
        System.out.println("Minimum element: " + minElement.get());
      }
  }
}

Output

Minimum element: 1

2. In the following example custom comparator is passed as an argument to the min() method to get minimum method as per the passed Comparator.

public class StreamMin {
  public static void main(String[] args) {
    List<Integer> numList = Arrays.asList(7, 9, 14, 1, 59, 23, 77, 10, 12, 4);
      Optional<Integer> minElement = numList.stream().min(new MyComparator());
      if(minElement.isPresent()){
        System.out.println("Minimum element: " + minElement.get());
      }
  }
}

class MyComparator implements Comparator<Integer>{
  @Override
  public int compare(Integer o1, Integer o2) {
    return o1.compareTo(o2);
  }
}

Output

Minimum element: 1

3. Using Stream.min() method with custom object. In the example, objects of Employee class are used and the objective is to find minimum salary using the min() method of the Java Stream API.

Employee class used is as given here.

public class Employee {
  private String empId;
  private int age;
  private String name;
  private char gender;
  private int salary;
  Employee(String empId, int age, String name, char gender, int salary){
    this.empId = empId;
    this.age = age;
    this.name = name;
    this.gender = gender;
    this.salary = salary;
  }
  public String getEmpId() {
    return empId;
  }

  public int getAge() {
    return age;
  }

  public String getName() {
    return name;
  }

  public char getGender() {
    return gender;
  }

  public int getSalary() {
    return salary;
  }
}

In the example mapToInt() method is used to get the salary part of the employee object which is then passed to the min() to get the minimum salary.

public class StreamMin {
  public static void main(String[] args) {
    List<Employee> empList = Arrays.asList(new Employee("E001", 40, "Ram", 'M', 5000), 
                new Employee("E002", 35, "Shelly", 'F', 7000), 
                new Employee("E003", 24, "Mark", 'M', 9000), 
                new Employee("E004", 37, "Rani", 'F', 10000),
                new Employee("E005", 32, "Anuj", 'M', 12000));  
     OptionalInt minEmpSal = empList.stream()
                .mapToInt(Employee::getSalary)
                .min();
      if(minEmpSal.isPresent()){
        System.out.println("Minimum salary: " + minEmpSal.getAsInt());
      }
  }
}

Output

Minimum salary: 5000

That's all for this topic Java Stream - min() With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Java Stream - max() With Examples
  2. Java Stream - filter() With Examples
  3. Java Stream - distinct() With Examples
  4. Java Stream - findFirst() With Examples
  5. Java Stream API Interview Questions And Answers

You may also like-

  1. How to Sort ArrayList of Custom Objects in Java
  2. equals() And hashCode() Methods in Java
  3. Type Casting in Java With Conversion Examples
  4. StringJoiner Class in Java With Examples
  5. Writing a File Asynchronously Java Program
  6. Spring Integration With Quartz Scheduler
  7. Operator Overloading in Python
  8. Angular Access Control CanActivate Route Guard Example

Monday, October 14, 2024

Statement Interface in Java-JDBC

In the post Java JDBC Steps to Connect to DB we have already seen a complete example using the interfaces Driver, Connection, Statement and ResultSet provided by the JDBC API. In this post we’ll see Java Statement interface in detail.

Statement interface in JDBC

java.sql.Statement interface in JDBC API is used to execute a static SQL statement and returning the result of the executed query.

Statement interface has following two sub-interfaces

  1. PreparedStatement
  2. CallableStatement

PreparedStatement– PreparedStatement object stores the SQL statement in its pre-compiled state. That way it can efficiently execute the same SQL statement multiple times with different parameters.

CallableStatement- This interface is used to execute SQL stored procedures.

You can get a Statement object by calling the Connection.createStatement() method on the Connection object.

Frequently used methods of the Statement interface

Mostly you will use the execute methods of the Java Statement interface to execute queries.

  1. boolean execute(String sql)- Executes the given SQL statement (it can be any kind of SQL query), which may return multiple results.
    Returns a boolean which is true if the first result is a ResultSet object; false if it is an update count or there are no results.
  2. ResultSet executeQuery(String sql)- Executes the given SQL statement, which returns a single ResultSet object. If you want to execute a Select SQL query which returns results you should use this method.
  3. int executeUpdate(String sql)- Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement.
    Returns an int denoting either the row count for the rows that are inserted, deleted, updated or returns 0 if nothing is returned.
    Note:This method cannot be called on a PreparedStatement or CallableStatement.
  4. int[] executeBatch()- Submits a batch of commands to the database for execution and if all commands execute successfully, returns an array of update counts.

Java Statement example

Let’s see an example where SQL statements are executed using execute(), executeUpdate and executeQuery methods. In the example-

Using execute() method a SQL statement is executed and then the boolean value is checked.

Using executeUpdate() method insert, update and delete statements are executed and row count of the affected rows is displayed.

Using executeQuery() method select statement is executed and the returned ResultSet is processed.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCStmt {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Loading driver
      Class.forName("com.mysql.jdbc.Driver");
   
      // Creating connection
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/netjs", 
                   "root", "admin");
  
      // creating Statement
      Statement stmt = connection.createStatement();  
            
      /** execute method **/
      boolean flag = stmt.execute("Update Employee set age = 40 where id in (5, 6)");
      if(flag == false){
        System.out.println("Updated rows " + stmt.getUpdateCount() );
      }
            
      /** executeUpdate method **/
      // Insert
      int count = stmt.executeUpdate("Insert into employee(name, age) values('Kim', 23)");
      System.out.println("Rows Inserted " + count);
            
      // update
      count = stmt.executeUpdate("Update Employee set age = 35 where id = 17");
      System.out.println("Rows Updated " + count);
            
      //delete
      count = stmt.executeUpdate("Delete from Employee where id = 5");
      System.out.println("Rows Deleted " + count);
            
      /** executeQuery method **/
      // Executing Query
      ResultSet rs = stmt.executeQuery("Select * from Employee");

      // Processing Resultset
      while(rs.next()){
        System.out.println("id : " + rs.getInt("id") + " Name : " 
          + rs.getString("name") + " Age : " + rs.getInt("age")); 
      }    
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally{
      if(connection != null){
        //closing connection 
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      } // if condition
    }// finally
  }
}

Reference: https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/Statement.html

That's all for this topic Statement Interface in Java-JDBC. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Connection Interface in Java-JDBC
  2. Types of JDBC Drivers
  3. CallableStatement Interface in Java-JDBC
  4. Batch Processing in Java JDBC - Insert, Update Queries as a Batch
  5. Connection Pooling Using C3P0 in Java

You may also like-

  1. BigInteger in Java With Examples
  2. Nested class and Inner class in Java
  3. Serialization Proxy Pattern in Java
  4. How ArrayList Works Internally in Java
  5. CopyOnWriteArrayList in Java With Examples
  6. Volatile Keyword in Java With Examples
  7. Garbage Collection in Java
  8. Spring NamedParameterJdbcTemplate Insert, Update And Delete Example

Sunday, October 13, 2024

Types of JDBC Drivers

JDBC API standardizes the way any Java application connects to DB. JDBC API is a collection of interfaces and JDBC drivers implement these interfaces in the JDBC API enabling a Java application to interact with a database.

The JDBC driver gives out the connection to the database and implements the protocol for transferring the query and result between client and database.

JDBC Driver Types

JDBC drivers can be categorized into four types.

Saturday, October 12, 2024

ResultSet Interface in Java-JDBC

java.sql.ResultSet interface in JDBC API represents the storage for the data you get by executing a SQL statement that queries the database.

A ResultSet object maintains a cursor pointing at the result data. Initially the cursor is positioned before the first row. The next method moves the cursor to the next row, it returns false when there are no more rows in the ResultSet object.

Creating and iterating a ResultSet Example

ResultSet rs = stmt.executeQuery("Select * from Employee");
   
// Processing Resultset
while(rs.next()){
 System.out.println("id : " + rs.getInt("id") + " Name : " +  rs.getString("name") + " Age : " + rs.getInt("age")); 
}

By default, ResultSet object is not updatable and has a forward moving cursor only. Thus, you can iterate through it only once and only from the first row to the last row. But ResultSet interface provides parameters that can produce ResultSet objects that are scrollable and/or updatable.

Fields for scrollable ResultSet

ResultSet interface in Java has fields that determine whether ResultSet object will be scrollable or not and will it be sensitive to the changes to the data that is represented by ResultSet or not.

  • TYPE_FORWARD_ONLY- The constant indicating the type for a ResultSet object whose cursor may move only forward.
  • TYPE_SCROLL_INSENSITIVE- The constant indicating the type for a ResultSet object that is scrollable but generally not sensitive to changes to the data that underlies the ResultSet. Which means you can move the cursor to an absolute position or relative to the current cursor position. If the data in the DB is changed by another thread/process that change won’t be reflected in the data stored in the ResultSet.
  • TYPE_SCROLL_SENSITIVE- The constant indicating the type for a ResultSet object that is scrollable and generally sensitive to changes to the data that underlies the ResultSet. Which means you can move the cursor to an absolute position or relative to the current cursor position. If the data in the DB is changed by another thread/process that change is reflected in the data stored in the ResultSet.

Fields for updatable ResultSet

  • CONCUR_READ_ONLY- The constant indicating the concurrency mode for a ResultSet object that may NOT be updated.
  • CONCUR_UPDATABLE- The constant indicating the concurrency mode for a ResultSet object that may be updated.

Java ResultSet interface example

Let’s see an example with scrollable resultset, DB used here is MySql, schema is netjs and table is Employee.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCResultSet {

 public static void main(String[] args) {
  try(Connection connection = DriverManager.getConnection(
      "jdbc:mysql://localhost:3306/netjs", "root", "admin")){
   // creating Statement
   Statement stmt = connection.createStatement(
                           ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);  
   
   // Executing Query
   ResultSet rs = stmt.executeQuery("Select * from Employee");
   System.out.println("Displaying all rows");
   // Processing Resultset
   while(rs.next()){
       System.out.println("id : " + rs.getInt("id") + " Name : " 
        + rs.getString("name") + " Age : " + rs.getInt("age")); 
   }
   // moving to 3rd row
   rs.absolute(3);
   System.out.println("Displaying 3rd row");
   System.out.println("id : " + rs.getInt("id") + " Name : " 
                          + rs.getString("name") + " Age : " + rs.getInt("age")); 
  }catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

Output

Displaying all rows
id : 5 Name : Tom Age : 35
id : 6 Name : Tim Age : 20
id : 7 Name : John Age : 25
id : 8 Name : Johnny Age : 35
id : 17 Name : Johnny Age : 65
Displaying 3rd row
id : 7 Name : John Age : 25

Getter Methods in ResultSet

You would have noticed in the examples how appropriate data type getter method is used (i.e. getInt, getString) for retrieving column values from the current row. You can retrieve value using either the index number of the column or the name of the column.

In general, using the column index will be more efficient. Columns are numbered from 1. Drawback is, any alteration in the table structure will mean change in the indexes in the Java code.

Updater methods in ResultSet

There are also updater methods corresponding to the data types which are used when your ResultSet is updatable. Using updater methods you can update the column values then update the row in the DB. Updater methods are used in conjunction with updateRow and insertRow methods.

Let’s see an example to update a row and insert a row using ResultSet methods.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCResultSetUpdate {

 public static void main(String[] args) {
  try(Connection connection = DriverManager.getConnection(
                   "jdbc:mysql://localhost:3306/netjs", "root", "admin")){
   // creating Statement
   Statement stmt = connection.createStatement(
                          ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);  
   
   // Executing Query
   ResultSet rs = stmt.executeQuery("Select * from Employee");
   System.out.println("Displaying all rows");
   // Processing Resultset
   while(rs.next()){
       System.out.println("id : " + rs.getInt("id") + " Name : " 
                               + rs.getString("name") + " Age : " + rs.getInt("age")); 
   }
   // moving to 3rd row
   rs.absolute(3);
   // updating age column for 3rd row
   rs.updateInt("age", 28);
   rs.updateRow();
   System.out.println("Displaying 3rd row");
   System.out.println("id : " + rs.getInt("id") + " Name : " 
                            + rs.getString("name") + " Age : " + rs.getInt("age"));
   
   /*** Inserting row  ***/
   // moves cursor to the insert row
   rs.moveToInsertRow(); 
     
   //rs.updateInt("id",18); //updates the first column using column name
   rs.updateString(2, "Bob"); //updates the second column using column index
   rs.updateInt("age",45);
   rs.insertRow();
   rs.moveToCurrentRow();
   
  }catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

Other fields of ResultSet interface

Some of the fields are already mentioned with examples, ResultSet in Java has some other fields which are as follows-

  • CLOSE_CURSORS_AT_COMMIT- This constant indicates that open ResultSet will be closed when the current transaction is commited.
  • HOLD_CURSORS_OVER_COMMIT- This constant indicates that open ResultSet will remain open when the current transaction is commited.
  • FETCH_FORWARD- The constant indicating that the rows in a result set will be processed in a forward direction; first-to-last.
  • FETCH_REVERSE- The constant indicating that the rows in a result set will be processed in a reverse direction; last-to-first.
  • FETCH_UNKNOWN- The constant indicating that the order in which rows in a result set will be processed is unknown.

Methods of the ResultSet

Most of the often used methods of the ResultSet are already covered with the examples. Some of the other methods which are used for moving the cursor are as follows-

  • afterLast()- Moves the cursor to the end of this ResultSet object, just after the last row.
  • beforeFirst()- Moves the cursor to the front of this ResultSet object, just before the first row.
  • first()- Moves the cursor to the first row in this ResultSet object.
  • last()- Moves the cursor to the last row in this ResultSet object.
  • moveToCurrentRow()- Moves the cursor to the remembered cursor position, usually the current row.
  • moveToInsertRow()- Moves the cursor to the insert row. The insert row is a special row associated with an updatable result set. It is essentially a buffer where a new row may be constructed by calling the updater methods prior to inserting the row into the result set.
  • next()- Moves the cursor froward one row from its current position.
  • previous()- Moves the cursor to the previous row in this ResultSet object.
  • relative(int rows)- Moves the cursor a relative number of rows, either positive or negative.

Reference: https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/ResultSet.html

That's all for this topic ResultSet Interface in Java-JDBC. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Connection Interface in Java-JDBC
  2. Statement Interface in Java-JDBC
  3. DatabaseMetaData Interface in Java-JDBC
  4. Types of JDBC Drivers
  5. Configuring DataSource in Spring Framework

You may also like-

  1. Difference Between Abstract Class And Interface in Java
  2. super Keyword in Java With Examples
  3. Try-With-Resources in Java With Examples
  4. How HashMap Works Internally in Java
  5. Difference Between CountDownLatch And CyclicBarrier in Java
  6. Java Stream API Examples
  7. Java Object Cloning - clone() Method
  8. Spring NamedParameterJdbcTemplate Select Query Example

Friday, August 23, 2024

Creating Custom Exception Class in Java

In this post we'll see how to create a custom exception in Java.

custom exception in Java

Though Java's exception handling covers the whole gamut of errors and most of the time it is recommended that you should go with standard exceptions rather than creating your own custom exception classes in Java, but you might need to create custom exception types to handle situations which are specific to your application.

Wednesday, June 19, 2024

Java Nested Class And Inner Class

In Java programming language you can define a class within another class. Such a class is known as a nested class in Java.


Nested class categories

Java Nested classes are divided into two categories-

  • Static nested classes- Nested classes that are declared static are called static nested classes.

    General form of static nested class in Java-

    class OuterClass {
      ...
      static class StaticNestedClass {
        ...
      } 
    }
    
  • Non-static nested classes- Nested classes that are not static are called Non-static nested classes. They are known better as inner classes in Java.

    General form of inner class in Java-

    class OuterClass {
      ...
      class InnerClass {
        ...
      }
    }
    

Java Static nested class example

public class NestedDemo {
 int num = 10;
 public static class Nested{
  NestedDemo nd = new NestedDemo();
  private int quantity = 10;
  void msg(){
   System.out.println("data is "+ nd.num * quantity);
  }
 }
 public static void main(String[] args) {
  NestedDemo.Nested nested = new NestedDemo.Nested();
  nested.msg();
 }
}

Output

data is 100

Benefits of using Nested Classes in Java

  1. Nested classes provide a way to logically group classes that are only used in one place.
    If a class is useful to only one other class, then it makes sense to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.
  2. It increases encapsulation. Note that a nested class has access to all the members of the outer class even private members. Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.
  3. It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.

Important points about static nested class

  1. Just like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class, it can use them only through an object reference.
  2. Static nested classes are accessed using the enclosing class name: NestedDemo.Nested
  3. Since nested class is a member of its enclosing class, a nested class can have any of the access modifiers; private, public, protected, or package private. Note that outer classes can only be declared public or package private.

Inner class in Java

An inner class is a nested class that is not static. Inner class has access to all the members (fields and methods) of the outer class including those with access modifier as private. Let’s see a simple inner class example here to make it clearer.

Java Inner class example

In this example there is a OuterClass with one private field, a method createInner() and an inner class InnerClass. Inner class has one method displayMsg() which takes String as argument.

class OuterClass {
 private int outerVar = 12;
 // Inner class
 class InnerClass{
  void displayMsg(String msg){
   System.out.println("Message is - " + msg);
   System.out.println("Outer class variable - " + outerVar);
  }
 }
 
 void createInner(){
  InnerClass ic = new InnerClass();
  ic.displayMsg("Calling From a method with in the Outer class");
 }
}

public class ICDemo {
 public static void main(String[] args) {
  OuterClass oc = new OuterClass();
  oc.createInner();
  // Creating inner class object using outer class object
  OuterClass.InnerClass oic = oc.new InnerClass();
  oic.displayMsg("Calling from outside the OuterClass scope");
 }
}

Output

Message is - Calling From a method with in the Outer class
Outer class variable - 12
Message is - Calling from outside the OuterClass scope
Outer class variable - 12

Points to note

There are several points of interest to note here about the inner classes–

  1. From the output you can see that inner class has access to fields and methods of the outer class, even if they are private. In the displayMsg() method of the inner class outerVar variable is accessed which is private and resides with in the scope of outer class.
  2. If you want to make an object of the inner class with in a non-static method of the outer class you don’t need to qualify it with Outer class name. Since createInner() method is a method of the outer class and it is not static you can create an object of the inner class directly.
  3. If you want to make an object of the inner class outside the scope of the outer class or from a method with in the outer class which is static you have to qualify inner class with the outer class so the type of the object would be specified as OuterClassName.InnerClassName. You can see example of object creation of inner class that way in the main method as it resides in another class ICDemo.
  4. An inner class can be private, public, protected or package-private. Note that normal class can only be public or package-private (default).

Types of inner classes

Apart from non-static nested class (also known as member inner class) there are two additional types of inner classes in Java.

  • Local inner class
  • Anonymous inner class

Local inner class in Java

Local inner classes are inner classes that can be defined within a block, here block means any group of zero or more statements between balanced braces. Generally you will find local inner classes defined within a method body.

Java Local inner class example

Let’s see an example of local inner class where inner class is defined in the method msg. Here Local inner class is also implementing an interface Message.

package org.prgm;
// Interface
interface Message{
 String readMsg();
}

class Outer {
 private int outerVar = 12;
 public Message msg(String str){
  // Local variable - it has to be final or
  // effectively final
  String hello = "Hello ";
  // Local Inner class
  class InnerMsg implements Message{
   
   private String msg;
   
   InnerMsg(String msg){
    this.msg = msg;
   }
   @Override
   // implementing interface method
   public String readMsg() {
    //hello = "Hi";
    System.out.println("I can read outer class variable its value is - " + outerVar );
    return hello + msg;
   }   
  }
  return new InnerMsg(str); 
 }
}
public class ICLocalDemo {

 public static void main(String[] args) {
  Outer outer = new Outer();
  Message message = outer.msg("Local Inner Class");
  String temp = message.readMsg();
  System.out.println("temp -- " + temp); 
 }
}

Output

I can read outer class variable its value is - 12
temp -- Hello Local Inner Class

Points to note

There are several points of interest in the above code so let’s go through those points and try to get a better explanation.

  1. Here inner class InnerMsg is defined with in the method msg that is why it is local inner class as it is local to the method msg.
  2. Local inner class can access members of the enclosing class, you can see that int variable outerVar is accessed with in the inner class InnnerMsg.
  3. A local class has access to local variables (variables defined inside the method body). However, a local class can only access local variables that are declared final (before Java 8).
  4. Starting in Java SE 8, local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final. In the method readMsg() if you uncomment the line- //hello = "Hi"; You will get the error “Local variable hello defined in an enclosing scope must be final or effectively final” if you are running this code in Java 8. If you are using version lesser than 8 then it will ask you to declare hello as final.
  5. In the above code one thing to note is that inner class implements an interface. Doing that you are abiding to a very important point of object oriented programming – Abstraction. If you have noticed the return type of the method msg is interface Message. That way your implementation of the inner class is completely hidden.

Anonymous inner class in Java

Anonymous inner class is a type of local inner class that has no name. You will always declare anonymous inner class as subclass or as implementation of an interface. Note that you cannot declare constructors in an anonymous class.

Java Anonymous inner class example

Let’s implement the same example as above as an anonymous inner class. There is an interface Message and that is implemented as an anonymous inner class with in the method msg.

//Interface
interface Message{
 String readMsg();
}

class MessageOuter {
 private int outerVar = 12;
 public Message msg(String str){
  // Local variable - it has to be final or
  // effectively final
  String hello = "Hello ";
  return new Message(){
   @Override
   public String readMsg() {
    //hello = "Hi";
    System.out.println("I can read outer class variable its value is - " + outerVar );
    return hello + str;
   }   
  }; // required to have semicolon
 }
}

/**
 * 
 */
public class ICAnonymousDemo {
 public static void main(String[] args) {
  MessageOuter mo = new MessageOuter();
  Message msg = mo.msg("Anonymous Inner Class");
  System.out.println("Message is - " + msg.readMsg());
 }
}

Output

I can read outer class variable its value is - 12
Message is - Hello Anonymous Inner Class

Points to note

There are several points of interest in the above code so let’s go through those points and try to get a better explanation.

  1. Here inner class with in the method msg is an anonymous inner class. It contains a new operator, name of the interface it is implementing (it can also extend a class), and class declaration body with in the braces.
  2. Because an anonymous class definition is an expression, it must be part of a statement. That is why there is a semicolon after the closing brace.
  3. Anonymous inner class can access members of the enclosing class, you can see that int variable outerVar is accessed with in the method of the anonymous inner class.
  4. Anonymous inner class has access to local variables (variables defined inside the method body). Same rules apply as in the case of local inner class.
  5. You cannot declare constructors in an anonymous class as it has no name.

That's all for this topic Java Nested Class And Inner Class. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Basics Tutorial Page


Related Topics

  1. Serialization and Deserialization in Java
  2. Java Object Cloning - clone() Method
  3. final Keyword in Java With Examples
  4. Effectively Final in Java 8
  5. Lambda Expressions in Java 8

You may also like-

  1. BigDecimal in Java With Examples
  2. Java split() Method - Splitting a String
  3. Java Program to Find The Longest Palindrome in a Given String
  4. Parallel Stream in Java Stream API
  5. Deadlock in Java Multi-Threading
  6. How to Inject Prototype Scoped Bean into a Singleton Bean in Spring
  7. Creating New Component in Angular
  8. Python First Program - Hello World

Tuesday, June 18, 2024

DatabaseMetaData Interface in Java-JDBC

DatabaseMetaData in Java, which resides in java.sql package, provides information about the database (DB meta data) you are connected to.

Using the methods provided by Java DatabaseMetaData interface you can get information about-

  • Database like DB name and version
  • JDBC driver like the driver’s name and version,
  • names of DB schemas,
  • name of tables in any DB schema,
  • names of views,
  • information about the procedures.

In this post we’ll see examples of some of the commonly used methods. You can get the list of full methods here- https://docs.oracle.com/javase/9/docs/api/java/sql/DatabaseMetaData.html


How to get DatabaseMetaData object in JDBC

You can get the DatabaseMetaData instance by calling the getMetaData() method of the Connection class.

DatabaseMetaData dbMetaData = connection.getMetaData();

DatabaseMetaData example-Getting DB product and version information

This example code shows how you can get DB name and version information using DatabaseMetaData in JDBC.

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBMetaData {

 public static void main(String[] args) {
  Connection connection = null;
   try {
    // Loading driver
    Class.forName("com.mysql.jdbc.Driver");
    
    // Creating connection
    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/netjs", 
                        "root", "admin");
    
    DatabaseMetaData dbMetaData = connection.getMetaData();
    
    System.out.println("Database Name - " + dbMetaData.getDatabaseProductName());
    System.out.println("Database Version - " + dbMetaData.getDatabaseProductVersion());
    System.out.println("Database Major Version - " + dbMetaData.getDatabaseMajorVersion());
    System.out.println("Database Minor Version - " + dbMetaData.getDatabaseMinorVersion());
    System.out.println("Database User - " + dbMetaData.getUserName());
    
   } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
   } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
   }finally{
       if(connection != null){
         //closing connection 
         try {
           connection.close();
         } catch (SQLException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
       } // if condition
   }// finally
 }
}

DatabaseMetaData example - Getting driver information

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBMetaData {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Loading driver
      Class.forName("com.mysql.jdbc.Driver");
      
      // Creating connection
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/netjs", 
                       "root", "admin");
      
      DatabaseMetaData dbMetaData = connection.getMetaData();
      
      System.out.println("Driver Name - " + dbMetaData.getDriverName());
      System.out.println("Driver Version - " + dbMetaData.getDriverVersion());
      System.out.println("Driver Major Version - " + dbMetaData.getDriverMajorVersion());
      System.out.println("Driver Minor Version - " + dbMetaData.getDriverMinorVersion());
      System.out.println("JDBC Major Version - " + dbMetaData.getJDBCMajorVersion());
      System.out.println("JDBC Minor Version - " + dbMetaData.getJDBCMinorVersion());
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
   }finally{
      if(connection != null){
        //closing connection 
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      } // if condition
    }// finally
  }
}

Example to get tables using DatabaseMetaData in JDBC

For getting tables you can use getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) method. You can provide null as value for all the parameters, that way you don’t narrow the search and all the tables are returned. If you want to narrow your search to get specific tables then you can provide values for these parameters.

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBMetaData {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Loading driver
      Class.forName("com.mysql.jdbc.Driver");
    
      // Creating connection
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/world", 
                        "root", "admin");
    
      DatabaseMetaData dbMetaData = connection.getMetaData();
      
      ResultSet rs = dbMetaData.getTables(null, null, null, null);
      while (rs.next()){
        System.out.println("Table name " + rs.getString(3));
      }
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally{
      if(connection != null){
        //closing connection 
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      } // if condition
    }// finally
  }
}

Output

Table name city
Table name country
Table name countrylanguage

Here I am connecting to “world” schema in MySQL and getting all the tables.

Each table description in the returned ResultSet has the following columns:

Table Description Columns
Column Name Type Description
TABLE_CAT String table catalog (may be null)
TABLE_SCHEM String table schema (may be null)
TABLE_NAME String table name
TABLE_TYPE String table type. Typical types are "TABLE", "VIEW" etc.
REMARKS String explanatory comment on the table (may be null)
TYPE_CAT String the types catalog (may be null)
TYPE_SCHEM String the types schema (may be null)
TYPE_NAME String type name (may be null)
SELF_REFERENCING_COL_NAME String name of the designated "identifier" column of a typed table (may be null)
REF_GENERATION String specifies how values in SELF_REFERENCING_COL_NAME are created.

That’s why column index is 3 while getting result from ResultSet as TABLE_NAME is at number 3.

Example to get Procedures using DatabaseMetaData in JDBC

For getting procedures you can use getProcedures(String catalog, String schemaPattern, String procedureNamePattern) method. Again you can pass null as value for all the parameters if you don’t want to narrow the search.

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBMetaData {

 public static void main(String[] args) {
  Connection connection = null;
   try {
    // Loading driver
    Class.forName("com.mysql.jdbc.Driver");
    
    // Creating connection
    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/netjs", 
                        "root", "admin");
    
    DatabaseMetaData dbMetaData = connection.getMetaData();
    
    ResultSet rs = dbMetaData.getProcedures(null, null, null);
    
    while (rs.next()){
     System.out.println("Procedure name " + rs.getString(3));
    }
    
   } catch (ClassNotFoundException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
   } catch (SQLException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
   }finally{
       if(connection != null){
          //closing connection 
          try {
            connection.close();
          } catch (SQLException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
          }
       } // if condition
   }// finally
 }
}

Each procedure description in the returned ResultSet has the following columns:

Procedure Description Columns
Column Name Type Description
PROCEDURE_CAT String procedure catalog (may be null)
PROCEDURE_SCHEM String procedure schema (may be null)
PROCEDURE_NAME String procedure name
reserved for future use
reserved for future use
reserved for future use
REMARKS String explanatory comment on the procedure
PROCEDURE_TYPE short type name (may be null)
SPECIFIC_NAME String The name which uniquely identifies this procedure within its schema.

That’s why column index is 3 while getting result from ResultSet as PROCEDURE_NAME is at number 3.

That's all for this topic DatabaseMetaData Interface in Java-JDBC. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. DataSource in Java-JDBC
  2. Java JDBC Steps to Connect to DB
  3. Statement Interface in Java-JDBC
  4. ResultSet Interface in Java-JDBC
  5. Data access in Spring framework

You may also like-

  1. How LinkedList Class Works Internally in Java
  2. Difference Between HashMap And ConcurrentHashMap in Java
  3. Java ReentrantReadWriteLock With Examples
  4. Livelock in Java Multi-Threading
  5. Enum Type in Java
  6. interface static methods in Java 8
  7. Arrange Non-Negative Integers to Form Largest Number - Java Program
  8. Print Odd-Even Numbers Using Threads And wait-notify Java Program

Wednesday, June 12, 2024

Java JDBC Steps to Connect to Database

JDBC API provides a set of interfaces and classes for performing the following tasks-

  • Connecting to database
  • Creating SQL statement
  • Executing created SQL statement in database
  • Returning the results
  • Processing that ResultSet

Steps for connecting any Java application to DB and fetching results using JDBC can be summarized as follows

  • Registering driver class
  • Creating connection to DB
  • Creating Statement
  • Executing Query
  • Processing ResultSet
  • Closing connection

Interfaces provided by JDBC for these steps are-

  1. Driver (That is the interface implemented by the database vendors to provide a JDBC driver for specific databases)
  2. Connection
  3. Statement
  4. ResultSet

Steps for connecting to Database using JDBC

Steps for connecting to Database using JDBC are explained here along with examples to connect to differenct DBs like Oracle, MySql, DB2.

1. Registering driver class

First thing you need to do is to register JDBC driver for the DB you are connecting to. You can use forName() method provided by class Class to load the JDBC driver in order to register it.

General form using Class.forName()

class.forName(“JDBC Driver Class”);

Using registerDriver() method

You can also use registerDriver() method provided by DriverManager class to load the appropriate driver. Note that it is a static method.

General form using registerDriver() method

DriverManager.registerDriver(Driver class object);

Driver classes for some of the databases are as follows -

  • MySql– com.mysql.jdbc.Driver (You need to download MySQL Connector/J jar mysql-connector-java-5.1.39.jar (Please check for the latest version) which will have the JDBC driver).
  • Oracle– oracle.jdbc.driver.OracleDriver (You need to download ojdbc8.jar or higher version for Java 8 and JDBC 4.2).
  • DB2– com.ibm.db2.jcc.DB2Driver (You need to download db2jcc.jar for the DB2 JDBC driver).

Loading Oracle driver using Class.forName() method-

Class.forName(“oracle.jdbc.driver.OracleDriver”);

JVM automatically loads the classes that are used in the program. Since the driver class is not explicitly used in the program that’s why JVM won’t load it automatically. That is the reason you need to load driver class using class.forName() that way you explicitly tell JVM to load this driver class.

Loading MySql driver using resgisterDriver method-

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

If you are using JDBC 4.x (Version Java 6 or higher) then actually you don’t need to explicitly load the JDBC driver. As Automatic loading of JDBC drivers is supported from JDBC 4 you just need to have the appropriate jar in the class path. So loading driver step is optional from Java 6 onwards make sure that automatic loading is supported by the driver you are using.

2. Creating connection object

Once you have registered the driver, second step is to open a connection to the DB. For that you can use the static method getConnection() of the java.sql.DriverManager class.

General form of getConnection method

DriverManager.getConnection(DB_URL, DBuser, password)

URL Pattern for some of the databases

  • Oracle– jdbc:oracle:<drivertype>:@<database>

    As example- Connecting user scott with password tiger to a database with SID orcl through port 1521 of host myhost, using the Thin driver.

    Connection connection = DriverManager.getConnection
         ("jdbc:oracle:thin:@myhost:1521:orcl", "scott", "tiger");
    
  • MySQL– jdbc:mysql://hostname:portnumber/dbName

    As example- Connecting user root with password admin to a database test through port 3306 of host localhost.

    Connection connection = DriverManager.getConnection
         ("jdbc:mysql://localhost:3306/test", "root", "admin");
    
  • DB2– jdbc:db2://hostname:portnumber/dbName

    As example- Connecting user dbadmin with password dbadmin to a database mydb through port 5021 of host myhost.

    Connection connection = DriverManager.getConnection
         ("jdbc:db2://myhost:5021/mydb","dbadmin","dbadmin");
    

3. Creating Statement object

Once Connection object is created that can be used to create a Statement object. This object is needed for specifying the SQL statement that has to be executed by the DB.

Statement statement = connection.createStatement();

4. Executing Query

To execute a query you need to call execute() method of the Statement class.

You can call executeUpdate(String sql) method for INSERT, DELETE, UPDATE or DDL (Data Definition Language) SQL statements. This method returns an integer representing the number of rows affected by the SQL statement so you will know how many rows are inserted, deleted or updated.

You can call executeQuery(String SQL) method for SELECT sql queries. This method returns a ResultSet.

As example-

  1. To create a table employee
    statement.executeUpdate(“CREATE TABLE employee (id int(11), name varchar(35), age int(11))”);
    
  2. To get data for all employees
    ResultSet rs = statement.executeQuery("Select * from Employee"); 
    

5. Processing ResultSet

Once the query is executed and you have the ResultSet you access the data in a ResultSet object through a cursor. This cursor is a pointer that points to one row of data in the ResultSet object. Initially, the cursor is positioned before the first row. You can use next method to move to the next row of the ResultSet. There are various getter methods based on data type to get the value of the current row.

As example-

If you want to iterate the ResultSet returned from the above query for getting all the employees.

while(rs.next()){
 System.out.println("id : " + rs.getInt("id") + " Name : " + rs.getString("name") + " Age : " + rs.getInt("age"));
}

In the example getter method are using the column labels to retrieve the values you can also use the column indexes to get the values, index starts from 1.

while(rs.next()){
 System.out.println("id : " + rs.getInt(1) + " Name : " + rs.getString(2) + " Age : " + rs.getInt(3));
}

6. Closing the connection

Once you have the processed the ResultSet you can close the connection.

connection.close();

It’s better to close an opened connection in a finally block. That ensures that the connection is closed even if there is an exception in the code.

JDBC Connection example

Let’s put all these steps together in a Java example program connecting to MySQL DB using JDBC. DB schema is netjs and table is Employee.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCCon {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Loading driver
      Class.forName("com.mysql.jdbc.Driver");
      // Another way
      //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
   
      // Creating connection
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/netjs", 
                   "root", "admin");
      // creating Statement
      Statement stmt = connection.createStatement();  
   
      // Executing Query
      ResultSet rs = stmt.executeQuery("Select * from Employee");

      // Processing Resultset
      while(rs.next()){
         System.out.println("id : " + rs.getInt("id") + " Name : " 
          + rs.getString("name") + " Age : " + rs.getInt("age")); 
      }
    
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SQLException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
    }finally{
      if(connection != null){
         //closing connection 
         try {
           connection.close();
         } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         }
      }
    }
  }
}

You can put DB credential information in a properties file and read it from there. Refer How to read Properties file in Java to see how to read properties file in Java.

JDBC Connection to DB using try-with-resources

If you are using Java 7 or above, you can use a try-with-resources statement, when connecting to DB using JDBC, to automatically close Connection, Statement, and ResultSet objects, regardless of whether an SQLException has been thrown.

If we modify the above code to include try-with-resources then we can get rid of finally block used to close the connection.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCCon {
  public static void main(String[] args) {
    try(Connection connection = DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/netjs", "root", "admin"))
    {
      // creating Statement
      Statement stmt = connection.createStatement();  

      // Executing Query
      ResultSet rs = stmt.executeQuery("Select * from Employee");
     
      // Processing Resultset
      while(rs.next()){
         System.out.println("id : " + rs.getInt("id") + " Name : " 
               + rs.getString("name") + " Age : " + rs.getInt("age")); 
      }
    }catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

Note that Class.forName("com.mysql.jdbc.Driver"); statement is excluded as that is also optional, from JDBC 4.0 drivers which are in the class path are automatically loaded.

That's all for this topic Java JDBC Steps to Connect to DB. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Java JDBC overview - JDBC Tutorial
  2. Types of JDBC Drivers
  3. PreparedStatement Interface in Java-JDBC
  4. DataSource in Java-JDBC
  5. Spring JdbcTemplate Insert, Update And Delete Example

You may also like-

  1. How to Remove Duplicate Elements From an ArrayList in Java
  2. ConcurrentHashMap in Java With Examples
  3. Lambda Expressions in Java 8
  4. Transient Keyword in Java With Examples
  5. Spring NamedParameterJdbcTemplate Select Query Example
  6. Race Condition in Java Multi-Threading
  7. Angular Template-Driven Form Validation Example
  8. Node.js Event Driven Architecture

Monday, June 10, 2024

JDBC Tutorial - Java JDBC Overview

This JDBC tutorial gives an overview of JDBC which is the Java API for developing Java applications that access relational databases.

Why use JDBC

JDBC provides developers with a uniform interface to connect with different relational databases like Oracle, MySQL, DB2, Access etc.

JDBC provides a set of interfaces and classes that standardize the interaction with different databases and abstracts you as a developer with the inner working of the proprietary databases. You just need to know the standard JDBC steps to connect to database, query it in order to fetch results or update DB. Note here that the SQL may differ according to the DB used.

JDBC Drivers

In Order to connect to database JDBC uses JDBC drivers. Since JDBC driver acts as a connector between JDBC and proprietary databases JDBC drivers are DB specific and generally provided by the DB vendor itself.

As example– In order to connect to MySql DB you will need a MySql JDBC connector driver which is bundled in the mysql-connector-javaXXX.jar.

The interaction of JDBC with the database using JDBC driver can be pictorially represented as follows-

JDBC Drivers

Packages in JDBC API

The JDBC API is comprised of two packages:

  • java.sql- Referred to as the JDBC core API
  • javax.sql- Referred to as the JDBC Optional Package API

You automatically get both packages when you download the Java Platform Standard Edition (Java SE).

Changes in JDBC 4.x

The current version of JDBC which comes bundled with Java is JDBC 4.3. There are some noticeable changes in the 4.x versions like-

  1. Addition of the java.sql.SQLType Interface
  2. Addition of the java.sql.JDBCType Enum– Using SQLType interface and JDBCType Enum you can identify the generic SQL types like CLOB, REF_CURSOR, TINYINT, VARCHAR etc.
  3. You can use try-with-resources statement to automatically close resources of type Connection, ResultSet, and Statement.
  4. Automatic loading of JDBC drivers on the class path.

Steps for connecting to DB using JDBC

JDBC API provides a set of interfaces and classes for connecting to DB, creating SQL statement, executing created SQL statement in database, returning the results and processing that ResultSet.

These steps can be summarized as follows-

  • Loading driver
  • Creating connection to DB
  • Creating Statement
  • Executing Query
  • Processing ResultSet
  • Closing connection

Refer Java JDBC Steps to Connect to DB to see these steps in details and a JDBC example Java program.

A pictorial representation of these steps can be represented as follows.

JDBC DB connection steps

That's all for this topic JDBC Tutorial - Java JDBC Overview. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Connection Interface in Java-JDBC
  2. Statement Interface in Java-JDBC
  3. Transaction in Java-JDBC
  4. DataSource in Java-JDBC
  5. Data access in Spring framework

You may also like-

  1. Interface Default Methods in Java 8
  2. PermGen Space Removal in Java 8
  3. How ArrayList Works Internally in Java
  4. Difference Between CountDownLatch And CyclicBarrier in Java
  5. Java Object Cloning - clone() Method
  6. Spring NamedParameterJdbcTemplate Insert, Update And Delete Example
  7. Arrange Non-Negative Integers to Form Largest Number - Java Program
  8. Best Practices For Exception Handling in Java

Sunday, June 9, 2024

Connection Interface in Java-JDBC

In the post Java JDBC Steps to Connect to DB we have already seen a complete example using the interfaces Driver, Connection, Statement and ResultSet provided by the JDBC API. In this post we’ll see Java Connection interface in detail.

Connection interface in JDBC

Connection interface resides in java.sql package and it represents a session with a specific database you are connecting to. SQL statements that you want to execute, results that are returned all that happens with in the context of a connection.

You can get a Connection object by using the getConnection() method of the DriverManager class.

Using Connection class object-

  • You can get an object of Statement.
  • You can get the information about the database (DatabaseMetaData) it is connecting to.
  • Connection also provides method for transaction management like commit(), rollback().

Fields in the Connection interface

Connection interface provides a set of fields for specifying transaction isolation level-

  • TRANSACTION_NONE- A constant indicating that transactions are not supported.
  • TRANSACTION_READ_COMMITTED- A constant indicating that dirty reads are prevented; non-repeatable reads and phantom reads can occur.
  • TRANSACTION_READ_UNCOMMITTED- A constant indicating that dirty reads, non-repeatable reads and phantom reads can occur.
  • TRANSACTION_REPEATABLE_READ- A constant indicating that dirty reads and non-repeatable reads are prevented; phantom reads can occur.
  • TRANSACTION_SERIALIZABLE- A constant indicating that dirty reads, non-repeatable reads and phantom reads are prevented.

Frequently used methods of the Connection

Some of the frequently used methods of the Connection are as follows-

For creating statement

There are also overloaded variant of these methods where you can specify the type of ResultSet and its concurrency level.

For getting information about the DB

  • getMetaData()- Returns a DatabaseMetaData object containing metadata about the connected database.

See example of using DatabaseMetaData here- DatabaseMetaData Interface in Java-JDBC.

For transaction management

  • setAutoCommit(boolean autoCommit)- Sets this connection's commit mode to true or false.
  • setTransactionIsolation(int level)- Attempts to changes the transaction isolation level for this Connection object to the one given.
  • rollback()- Undoes all changes made in the current transaction and releases any database locks currently held by this Connection object.
  • commit()- Makes all changes made since the previous commit/rollback permanent and releases any database locks currently held by this Connection object.

See details of Transaction management using JDBC here- Transaction in Java-JDBC.

Reference: https://docs.oracle.com/en/java/javase/12/docs/api/java.sql/java/sql/Connection.html

That's all for this topic Connection Interface in Java-JDBC. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. Java JDBC overview - JDBC Tutorial
  2. CallableStatement Interface in Java-JDBC
  3. Transaction Management in Java-JDBC
  4. DataSource in Java-JDBC
  5. Data Access in Spring Framework

You may also like-

  1. Java Program to Get All DB Schemas
  2. final Vs finally Vs finalize in Java
  3. How to create immutable class in Java
  4. BigDecimal in Java With Examples
  5. Heap Memory Allocation in Java
  6. Reflection in Java - Class
  7. Serialization Proxy Pattern in Java
  8. Spring JdbcTemplate Select Query Example

Tuesday, April 30, 2024

Pre-defined Functional Interfaces in Java

We saw in the post Functional Interfaces in Java how you can create your own functional interface and also annotate it using @FunctionalInterface Annotation. Though it is not always required that you have to create your own functional interface for each scenario, Java has introduced a new package java.util.function that defines many general purpose pre-defined functional interfaces used by many Java libraries like Collection framework, Java Stream API and used by user code as well. In this post we’ll go through these built-in functional interfaces in Java so you have a good idea which functional interface to use in which context while using with Lambda expressions in Java.


Pre-defined functional interfaces categorization

Functional interfaces defined in java.util.function package can be categorized into five types-

  1. Consumer- Consumes the passed argument and no value is returned.
  2. Supplier- Takes no argument and supplies a result.
  3. Function- Takes argument and returns a result.
  4. Predicate- Takes argument and returns a boolean result (true or false).
  5. Operators- Functional interfaces categorized under Operator are specialized Function where the passed argument and result are of the same type.

Consumer functional interface

Consumer<T> represents a function that accepts a single input argument and returns no result. Consumer functional interface definition is as given below consisting of an abstract method accept() and a default method andThen()-

@FunctionalInterface
public interface Consumer<T> {
  void accept(T t);
  default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
  }
}

Following pre-defined Consumer functional interfaces are categorized as Consumer as all of these interfaces have the same behavior of consuming the passed value(s) and returning no result. You can use any of these based on number of arguments or data type.

  • BiConsumer<T,U>- Represents an operation that accepts two input arguments and returns no result.
  • DoubleConsumer- Represents an operation that accepts a single double-valued argument and returns no result.
  • IntConsumer- Represents an operation that accepts a single int-valued argument and returns no result.
  • LongConsumer- Represents an operation that accepts a single long-valued argument and returns no result.
  • ObjDoubleConsumer<T>- Represents an operation that accepts an object-valued and a double-valued argument, and returns no result.
  • ObjIntConsumer<T>- Represents an operation that accepts an object-valued and a int-valued argument, and returns no result.
  • ObjLongConsumer<T>- Represents an operation that accepts an object-valued and a long-valued argument, and returns no result.

Consumer functional interface Java example

In the example elements of List are displayed by using an implementation of Consumer functional interface.

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class ConsumerExample {
  public static void main(String[] args) {
    Consumer<String> consumer = s -> System.out.println(s);
    List<String> alphaList = Arrays.asList("A", "B", "C", "D");
    for(String str : alphaList) {
      // functional interface accept() method called
      consumer.accept(str);
    }
  }
}

Output

A
B
C
D

Supplier functional interface

Supplier<T> represents a function that doesn't take argument and supplies a result. Supplier functional interface definition is as given below consisting of an abstract method get()-

@FunctionalInterface
public interface Supplier<T> {
  T get();
}

Following pre-defined Supplier functional interfaces are categorized as Supplier as all of these interfaces have the same behavior of supplying a result.

  • BooleanSupplier- Represents a supplier of boolean-valued results.
  • DoubleSupplier- Represents a supplier of double-valued results.
  • IntSupplier- Represents a supplier of int-valued results.
  • LongSupplier- Represents a supplier of long-valued results.

Supplier functional interface Java example

In the example Supplier functional interface is implemented as a lambda expression to supply current date and time.

import java.time.LocalDateTime;
import java.util.function.Supplier;

public class SupplierExample {
  public static void main(String[] args) {
    Supplier<LocalDateTime> currDateTime = () -> LocalDateTime.now();
    System.out.println(currDateTime.get());
  }
}

Function functional interface

Function<T,R> represents a function that accepts one argument and produces a result. Function functional interface definition is as given below consisting of an abstract method apply(), two default methods compose(), andThen() and a static method identity().

@FunctionalInterface
public interface Function<T, R> {

  R apply(T t);

  default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
  }

  default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
  }
  static <T> Function<T, T> identity() {
    return t -> t;
  }
}

Following pre-defined Function functional interfaces are categorized as Function as all of these interfaces have the same behavior of accepting argument(s) and producing a result.

  • BiFunction<T,U,R>- Represents a function that accepts two arguments and produces a result.
  • DoubleFunction<R>- Represents a function that accepts a double-valued argument and produces a result.
  • DoubleToIntFunction- Represents a function that accepts a double-valued argument and produces an int-valued result.
  • DoubleToLongFunction- Represents a function that accepts a double-valued argument and produces a long-valued result.
  • IntFunction<R>- Represents a function that accepts an int-valued argument and produces a result.
  • IntToDoubleFunction- Represents a function that accepts an int-valued argument and produces a double-valued result.
  • IntToLongFunction- Represents a function that accepts an int-valued argument and produces a long-valued result.
  • LongFunction<R>- Represents a function that accepts a long-valued argument and produces a result.
  • LongToDoubleFunction- Represents a function that accepts a long-valued argument and produces a double-valued result.
  • LongToIntFunction- Represents a function that accepts a long-valued argument and produces an int-valued result.
  • ToDoubleBiFunction<T,U>- Represents a function that accepts two arguments and produces a double-valued result.
  • ToDoubleFunction<T>- Represents a function that produces a double-valued result.
  • ToIntBiFunction<T,U>- Represents a function that accepts two arguments and produces an int-valued result.
  • ToIntFunction<T>- Represents a function that produces an int-valued result.
  • ToLongBiFunction<T,U>- Represents a function that accepts two arguments and produces a long-valued result.
  • ToLongFunction<T>- Represents a function that produces a long-valued result.

Function functional interface Java example

In the example a Function interface is implemented to return the length of the passed String.

import java.util.function.Function;

public class FunctionExample {
  public static void main(String[] args) {
    Function<String, Integer> function = (s) -> s.length();
    System.out.println("Length of String- " + function.apply("Interface"));
  }
}

Output

Length of String- 9

Predicate functional interface

Predicate<T> represents a function that accepts one argument and produces a boolean result. Abstract method in the Predicate functional interface is boolean test(T t).

Following pre-defined Predicate functional interfaces are categorized as Predicate as all of these interfaces have the same behavior of accepting argument(s) and producing a boolean result.

  • BiPredicate<T,U>- Represents a predicate (boolean-valued function) of two arguments.
  • DoublePredicate- Represents a predicate (boolean-valued function) of one double-valued argument.
  • IntPredicate- Represents a predicate (boolean-valued function) of one int-valued argument.
  • LongPredicate- Represents a predicate (boolean-valued function) of one long-valued argument.

Predicate functional interface Java Example

In the example a number is passed and true is returned if number is even otherwise odd is retuned.

import java.util.function.Predicate;

public class PredicateExample {
  public static void main(String[] args) {
    Predicate<Integer> predicate = (n) -> n%2 == 0;
    boolean val = predicate.test(6);
    System.out.println("Is Even- " + val);    
    System.out.println("Is Even- " + predicate.test(11));
  }
}

Output

Is Even- true
Is Even- false

Operator functional interfaces

Operator functional interfaces are specialized Function interfaces that always return the value of same type as the passed arguments. Operator functional interfaces extend their Function interface counterpart like UnaryOperator extends Function and BinaryOperator extends BiFunction.

Following pre-defined Operator functional interfaces are there that can be used in place of Function interfaces if returned value is same as the type of the passed argument(s).

  • BinaryOperator<T>- Represents an operation upon two operands of the same type, producing a result of the same type as the operands.
  • DoubleBinaryOperator- Represents an operation upon two double-valued operands and producing a double-valued result.
  • DoubleUnaryOperator- Represents an operation on a single double-valued operand that produces a double-valued result.
  • IntBinaryOperator- Represents an operation upon two int-valued operands and producing an int-valued result.
  • IntUnaryOperator- Represents an operation on a single int-valued operand that produces an int-valued result.
  • LongBinaryOperator- Represents an operation upon two long-valued operands and producing a long-valued result.
  • LongUnaryOperator- Represents an operation on a single long-valued operand that produces a long-valued result.
  • UnaryOperator<T>- Represents an operation on a single operand that produces a result of the same type as its operand.

UnaryOperator functional interface Java example

In the example UnaryOperator is implemented to return the square of the passed integer.

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {
  public static void main(String[] args) {
    UnaryOperator<Integer> unaryOperator = (n) -> n*n;
    System.out.println("4 squared is- " + unaryOperator.apply(4));
    System.out.println("7 squared is- " + unaryOperator.apply(7));
  }
}

Output

4 squared is- 16
7 squared is- 49

That's all for this topic Pre-defined Functional Interfaces in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Exception Handling in Java Lambda Expressions
  2. Method Reference in Java
  3. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  4. Java Stream API Tutorial
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. Java Stream flatMap() Method
  2. Java Lambda Expression Callable Example
  3. Invoke Method at Runtime Using Java Reflection API
  4. LinkedHashMap in Java With Examples
  5. java.lang.ClassCastException - Resolving ClassCastException in Java
  6. Java String Search Using indexOf(), lastIndexOf() And contains() Methods
  7. BeanFactoryAware Interface in Spring Framework
  8. Angular Two-Way Data Binding With Examples