Date: 1-Mar-24
ResultSetMetaData:
MetaData --- Data about Data
In a Java program you write comments, they represent
metadata.
In a Java program you write annotations, they represent
metadata.
ResultSetMetaData is used to get the information about the
columns which are stored in ResultSet object.
ResultSetMetaData is an interface, its implementation will be
available in driver software.
For the interfaces provided in JDBC API, the implementations
exist in Driver software/application.
Call getMetaData() method of ResultSet
object, to create ResultSetMetaData object.
ResultSetMetaData rsmd = rs.getMetaData();
To extract the information about the columns
from the ResultSetMetaData object, we have
to call the below methods.
1. getColumnCount() : returns the number of columns in
ResultSet object.
2. getColumnTypeName(columnIndex) : returns
the datatype of the column in ResultSet
object.
3. getColumnDisplaySize(columnIndex) :
returns the size of the column in ResultSet
object.
4. isNullable(columnIndex) : returns true,
if the column allows null, otherwise returns
false.
ResultSet rs = stmt.executeQuery( "SELECT EMPNO,
SAL, ENAME FROM EMP ");
ResultSetMetaData rsmd =
rs.getMetaData();
int columns_count =
rsmd.getColumnCount();
for(int index = 1; index <=
columns_count; index++ ) {
System.out.println("column number
: " + index);
System.out.println("column name
: " + rsmd.getColumnName(index));
System.out.println("column type
: " + rsmd.getColumnTypeName(index));
System.out.println("column size
: " + rsmd.getColumnDisplaySize(index));
System.out.println("isNullable
: " + rsmd.isNullable(index));
System.out.println("============================
============");
} //end for
Types of statements in JDBC:
1. Statement
2. PreparedStatement
3. CallableStatement
Statement
<<interface>>
PreparedStatement
<<interface>>
CallableStatement
<<interface>>
PreparedStatement is an extension of
Statement.
CallableStatement is an extension of
PreparedStatement.
Statement stmt = conn.createStatement();
//insert records of 500 students
1. Create a for loop which repeats from 1 to
500
2. Take the student data from user within
the loop
3. Put the data/values in the insert query
4. Call executeUpdate() method with query to
insert the student record.
Scanner sc = new Scanner(System.in);
for(int i = 1; i <= 500; i++) {
S.o.p(“enter student id”);
int sid = sc.nextInt();
//similarly for other data
String query = “ INSERT INTO STUDENT
VALUES( “ + sid + “ , ‘ “ +
sname +
“ ‘ , “ + marks + “ )
“;
int k = stmt.executeUpdate(query);
}
In the above code, each time when the query
is sent to the database, it is compiled
first then
Executed next then the result will be
returned back to the program.
Here, the loop repeats for 500 times, so the
same query will be compiled for 500 times.
The problem with this kind of execution is
it decreases the performance of a program.
The solution for the above problem is, use
PreparedStatement interface.
PrepardStatemt allows us to pre-compile SQL
query for once and you can execute the query
as many times you want without compilation
again.
So PreparedStatement improves the
performance of an application.
PreparedStatement is given for three
reasons.
1. To improve the performance
2. To prevent SQL Injection attacks.
3. To store/retrieve the images
How to create PreparedStatement?
PreparedStatement pstmt =
conn.prepareStatement(query);
Here, query is passed to compile and to
execute. So we have put placeholders(?) for
parameters.
Ex:
String query = “INSERT INTO STUDENT
VALUES(?, ?, ?)”;
PreparedStatement pstmt =
conn.prepareStatement(query);
Whenever we are working with the
PreparedStatement, there are 3 steps to
follow.
1. Preparing
2. Parameter setting
3. Executing the query
Preparing is nothing but creating the
PreparedStatement object.
Call setXxx() methods to set the values to
the parameters
Call executeUpdate() / executeQuery()
methods
Example:
package com.ashokit.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Scanner;
public class Pstmt_Example {
public static void main(String[] args) {
String databaseURL =
"jdbc:oracle:thin:@localhost:1521:xe";
String uname = "system";
String pwd = "tiger";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn =
DriverManager.getConnection(databaseURL, uname,
pwd);
String query = "INSERT INTO STUDENT
VALUES( ?, ?, ?)";
pstmt = conn.prepareStatement(query);
Scanner sc = new Scanner(System.in);
for (int i = 1; i <= 5; i++) {
System.out.println("Please enter
student id");
int sid = sc.nextInt();
pstmt.setInt(1, sid);
sc.nextLine();
System.out.println("Please enter
student name");
String sname = sc.nextLine();
pstmt.setString(2, sname);
System.out.println("Please enter
student marks");
int marks = sc.nextInt();
pstmt.setInt(3, marks);
pstmt.executeUpdate();
System.out.println("Row
inserted ......");
} // end for
} // end try
catch (Exception ex) {
ex.printStackTrace();
} // end catch
finally {
try {
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
} //end finally
} //end main
} //end class
SQL Injection attack?
---------------------
For ex:
S.o.p(“enter username”);
String username = sc.nextLine();
String query = “SELECT * FROM USERS WHERE
USERNAME = “+ username;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
The malicious user has entered the username
as
‘Sathish’ OR 1=1
If the username is substituted in the query
then it becomes,
SELECT * FROM USERS WHERE USERNAME =
‘Sathish’ OR 1=1
In the above query, the malicious
user/hacker don’t know the username but 1=1
is always true. So the hacker is able to
steal the data of all the users.
This type of SQL Injection attacks are
possible with Statement object.
To prevent SQL injection attacks, we have to
use PreparedStatement object.
For ex:
S.o.p(“enter username”);
String username = sc.nextLine();
String query = “SELECT * FROM USERS WHERE
USERNAME = ? “;
PreparedStatement pstmt =
conn.prepareStatement(query);
Suppose, a hacker has given username as
‘sathish’ or 1=1
pstmt.setString(1, username);
Now the query is
“SELECT * FROM USERS WHERE USERNAME =
‘sathish’ or 1=1 “
In this case, there is no user with the
given username, so hacker can’t steal the
data of the users.
Storing an image in a database:
-------------------------------
To store an image in a database, the table
must contain a column of datatype BLOB.
BLOB – Binary Large Object
The image type that can be stored in a
database, is except bmp files.
package com.ashokit.jdbc;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Insert_Image {
public static void main(String[] args) {
String databaseURL =
"jdbc:oracle:thin:@localhost:1521:xe";
String uname = "system";
String pwd = "tiger";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn =
DriverManager.getConnection(databaseURL,
uname, pwd);
String query = "INSERT INTO
IMAGES VALUES(?, ?)";
pstmt =
conn.prepareStatement(query);
pstmt.setString(1, "earth");
File file = new File("C:\\Users\\
hi\\Documents\\planet.jpg");
FileInputStream fis = new
FileInputStream(file);
//pstmt.setBinaryStream(2, fis);
pstmt.setBlob(2, fis);
pstmt.executeUpdate();
System.out.println("Row
inserted.....");
}catch(SQLException | IOException ex)
{
ex.printStackTrace();
}
finally {
try {
if (pstmt != null) {
pstmt.close();
}
if(conn != null) {
conn.close();
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
Installing mysql server:
Open google and type mysql community server
download
Select the first link
Change the mysql server version to 8.0.36
Click on goto download page link
Choose mysql server 285M download
Installer file is downloaded
Double click on the downloaded file
In the opened window, choose custom radio
button
In the next window, expand mysql server8.0
select mysql server 8.0 x64 move it to right
side
Expand applications mysql workbench
move to right side.
Then follow the next buttons to finish the
installation.
Mysql server and workbench are installed at
C:\Program Files\MySQL
MySQL workbench is a GUI client to connect
with mysql server.
Open the workbench
In Windows search, type mysql workbench
open
Click on Local instance enter the password
In the window, create a database
Command: create database test;
Execute the command
Goto Database menu connect to Database
in schema, enter test ok
Select shemas tab at right side, then you
can able to see the database test
Before executing any sql queries in
workbench, first execute the below command
SET SQL_SAFE_UPDATES = 0;
The connection properties for mysql database
are,
String databaseURL =
"jdbc:mysql://localhost:3306/test";
String uname = "root";
String pwd = "root";
You have to download mysql-connector-j jar
file for mysql driver software.
Mysql driver classname:
com.mysql.cj.jdbc.Driver
CallableStatement:
-----------------
CallableStatement is an extension of
PreparedStatement, which has all the
capabilities of PreparedStatement plus, it
has the additional capability to invoke the
stored procedures in a database.
Stored procedures in a database means, both
procedures and functions in a database.
Here, we are writing the logic in Java
program. But we can move this logic to the
database also.
In the database, we can create a function to
perform this operation. It will take empno
as input and returns the experience of that
employee.
Procedure or functions are created to
perform a task or operation. The advantage
is, it is reusable.
The difference between procedure and a
function in a database are,
1. Procedure can perform the task but
doesn’t return the value. But function can
return a single value.
2. Procedure can perform transactions, but
function can’t perform transaction.
To create a procedure/function in a
database, we have to follow the syntax
specific to that database.
Date: 11/3/24
Suppose, if you want to create a function in
mysql database then you have to open mysql
workbench.
In query editor, type the command
Use test;
Now we are creating a function to accept
empno as input and should return the
experience of the employee based on his hire
date.
Expand test database
Right click on functions create function
Type the following code
CREATE FUNCTION `experience_of_employee`
(eno INT)
RETURNS DOUBLE deterministic
BEGIN
DECLARE jd date;
DECLARE experience DOUBLE;
DECLARE td date;
SELECT HIREDATE into jd FROM EMP WHERE
EMPNO = eno;
SELECT CURRENT_DATE into td from dual;
SET experience = DATEDIFF(td,jd ) / 365;
RETURN experience;
END
Click on Apply and then again apply and
finish.
Finally function is created in the database.
To create a CallableStatement object, you
have to call prepareCall() method of
Connection object.
String query = “{ ? = CALL
experience_of_employee(?) } “;
CallableStatement cstmt =
conn.prepareCall(query);
The query is a call statement, with two
parameters.
The first parameter is to capture the
result/output and second parameter is for
sending the input.
So we need to register the first parameter
as out parameter with CallableStatement
object.
cstmt.registerOutParameter(1, Types.DOUBLE);
Then you have to call execute() method.
In function creation, the parameters of a
function must be of mode IN.
The default mode of a parameter is IN.
In procedure creation, the parameters of a
procedure can be
Of mode IN,
Of mode OUT, OR
Of mode INOUT
Date: 12/3/2024
Transaction management in JDBC:
Transaction consists a group of
statements/operations which are executed as
a single unit.
A transaction completes either with a
success or with a failure.
From a jdbc program, each sql query will
execute as a separate transaction. It means,
once the query is executed then it is
automatically committed in the database.
If you want to execute multiple queries from
a jdbc program as a single transaction then
you have to use transaction management in
JDBC.
You have to follow the below steps.
1. Disable auto commit mode of connection,
to begin the transaction.
2. If all the queries are executed
successfully then you have to commit the
transaction.
3. If any query execution is failed then
you have to rollback the transaction.
In connection object, we have the methods
for transaction management.
1. setAutoCommit()
2. commit()
3. rollback()
conn.setAutoCommit(false); // It will
disable auto commit mode.
conn.commit(); //it will commit the
transaction
conn.rollback();//it will rollback the
transaction
conn.setAutoCommit(false); //transaction
begin
try {
execute query1
execute query2
execute query3
execute query4
conn.commit(); // transaction
success
}
catch(Exception ex) {
conn.rollback(); //transaction
failed
}
DATE : 13 / 3 / 2024
Transactions are 2 types.
1. Local transaction
2. Global transaction / distributed
transaction
In a Local transaction, the entire
transaction is executed on a single
database.
In a global transaction, the transaction is
executed on more than one database.
With JDBC API, we can only execute the local
transactions.
To execute global transactions, we have to
use JTA(Java Transaction API).
//Fund transfer example(local transaction)
package com.ashokit.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class Transaction_Demo {
public static void main(String[] args) {
String databaseURL =
"jdbc:mysql://localhost:3306/test";
String uname = "root";
String pwd = "root";
Connection conn = null;
try {
conn =
DriverManager.getConnection(databaseURL,
uname, pwd);
conn.setAutoCommit(false); //
transaction begin
int fromAccount = 10011011;
int toAccount = 20022022;
double amount = 4500;
boolean flag =
transferFunds(conn, fromAccount, toAccount,
amount);
if(flag == false) {
throw new Exception();
}
else {
conn.commit();
System.out.println("Transaction success!!
Money transfered.");
}
}
catch(Exception ex) {
try {
if(conn != null)
conn.rollback();
System.out.println("Transaction failed!!
Money not transfered");
}catch(Exception e) {
e.printStackTrace();
}
}
finally {
try {
if(conn != null) {
conn.close();
}
}catch(Exception exe) {
exe.printStackTrace();
}
private static boolean
transferFunds(Connection conn, int
fromAccount, int toAccount, double amount)
throws Exception{
try {
Statement stmt =
conn.createStatement();
ResultSet rs1 =
stmt.executeQuery("SELECT ACCOUNT_BALANCE
FROM ACCOUNT WHERE ACCOUNT_NUMBER =
"+fromAccount);
rs1.next();
double bal_fromAccount =
rs1.getDouble("ACCOUNT_BALANCE");
rs1.close();
ResultSet rs2 =
stmt.executeQuery("SELECT ACCOUNT_BALANCE
FROM ACCOUNT WHERE ACCOUNT_NUMBER =
"+toAccount);
rs2.next();
double bal_toAccount =
rs2.getDouble("ACCOUNT_BALANCE");
rs2.close();
stmt.executeUpdate("UPDATE
ACCOUNT SET ACCOUNT_BALANCE = " +
(bal_fromAccount - amount) + " WHERE
ACCOUNT_NUMBER = "+ fromAccount);
stmt.executeUpdate("UPDATE
ACCOUNT SET ACCOUNT_BALANCE = " +
(bal_toAccount + amount) + " WHERE
ACCOUNT_NUMBER = "+ toAccount);
stmt.close();
if(bal_fromAccount - amount < 0)
{
return false;
}
else {
return true;
}
}
finally {
Scrollable result set
---------------------
By default, a result set is forward only
type.
It means, the cursor can be moved only in
the forward direction.(top to bottom).
When you have large data sets in the result
set object and if you want to move the
cursor in forward and backward directions
then you have create a scrollable result set
object.
To create scrollable result set object, you
have to pass two parameters while creating a
statement.
Statement stmt = conn.createStatement(type,
mode);
Type can be:
ResultSet.TYPE_SCROLL_SENSITIVE (or)
ResultSet.TYPE_SCROLL_INSENSITIVE
Mode can be:
ResultSet.CONCUR_READ_ONLY (or)
ResultSet.CONCUR_UPDATABLE
Date: 14 /3 / 2024
TYPE_SCROLL_SENSITIVE: while result set is
open, if any changes are made to the
database by another application, the changes
will get reflected into the result set
object also.
TYPE_SCROLL_INSENSITIVE: while result set is
open, if any changes are made to the
database by another application, the changes
will not get reflected into the result set
object.
CONCUR_READ_ONLY: The program can only read
the data from result set object, but it
can’t make any changes to the data in the
database, thru this result set object.
CONCUR_UPDATABLE: The program can read the
data from result set object and also it can
make changes to the data in database, thru
this result set object.
You have to use the below methods to move
the cursor.
next()
previous()
beforeFirst()
afterLast()
absolute()
absolute(3) cursor will be moved to
the
3rd row from top
Absolute(-3) cursor will be moved to
the
3rd row from bottom
first()
last()
updateXxx() : to make changes to the data in
resultset object
insertRow()
updateRow()
deleteRow()
package com.ashokit.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class ScrollableTest {
public static void main(String[] args)
throws Exception {
String databaseURL =
"jdbc:oracle:thin:@localhost:1521:XE";
String uname = "system";
String pwd = "tiger";
Connection conn =
DriverManager.getConnection(databaseURL, uname,
pwd);
Statement stmt =
conn.createStatement(ResultSet.TYPE_SCROLL_INSEN
SITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery( "SELECT
* FROM EMP" );
rs.afterLast(); //moves cursor to after
the last row
System.out.println("==========printing
the records from bottom to
top====================");
while(rs.previous()) {
System.out.println(rs.getInt(1)+"
"+ rs.getString(2) +" " + rs.getDouble(3)
+ " "+
rs.getDate(4)+ " " + rs.getInt(5));
}
System.out.println("============ printing
3rd row of result set ===================");
rs.absolute(3);
System.out.println(rs.getInt(1)+" "+
rs.getString(2) +" " + rs.getDouble(3)
+ " "+ rs.getDate(4)+ " " +
rs.getInt(5));
rs.close();
stmt.close();
conn.close();
package com.ashokit.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class UpdatableTest {
public static void main(String[] args)
throws Exception {
String databaseURL =
"jdbc:mysql://localhost:3306/test";
String uname = "root";
String pwd = "root";
Connection conn =
DriverManager.getConnection(databaseURL, uname,
pwd);
Statement stmt =
conn.createStatement(ResultSet.TYPE_SCROLL_INSEN
SITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT
* FROM ACCOUNT");
rs.next();
rs.updateDouble(3, 6499.0);
rs.updateRow();
System.out.println("row updated......");
rs.close();
stmt.close();
conn.close();
Date: 15 / 3 / 2024
Connection pooling in JDBC:
So far, our applications obtained a
connection with a database using
DriverManager class.
If our application is a stand-alone
application then we can use
DriverManager class to obtain the
database connection.
If our application is running on a
server,
Multiple users can make a request. In
this case our application obtains a
separate connection for each request.
If multiple connections with a database
then at some point, the database may
crash due to more connections opened.
So, DriverManager class can’t be used
in the real-time applications. It can
be used only for the testing purpose.
The solution to the above problem is
connection pooling mechanism.
In connection pooling mechanism, a
set/group of reusable database
connections are opened and managed in a
pool.
When application wants a connection, it
borrows from the pool. After executing
the queries, the application returns
the connection back to the pool for
reuse.
To create & manage a pool and also to
obtain/borrow a connection from the
pool, JDBC API has provided, DataSource
interface.
DataSource interface uses internally a
connection pool manager for creating
and managing the connection in a pool.
For DataSource interface, the
implementation is given in driver
software and also there are third party
softwares available.
For example, Apache Commons DBCP and
HikariCP are the third party softwares.
For example, if you are working with
HikariCP api, then you have to include
the below jars in the classpath.
HikariCP-5.0.0.jar
Mysql-connector-j-8.3.0.jar
Slf4j-api-2.0.12.jar
Slf4j-simple-2.0.12.jar
try-with-resources:
-------------------
You can specify with which resources
you would like work with in the try
block.
Once, the try block is executed either
successfully or by throwing exception,
the resources will be automatically
closed.
In this way, we can avoid writing
finally block sometimes.
try block can only work with auto
closeable resources. It means, the
object with which try block is working
should implement AutoCloseable
interface.
try ( Connection conn =
DriverManager.getConnection(url,
uname,pwd) )
{
//code
}
catch(Exception ex) {
ex.printStackTrace();
}
For ex:
try( Connection conn =
DriverManager.getConnection(databaseURL, uname,
pwd);
Statement stmt
=conn.createStatement(ResultSet.TYPE_SCROLL_INSE
NSITIVE, ResultSet.CONCUR_UPDATABLE) )
{
ResultSet rs = stmt.executeQuery(
"SELECT * FROM EMP" );
rs.afterLast(); //moves cursor to
after the last row
System.out.println("==========printing the
records from bottom to
top====================");
while(rs.previous()) {
System.out.println(rs.getInt(1)+"
"+ rs.getString(2) +" " + rs.getDouble(3)
+ " "+
rs.getDate(4)+ " " + rs.getInt(5));
}
rs.close();
}
catch(Exception ex) {
ex.printStackTrace();
}
Batch execution:
---------------
when a program is executing multiple
sql queries on a database, each query
will be executed separately.
In this way, the number of round trips
b/w appln and database will be
increased. It will effect the
performance of the application.
The solution is, you can make all the
queries into one batch and you can
execute the entire batch at a time on
database. This is called batch
processing.
The two methods for batch processing,
1. addBatch()
2. executeBatch()
For ex:
Stmt.addBatch(“INSERT INTO ………………. “);
Stmt.addBatch(“UPDATE
…………………………………..”);
Stmt.addBatch(“DELTE …………………………….. “);
Stmt.addBatch(“UPDATE …………………………….. “);
int x[ ] = stmt.executeBatch();