Java Unit - 1
Java Unit - 1
Definition
Java Database Connectivity (JDBC) is an Application Programming Interface (API) in Java
that allows applications to communicate with relational databases. JDBC acts as a bridge
between Java applications and database management systems (DBMS), enabling developers
to perform operations such as inserting, retrieving, updating, and deleting (CRUD
operations) data from databases using SQL queries.
JDBC provides a standardized way to interact with databases, ensuring that Java applications
remain portable across different database systems without significant modifications.
Purpose of JDBC
JDBC (Java Database Connectivity) is a standard Java API that enables Java applications to
interact with relational databases. It provides a uniform interface for accessing different
databases, allowing developers to write database-independent applications.
The primary purpose of JDBC is to establish a connection between Java programs and
databases, execute SQL statements, and retrieve and manipulate data stored in databases.
JDBC eliminates the need for database-specific coding by providing a common set of interfaces
and classes.
JDBC ensures portability, scalability, and maintainability of Java applications by allowing the
same Java code to work with multiple databases by simply changing the JDBC driver.
Objectives of JDBC
● To provide a standard API for database access in Java
● To enable database-independent application development
● To execute SQL queries and updates from Java programs
● To manage database connections efficiently
● To retrieve and process query results in Java applications
JDBC Architecture
JDBC architecture follows a layered approach that separates Java applications from
database-specific implementations. It consists of multiple components that work together to
enable database communication.
1. Java Application
The Java application represents the client program that requires access to the database. It uses
JDBC API classes and interfaces to interact with the database.
2. JDBC API
The JDBC API provides a set of standard interfaces and classes defined in the [Link] and
[Link] packages. These interfaces allow Java applications to perform database
operations such as establishing connections, executing SQL statements, and processing
results.
● Driver
● Connection
● Statement
● PreparedStatement
● CallableStatement
● ResultSet
3. DriverManager
DriverManager is responsible for managing JDBC drivers. It selects the appropriate driver based
on the database URL and establishes a connection between the Java application and the
database.
4. JDBC Driver
A JDBC driver is a vendor-specific implementation that converts JDBC method calls into
database-specific requests. It acts as a communication link between the Java application and
the database.
5. Database
The database is the backend system where data is stored. It executes SQL queries received
from the JDBC driver and returns results to the Java application.
● Database independence
● Platform independence
● Ease of maintenance
● Secure and efficient database access
● Supports enterprise-level applications
JDBC Drivers
JDBC Drivers are software components that allow Java applications to connect to databases.
They act as a bridge between a Java application and a database management system
(DBMS) by converting Java calls into database-specific operations.
Each database (MySQL, PostgreSQL, Oracle, SQL Server, etc.) requires a compatible JDBC
driver to communicate with it. JDBC drivers differ in how they handle this communication, which
leads to different performance levels and use cases.
There are four types of JDBC drivers, each with its own advantages and limitations.
How It Works
● The Java application sends a database request to the JDBC-ODBC Bridge Driver.
● The bridge translates the request into an ODBC call.
● The ODBC driver communicates with the database and retrieves the requested data.
● The data is then sent back to the Java application.
Characteristics
import [Link];
import [Link];
try {
[Link]("[Link]"); //
Load JDBC-ODBC Driver
Connection con =
[Link]("jdbc:odbc:myDSN", "user",
"password");
[Link]();
} catch (Exception e) {
[Link]();
⚠ This code will not work in Java 8+ because the JDBC-ODBC Bridge has been removed.
2. Native API Driver (Type 2)
The Native API Driver interacts with the database using database vendor-specific native
libraries. It does not require an ODBC driver but depends on the database’s native client
software to function.
How It Works
Characteristics
import [Link];
import [Link];
try {
[Link]("[Link]"); //
Oracle Native Driver
Connection con =
[Link]("jdbc:oracle:oci8:@localhost:1521:xe
", "user", "password");
[Link]("Connected using Type 2 Driver");
[Link]();
} catch (Exception e) {
[Link]();
📌 Requires Oracle’s native OCI (Oracle Call Interface) libraries installed on the system.
How It Works
Characteristics
Middleware solutions like IBM WebSphere and Sybase use Type 3 drivers.
import [Link];
import [Link];
try {
Connection con =
[Link]("jdbc:net://middleware-server:1
521/mydb", "user", "password");
[Link]();
} catch (Exception e) {
[Link]();
📌 Rarely used today because Type 4 drivers provide better performance without middleware.
How It Works
Characteristics
import [Link];
try {
[Link]("[Link]"); // MySQL
Thin Driver
Connection con =
[Link]("jdbc:mysql://localhost:3306/my
db", "root", "password");
[Link]();
} catch (Exception e) {
[Link]();
📌 Most modern databases provide Type 4 JDBC drivers, such as PostgreSQL, MySQL,
Oracle, and SQL Server.
The JDBC driver acts as a communication link between the Java application and the database.
Loading the driver registers it with the DriverManager.
This step ensures that the appropriate database driver is available to establish a connection.
A connection represents a session between the Java application and the database.
The DriverManager class is used to create this connection using database URL, username,
and password.
Once the connection is established, the Java application can send SQL commands to the
database.
Step 3: Create a Statement Object
When a SELECT query is executed, the database returns data in the form of a ResultSet.
The ResultSet object stores the result of the query and allows the application to read data row
by row.
After completing database operations, all resources such as ResultSet, Statement, and
Connection must be closed to avoid memory leaks.
DriverManager
DriverManager is a class that manages a list of database drivers.
It selects the appropriate driver based on the database URL and establishes a connection
between the Java application and the database.
Functions of DriverManager:
Statement
The Statement interface is used to execute simple SQL statements without parameters.
Characteristics:
PreparedStatement
PreparedStatement is a subinterface of Statement used for executing parameterized SQL
queries.
Characteristics:
PreparedStatement is preferred when the same query is executed multiple times with different
values.
ResultSet
ResultSet is an object that holds the data returned by a SELECT query.
It acts like a table of data that can be traversed row by row.
Features of ResultSet:
[Link](“id”);
while ([Link]()) {
[Link]("ID: " + [Link]("id") + ",
Name: " + [Link]("name") + ", Age: " + [Link]("age"));
}
[Link]();
} catch (Exception e) {
[Link]();
}
}
}
Non-Conventional Database
Non-conventional databases, also known as NoSQL databases, are different from traditional
relational databases (like MySQL, Oracle, PostgreSQL). Instead of storing data in tables with
rows and columns,they use different data storage techniques such as document-based,
key-value, column-family, or graph-based models.
JDBC (Java Database Connectivity) cannot be used directly with these databases. Instead,
Java provides custom drivers and APIs for connecting to them.
Handling Big Data Excellent for storing and querying massive datasets.
Introduction to MongoDB
MongoDB is a NoSQL database that stores data in JSON-like documents (BSON format). It is
used for applications that require scalability and flexibility. A typical MongoDB document
looks like this:
{
"_id": "12345",
"name": "Ummed Singh",
"email": "Ummed@[Link]",
"age": 24
}
MongoDB collections are like tables, and documents are like rows, but there is no strict schema.
🔹 Structure
● Database → contains collections
● Collection → contains documents
● Document → stores the actual data (like a row in SQL)
Collections Framework
Java Collections Framework
The Java Collections Framework is a unified architecture that provides a set of interfaces and
classes for storing and manipulating groups of data using various data structures and
algorithms.
For example, the LinkedList class in this framework implements a doubly-linked list data
structure, allowing efficient insertion and removal of elements.
Core Components
The framework includes a variety of interfaces, such as List, Set, Queue, and Map. These
interfaces define common operations that can be performed on collections, like adding,
removing, or accessing elements.
● We do not have to write code to implement these data structures and algorithms
manually.
● Our code will be much more efficient as the collections framework is highly optimized.
Moreover, the collections framework allows us to use a specific data structure for a particular
type of data. Here are a few examples,
● If we want our data to be unique, then we can use the Set interface provided by the
collections framework.
● To store data in key/value pairs, we can use the Map interface.
● The ArrayList class provides the functionality of resizable arrays.
The Collection interface is the root interface in the Java Collections Framework hierarchy. It
defines the basic operations that can be performed on a group of elements.
Java does not directly provide implementations of the Collection interface itself. Instead, it
offers implementations for its subinterfaces, such as List, Set, and Queue, which define
more specific behaviors for different types of collections.
Collections Framework vs. Collection Interface
The Collections Framework is a comprehensive set of interfaces and classes in Java used to
store, manage, and manipulate groups of objects efficiently.
Within this framework, the Collection interface serves as the root interface for most
collection types, such as List, Set, and Queue.
However, the framework also includes other important interfaces that are not part of the
Collection hierarchy, such as:
The Collection interface has several subinterfaces, each designed for specific types of data
handling. These subinterfaces inherit all the methods defined in the Collection interface and
may also introduce additional features tailored to their specific use.
1. List Interface
The List interface represents an ordered collection of elements, similar to an array. It allows
elements to be added, accessed, or removed by index, and it supports duplicate elements.
Since List is an interface, you cannot create objects directly from it. Instead, Java provides
several concrete classes that implement the List interface and offer its functionalities.
Here are the main classes that implement the List interface:
● ArrayList
● LinkedList
● Stack
● Vector
These classes are part of the Java Collections Framework and each has its own way of
storing and managing elements, while still following the behavior defined by the List interface.
How to Use the List Interface in Java
To use the List interface in Java, you need to import it from the [Link] package.
Example:
[Link](10);
[Link](20);
[Link](50);
[Link](20);
[Link](30);
[Link]([Link](1));
[Link]([Link]());
[Link]([Link](0));
[Link]([Link](0));
[Link]([Link]());
The List interface inherits all the methods from the Collection interface, as Collection is a
superinterface of List.
In addition to the methods provided by the Collection interface, the List interface also includes
methods that are specific to handling ordered collections and managing elements by index.
Some of the commonly used methods from the Collection interface, which are also available in
the List interface, include:
Methods Description
iterator() returns iterator object that can be used to sequentially access elements of
lists
clear() removes all the elements from the list (more efficient than removeAll())
In Java, when using an array, you must specify its size at the time of declaration. Once the size
is set, it cannot be changed.
However, this can be limiting if the number of elements is unknown or changes frequently. To
solve this problem, Java provides the ArrayList class, which allows for resizable arrays.
Unlike arrays, ArrayList can automatically adjust its capacity when elements are added or
removed. This makes ArrayList a dynamic array, offering more flexibility and ease of use in
scenarios where the size of the collection may change over time.
Example
class CustomArrayList<E>{ // Ummed Singh
private static final int DEFAULT_CAPACITY = 2;
private Object[] elements;
private int size = 0;
public CustomArrayList(){
elements = new Object[DEFAULT_CAPACITY];
}
public void add(E ele){
ensureCapacity();
elements[size] = ele;
size++;
}
public E get(int index){
checkIndex(index);
return (E) elements[index];
}
// {10, 20, 30, 40}; -> {10, 30, 40, 40} -> {10, 20, 30,
null} size--;
public void remove(int index){
checkIndex(index);
for (int i = index; i<size -1; i++){
elements[i] = elements[i+1];
}
elements[size-1] = null;
size--;
}
void ensureCapacity(){
if(size == [Link]){
int newCapacity = [Link] + ([Link]
/2);
elements = [Link](elements, newCapacity);
}
}
int size(){
return size;
}
}
public class ArrayListImplementationDemo {
[Link]([Link]());
[Link]([Link](4));
[Link](1);
[Link]([Link]());
}
}
Methods Descriptions
clone() Creates a new arraylist with the same element, size, and capacity.
contains() Searches the arraylist for the specified element and returns a boolean
result.
Example:
public static void main(String[] args) { // Ummed Singh
// 1. pre
// 2. next
// 3. data
Time Complexity:
● Insertion at start and end: O(1)
● Insertion at particular index: O(n) for lookup of the index + O(1) for adding
● Search: O(n)
● Deletion at start or end: O(1)
● Deletion at specific index: O(n) for the lookup of the index + O(1) for removal
Space Complexity: O(n)
Stack
● Represent LIFO (Last in First out) operation
● Since it extends Vector, its method is also Synchronized.
● How its different from Deque: Deque is not thread safe, stack is.
[Link]([Link]());
}
}
Time Complexity:
● Insertion: O(1)
● Deletion: O(1)
● Search: O(n)
Space Complexity: O(n)
Queue Interface
The Queue interface is used when we want to store and access elements in a First In, First Out
manner.
The Queue interface of the Java collections framework provides the functionality of the queue
data structure. It extends the Collection interface.
Since the Queue is an interface, we cannot provide the direct implementation of it.
In order to use the functionalities of Queue, we need to use classes that implement it:
● ArrayDeque
● LinkedList
● PriorityQueue
● Deque
● BlockingQueue
● BlockingDeque
Working of Queue Data Structure
In queues, elements are stored and accessed in First In, First Out manner. That is, elements are
added from the behind and removed from the front.
● add() - Inserts the specified element into the queue. If the task is successful, add()
returns true, if not it throws an exception.
● offer() - Inserts the specified element into the queue. If the task is successful, offer()
returns true, if not it returns false.
● element() - Returns the head of the queue. Throws an exception if the queue is empty.
● peek() - Returns the head of the queue. Returns null if the queue is empty.
● remove() - Returns and removes the head of the queue. Throws an exception if the
queue is empty.
● poll() - Returns and removes the head of the queue. Returns null if the queue is empty.
PriorityQueue
● Its of 2 types, Minimum Priority Queue and Maximum Priority Queue
● It is based on priority Heap (Min Heap and Max Heap).
● Elements are ordered according to either Natural Ordering (by default) or by Comparator
provided during queue construction time.
1. MinPriorityQueue: min priority queue, used to solve problems of min heap.
Output:
1
2
8
5
remove from top:1
remove from top:2
remove from top:5
remove from top:8
2. MaxPriorityQueue: max priority queue, used to solve problems of max heap
Output:
8
2
5
1
remove from top:8
remove from top:5
remove from top:2
remove from top:1
Map Interface
In Java, the Map interface allows elements to be stored in key/value pairs. Keys are unique
names that can be used to access a particular element in a map. And, each key has a single
value associated with it.
We can access and modify values using the keys associated with them.
In the above diagram, we have values: United States, Brazil, and Spain. And we have
corresponding keys: us, br, and es.
Now, we can access those values using their corresponding keys.
Note: The Map interface maintains 3 different sets:
● the set of keys
● the set of values
● the set of key/value associations (mapping).
Methods of Map
The Map interface includes the following methods:
● put(K, V) - Inserts the association of a key K and a value V into the map. If the key is
already present, the new value replaces the old value.
● putAll() - Inserts all the entries from the specified map to this map.
● putIfAbsent(K, V) - Inserts the association if the key K is not already associated with the
value V.
● get(K) - Returns the value associated with the specified key K. If the key is not found, it
returns null.
● getOrDefault(K, defaultValue) - Returns the value associated with the specified key K.
If the key is not found, it returns the defaultValue.
● containsKey(K) - Checks if the specified key K is present in the map or not.
● containsValue(V) - Checks if the specified value V is present in the map or not.
● replace(K, V) - Replace the value of the key K with the new specified value V.
● replace(K, oldValue, newValue) - Replaces the value of the key K with the new value
newValue only if the key K is associated with the value oldValue.
● remove(K) - Removes the entry from the map represented by the key K.
● remove(K, V) - Removes the entry from the map that has key K associated with value V.
● keySet() - Returns a set of all the keys present in a map.
● values() - Returns a set of all the values present in a map.
● entrySet() - Returns a set of all the key/value mapping present in a map.
In the above code, we have created a hashmap named numbers. Here, K represents the key
type and V represents the type of values. For example,
Here, the type of keys is String and the type of values is Integer.
[Link]("One", 1);
[Link]("Two", 2);
Method Description
// create a HashMap
[Link](1, "Java");
[Link](2, "Python");
[Link](3, "JavaScript");
[Link]("Keys: ");
[Link](key);
[Link](", ");
[Link]("\nValues: ");
[Link](value);
[Link](", ");
[Link]("\nEntries: ");
[Link](entry);
[Link](", ");
Note that we have used the [Link] in the above example. It is the nested class of
the Map interface that returns a view (elements) of the map.
We first need to import the [Link] package in order to use this class.
In Java, we can also create a hashmap from other maps. For example,
import [Link];
[Link]("Two", 2);
[Link]("Four", 4);
[Link]("Three", 3);
In the above example, we have created a TreeMap named evenNumbers. Notice the
expression,
Note: While creating a hashmap, we can include optional parameters: capacity and
load factor. For example,
Set Interface
The Set interface allows us to store elements in different sets similar to the set in mathematics.
It cannot have duplicate elements.
Here, we have created a Set called animals. We have used the HashSet class to implement the
Set interface.
Methods of Set
The Set interface includes all the methods of the Collection interface. It's because Collection is a
super interface of Set.
Some of the commonly used methods of the Collection interface that's also available in the Set
interface are:
● add() - adds the specified element to the set
● addAll() - adds all the elements of the specified collection to the set
● iterator() - returns an iterator that can be used to access elements of the set
sequentially
● remove() - removes the specified element from the set
● removeAll() - removes all the elements from the set that is present in another specified
set
● retainAll() - retains all the elements in the set that are also present in another specified
set
● clear() - removes all the elements from the set
● size() - returns the length (number of elements) of the set
● toArray() - returns an array containing all the elements of the set
● contains() - returns true if the set contains the specified element
● containsAll() - returns true if the set contains all the elements of the specified collection
● hashCode() - returns a hash code value (address of the element in the set)
Set Operations
The Java Set interface allows us to perform basic mathematical set operations like union,
intersection, and subset.
● Union - to get the union of two sets x and y, we can use [Link](y)
● Intersection - to get the intersection of two sets x and y, we can use [Link](y)
● Subset - to check if x is a subset of y, we can use [Link](x)
import [Link];
[Link](2);
[Link](3);
[Link](1);
[Link](2);
[Link](set1);