JDBC Statement & ResultSet: Database වැඩ Sinhala වලින්!

JDBC Statement and ResultSet: Database එක්ක කතා කරමු!
ආයුබෝවන් යාළුවනේ! කොහොමද කට්ටියට? අද අපි කතා කරන්න යන්නේ software development වලදි නැතුවම බැරි, ඒ වගේම ගොඩක් අය පොඩ්ඩක් ව්යාකූල වෙන topic එකක් ගැන. ඒ තමයි Java Database Connectivity (JDBC) වල තියෙන Statement
සහ ResultSet
කියන දෙක. මේ දෙන්නා තමයි අපේ Java application එක database එකක් එක්ක කතා කරනකොට ප්රධානම භූමිකාවක් කරන්නේ. Database වැඩ කියන්නේ developers ලා විදියට අපිට හැමදාම වගේ කරන්න වෙන දෙයක් නේද? ඒ නිසා මේ tools දෙක හරියටම තේරුම් ගැනීම හරිම වැදගත්.
අපි හිතමුකෝ database එකක් කියන්නේ පොත් ගොඩක් තියෙන ලොකු පුස්තකාලයක් කියලා. අපේ Java application එක තමයි මේ පුස්තකාලයට එන කෙනා. එතකොට JDBC කියන්නේ මේ පුස්තකාලයේ ඉන්න පුස්තකාලයා (librarian) වගේ. අපි ඉල්ලන පොත් ටික හොයලා දෙන, අලුත් පොත් එකතු කරන, නැති පොත් ලැයිස්තුවෙන් අයින් කරන වගේ වැඩ ඔක්කොම කරන්නේ පුස්තකාලයා හරහා. Statement
එකයි, ResultSet
එකයි කියන්නේ එයාට වැඩ කරන්න උදව් වෙන tools වගේ. සරලයි නේද? එහෙනම් අපි විස්තරේට යමු.
JDBC කියන්නේ මොකක්ද? (What is JDBC?)
සරලවම කිව්වොත්, JDBC කියන්නේ Java applications වලට relational databases එක්ක interact කරන්න පුළුවන් කරන API (Application Programming Interface) එකක්. මේක අපිට database එකකට connect වෙන්න, SQL queries execute කරන්න, ඒ queries වලින් එන results handle කරන්න වගේ ගොඩක් දේවල් වලට උදව් වෙනවා. Java වලින් database සම්බන්ධ වැඩ කරනකොට JDBC තමයි අපේ මූලිකම මෙවලම.
JDBC Architecture එකේ ප්රධාන Components ටිකක් තියෙනවා:
- Driver Manager: මේක තමයි අපිට අවශ්ය database එකට ගැලපෙන driver එක load කරලා, database connection එකක් හදන්න උදව් කරන්නේ.
- Drivers: මේවා තමයි database vendors ලා විසින් සපයන software. මේවා හරහා තමයි JDBC API calls database specific calls වලට convert වෙන්නේ. උදාහරණයක් විදියට MySQL, PostgreSQL, Oracle වගේ databases වලට වෙන වෙනම drivers තියෙනවා.
- Connection: මේක තමයි අපේ Java application එකයි database එකයි අතර තියෙන communication link එක. මේක නැතුව database එකට කතා කරන්න බෑ.
- Statement / PreparedStatement / CallableStatement: මේවා තමයි database එකට SQL queries යවන්න පාවිච්චි කරන objects. අද අපි
Statement
ගැන විතරක් ගැඹුරින් කතා කරමු. - ResultSet: database එකකින් දත්ත query කරද්දී (
SELECT
queries) එන results තියාගෙන ඉන්නේ මේ object එකේ.
හරි, දැන් JDBC කියන්නේ මොකක්ද කියලා පොඩි අදහසක් ආවනේ. දැන් අපි බලමු අපේ ප්රධාන චරිත දෙක, Statement
සහ ResultSet
, කොහොමද වැඩ කරන්නේ කියලා.
Statement එකේ බලය (The Power of Statement)
Statement
කියන්නේ JDBC API එකේ තියෙන fundamental interface එකක්. මේක අපිට database එකට static SQL queries යවන්න පාවිච්චි කරන්න පුළුවන්. static කියන්නේ, query එකේ parameters නැතුව, ඒ කියන්නේ සම්පූර්ණ query එක compile වෙන්න කලින්ම fix වෙලා තියෙන queries වලට. උදාහරණයක් විදියට, SELECT * FROM Users;
කියන query එක static query එකක්.
Statement object එකක් හදාගන්නේ කොහොමද?
Statement
object එකක් හදාගන්න නම් අපිට මුලින්ම database connection එකක් (Connection
object) අවශ්යයි. Connection object එකේ තියෙන createStatement()
method එකෙන් තමයි අපි මේක හදාගන්නේ.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
// ... Connection object එකක් හදපු ගමන්
Connection connection = null;
Statement statement = null;
try {
// Database URL, Username, Password
String url = "jdbc:mysql://localhost:3306/mydatabase";
String user = "root";
String password = "mypassword";
// Connection එක හදාගන්නවා
connection = DriverManager.getConnection(url, user, password);
// Statement object එක හදාගන්නවා
statement = connection.createStatement();
System.out.println("Statement object එක සාර්ථකව හැදුවා.");
} catch (SQLException e) {
e.printStackTrace();
} finally {
// Resources close කරන එක අනිවාර්යයි
try {
if (statement != null) statement.close();
if (connection != null) connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
Statement එකෙන් SQL Queries execute කරන්නේ කොහොමද?
Statement
object එකේ queries execute කරන්න ප්රධාන methods දෙකක් තියෙනවා:
executeUpdate(String sql)
: මේක පාවිච්චි කරන්නේ database එකට වෙනස්කම් කරන queries වලට. ඒ කියන්නේ INSERT
, UPDATE
, DELETE
වගේ queries වලට. මේ method එකෙන් return කරන්නේ query එක නිසා බලපෑ records ගාන (number of rows affected).
// INSERT query එකක්
String sqlInsert = "INSERT INTO Products (name, price) VALUES ('Laptop', 1200.00)";
int rowsAffectedInsert = statement.executeUpdate(sqlInsert);
System.out.println(rowsAffectedInsert + " row(s) inserted.");
// UPDATE query එකක්
String sqlUpdate = "UPDATE Products SET price = 1150.00 WHERE name = 'Laptop'";
int rowsAffectedUpdate = statement.executeUpdate(sqlUpdate);
System.out.println(rowsAffectedUpdate + " row(s) updated.");
// DELETE query එකක්
String sqlDelete = "DELETE FROM Products WHERE name = 'Laptop'";
int rowsAffectedDelete = statement.executeUpdate(sqlDelete);
System.out.println(rowsAffectedDelete + " row(s) deleted.");
executeQuery(String sql)
: මේක පාවිච්චි කරන්නේ database එකෙන් දත්ත ගන්න (retrieve) කරන SELECT
queries වලට. මේ method එකෙන් ResultSet
object එකක් return කරනවා. මේ ResultSet
එකේ තමයි අපේ query එකට අදාල දත්ත ටික තියෙන්නේ.
String sqlSelect = "SELECT id, name, email FROM Users";
ResultSet resultSet = statement.executeQuery(sqlSelect);
// දැන් resultSet එකෙන් දත්ත කියවන්න පුaranteed
Statement වල සීමාවන් (Limitations of Statement)
Statement
එක පාවිච්චි කරන්න හරිම ලේසියි. ඒත් මේකේ ප්රධාන සීමාවන් දෙකක් තියෙනවා:
- Performance: එකම query එක ගොඩක් පාරක් වෙනස් parameters එක්ක execute කරනකොට,
Statement
එක එච්චර efficient නෑ. මොකද හැම පාරම database එකට query එක compile (prepare) කරන්න වෙනවා. මේකට විසඳුම තමයිPreparedStatement
, ඒ ගැනත් වෙනදාට කතා කරමු.
SQL Injection Vulnerability: මේක තමයි ලොකුම ගැටලුව. අපි user input එකක් අරගෙන ඒක කෙලින්ම query එකට join කරලා Statement
එකෙන් execute කළොත්, ඒක SQL Injection attacks වලට ගොඩක් දුරට නිරාවරණය වෙනවා. Attackers ලාට පුළුවන් SQL code එකක් inject කරලා database එකට හානි කරන්න, නැත්නම් unauthorized access ගන්න. මේක ගැන පස්සේ වෙන post එකකින් විස්තරාත්මකව කතා කරමු.
// DANGER: SQL Injection අවදානම!
String userInput = "' OR '1'='1"; // මේක malicious input එකක් වෙන්න පුළුවන්
String unsafeSql = "SELECT * FROM Users WHERE username = '" + userInput + "'";
// statement.executeQuery(unsafeSql); -- මේක භයානකයි!
ඒ නිසා, Statement
එක සරල, static queries වලට විතරක් පාවිච්චි කරන එක තමයි හොඳම පුරුද්ද. user input involve වෙන තැන් වලට PreparedStatement
පාවිච්චි කරන්න!
ResultSet එකෙන් දත්ත කියවමු (Let's Read Data with ResultSet)
ResultSet
කියන්නේ database එකෙන් SELECT
query එකක් execute කරාට පස්සේ එන results තියාගෙන ඉන්න object එක. මේක table එකක වගේ දත්ත row by row තියාගෙන ඉන්නවා. ResultSet
එකේ cursor එකක් තියෙනවා. මේ cursor එකට පුළුවන් results වල තියෙන හැම row එකක් දිගේම move වෙන්න.
ResultSet එක වැඩ කරන්නේ කොහොමද?
ResultSet
object එක හැමවිටම Statement.executeQuery()
method එකෙන් return කරනවා. මුලින්ම, cursor එක පළවෙනි row එකට කලින් තැනක තමයි තියෙන්නේ. අපිට next()
method එක පාවිච්චි කරලා cursor එක ඊලඟ row එකට ගෙනියන්න පුළුවන්. next()
method එක return කරන්නේ boolean
value එකක්. ඒ කියන්නේ තවත් row එකක් තියෙනවා නම් true
, නැත්නම් false
.
මේ next()
method එක අපිට while
loop එකක් ඇතුලේ පාවිච්චි කරලා ResultSet
එකේ තියෙන හැම row එකක්ම iterate කරන්න පුළුවන්.
ResultSet එකෙන් දත්ත ලබාගන්නේ කොහොමද?
ResultSet
එකේ තියෙන data ලබාගන්න විවිධ getter methods තියෙනවා. මේවා column index එකක් (1-based index) හරි column name එකක් හරි parameter විදියට ගන්නවා.
getString(int columnIndex)
/getString(String columnName)
getInt(int columnIndex)
/getInt(String columnName)
getDouble(int columnIndex)
/getDouble(String columnName)
getDate(int columnIndex)
/getDate(String columnName)
- ... තවත් ගොඩක් methods තියෙනවා data types වලට අදාලව
Column name එක පාවිච්චි කරන එක තමයි හොඳම පුරුද්ද, මොකද ඒක code එකට කියවන්න ලේසියි, වගේම database table structure එකේ column order එක වෙනස් උනත් අපේ code එක කැඩෙන්නේ නෑ.
ප්රායෝගික උදාහරණයක්: Users ලා ටිකක් database එකෙන් ගන්න හැටි (A Practical Example: Fetching Users)
අපි හිතමු අපිට database එකේ තියෙන Users
table එකෙන් හැම user කෙනෙක්ගේම id
, name
, සහ email
address එක ගන්න ඕනේ කියලා. අපි මේක Statement
සහ ResultSet
පාවිච්චි කරලා කරන්නේ කොහොමද කියලා බලමු. මේකේදී අපි Java 7 වල හඳුන්වා දුන්නු try-with-resources statement එක පාවිච්චි කරනවා. මේකෙන් resource (connection, statement, resultSet වගේ) එකක් try block එකෙන් පස්සේ automatic ව close වෙනවා, ඒ නිසා manually close()
call කරන්න ඕනෙ නෑ. මේක හරිම හොඳ පුරුද්දක්!
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcExample {
// Database Connection Details
private static final String DB_URL = "jdbc:mysql://localhost:3306/mydatabase?useSSL=false";
private static final String DB_USER = "root";
private static final String DB_PASSWORD = "mypassword";
public static void main(String[] args) {
// මුලින්ම MySQL Driver එක load කරගමු (optional for modern JDBC, but good practice)
try {
Class.forName("com.mysql.cj.jdbc.Driver");
System.out.println("MySQL JDBC Driver Loaded!");
} catch (ClassNotFoundException e) {
System.err.println("MySQL JDBC Driver Not Found!");
e.printStackTrace();
return;
}
// try-with-resources statement එක පාවිච්චි කරමු
try (Connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
Statement statement = connection.createStatement()) {
System.out.println("Database Connection Successful!");
// SELECT query එක
String sql = "SELECT id, name, email FROM Users";
System.out.println("Executing query: " + sql);
// executeQuery() method එකෙන් ResultSet එක ලබාගන්නවා
try (ResultSet resultSet = statement.executeQuery(sql)) {
System.out.println("\n--- Users List ---");
// ResultSet එකේ හැම row එකක්ම iterate කරනවා
while (resultSet.next()) {
// Column values ලබාගන්නවා column name එකෙන්
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String email = resultSet.getString("email");
System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
}
System.out.println("------------------\n");
}
// INSERT query එකක්
String sqlInsert = "INSERT INTO Users (name, email) VALUES ('Kamal', '[email protected]')";
int rowsInserted = statement.executeUpdate(sqlInsert);
System.out.println(rowsInserted + " row(s) inserted. (Kamal)");
// නැවතත් Users list එක බලමු
System.out.println("\n--- Users List After Insert ---");
try (ResultSet resultSetAfterInsert = statement.executeQuery("SELECT id, name, email FROM Users")) {
while (resultSetAfterInsert.next()) {
System.out.println("ID: " + resultSetAfterInsert.getInt("id") + ", Name: " +
resultSetAfterInsert.getString("name") + ", Email: " +
resultSetAfterInsert.getString("email"));
}
}
System.out.println("------------------------------\n");
} catch (SQLException e) {
System.err.println("Database error occurred!");
e.printStackTrace();
}
}
}
මේ code එක execute කරන්න කලින්, ඔයාගේ database එකේ mydatabase
කියලා database එකකුත්, ඒක ඇතුලේ Users
කියලා table එකකුත් තියෙන්න ඕනේ. ඒ වගේම id
(INT PRIMARY KEY AUTO_INCREMENT), name
(VARCHAR), email
(VARCHAR) වගේ columns තියෙන්න ඕනේ. MySQL Driver JAR file එක classpath එකට add කරන්න අමතක කරන්න එපා. (Maven/Gradle නම් dependency එකක් විදියට add කරන්න පුළුවන්).
මතක තියාගන්න ඕන දේවල් සහ ඉස්සරහට (Important Notes and What's Next)
Statement
සහ ResultSet
කියන්නේ JDBC වල මූලිකම දේවල්. මේවා පාවිච්චි කරලා ඔයාලට database එකත් එක්ක ලේසියෙන් වැඩ කරන්න පුළුවන්. ඒත් මතක තියාගන්න ඕන වැදගත්ම දේ තමයි, SQL Injection අවදානම. Real-world applications වලදී user input එක්ක වැඩ කරනකොට Statement
එක පාවිච්චි කරන එක ගොඩක් භයානකයි. ඒකට හොඳම විසඳුම තමයි PreparedStatement
. PreparedStatement
එක SQL queries වලට parameters add කරන්න පුළුවන් ආරක්ෂිත සහ efficient ක්රමයක් සපයනවා. මේක ගැන අපි ඊලඟ post එකකින් අනිවාර්යයෙන්ම කතා කරමු.
ඒ වගේම, හැම වෙලාවෙම database resources (Connection
, Statement
, ResultSet
) වැඩ ඉවර වුන ගමන් close කරන්න මතක තියාගන්න. try-with-resources
ඒකට හොඳම විසඳුම. එහෙම නැත්නම් database connections leak වෙලා application එකේ performance අඩු වෙන්න, වගේම database server එකට හානි වෙන්නත් පුළුවන්.
අන්තිමට…
ඉතින් යාළුවනේ, අද අපි JDBC Statement
සහ ResultSet
ගැන හොඳටම ඉගෙන ගත්තා කියලා හිතනවා. Database programming කියන්නේ software engineering වලදි නැතුවම බැරි skill එකක්. මේ concepts හොඳට තේරුම් ගත්තොත් ඔයාලගේ applications වල data handling capacity එක හොඳටම දියුණු කරගන්න පුළුවන්.
මේ post එකෙන් ඔයාලට මොනවා හරි අලුත් දෙයක් ඉගෙන ගන්න ලැබුණා නම් comment section එකේ කියන්න. මොනවා හරි ප්රශ්න තියෙනවා නම් අහන්නත් අමතක කරන්න එපා. ඊළඟට PreparedStatement
ගැන article එකක් ගේන්න බලාපොරොත්තු වෙනවා. එතකන් හැමෝටම ජය වේවා! Happy Coding!