Skip to content

Commit

Permalink
add POM and java classes
Browse files Browse the repository at this point in the history
  • Loading branch information
donsez committed Nov 8, 2024
1 parent 4419a19 commit cac67b2
Show file tree
Hide file tree
Showing 28 changed files with 1,228 additions and 43 deletions.
145 changes: 102 additions & 43 deletions jdbc-postgresql/README.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,56 @@
# Manipulation d'une base PostgreSQL via JBDC

Read https://mkyong.com/jdbc/how-do-connect-to-postgresql-with-jdbc-driver-java/
This tutorial is based on https://mkyong.com/jdbc/how-do-connect-to-postgresql-with-jdbc-driver-java/

Check Java version
Check your Java version
```bash
java --version
javac --version
```

Install [Maven](https://maven.apache.org/install.html)
Install [Maven](https://maven.apache.org/install.html) for compiling the classes
```bash
mkdir -p ~/devtools/apache
cd ~/devtools/apache
wget https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz
tar xvf apache-maven-3.9.9-bin.tar.gz
```

Set $PATH
Set `mvn` into your `$PATH`
```bash
export PATH=$PATH:~/devtools/apache/apache-maven-3.9.9/bin
mvn -v
```

Start the PostgreSQL server using the instructions [here](../postgres/README.md).

Create and populate the `test` database using the [following example](../postgres/work/employee/employee.sql). Password is `changeme` .
Create and populate the `test` database using the [following example](../postgres/work/employee/employee.sql). Remenber : the password is `changeme` .


Install the JDBC example from https://github.com/mkyong/java-jdbc/
Build the classes of the program

```bash
mkdir -p ~/github/mkyong/
cd ~/github/mkyong/
git clone https://github.com/mkyong/java-jdbc/
cd ~/github/donsez/bd/jdbc-postgresql
mvn compile
tree target/classes
```

Build the classes of the program
> You can package the program as a Jarfile with `mvn compile`.
```bash
cd ~/github/mkyong/
cd java-jdbc/postgresql
mvn compile
tree target/classes
ls -al target/*.jar
```

> You can pachage the program as a Jarfile with `mvn compile`.
> You can install the program as a Jarfile with `mvn install` into your local Maven repository `~/.m2/repository`.
```bash
ls -al ~/.m2/repository/github/donsez/bd/jdbc-postgresql/0.1.0-SNAPSHOT/
```


Run the program `src/main/java/com/mkyong/jdbc/JDBCExample.java`
Run the program `src/main/java/com/mkyong/jdbc/ConnectOnlyExample.java`
```bash
MAIN_CLASS=com.mkyong.jdbc.JDBCExample
MAIN_CLASS=com.mkyong.jdbc.ConnectOnlyExample
APP_CLASSPATH=./target/classes
java -cp $APP_CLASSPATH $MAIN_CLASS
```
Expand All @@ -67,73 +64,138 @@ APP_CLASSPATH=$(mvn -q exec:exec -Dexec.executable=echo -Dexec.args="%classpath"
echo $APP_CLASSPATH
```

Re-Run the program `src/main/java/com/mkyong/jdbc/JDBCExample.java`
Re-Run the program `src/main/java/com/mkyong/jdbc/ConnectOnlyExample.java`
```bash
java -cp $APP_CLASSPATH $MAIN_CLASS
```

Re-Run the program `src/main/java/com/mkyong/jdbc/JDBCExample.java` with
```bash
MAIN_CLASS=com.mkyong.jdbc.JDBCExample
mvn -q exec:java -Dexec.mainClass=$MAIN_CLASS
```
> Question : What's happens ? Why ?
Change the password (the value is defined into [docker-compose.yml](../postgres/docker-compose.yml)) into the program `src/main/java/com/mkyong/jdbc/ConnectOnlyExample.java`.

Recompile the program with `mvn campile`.

Run the program `src/main/java/com/mkyong/jdbc/JDBCExample2.java`
Re-Run the program `src/main/java/com/mkyong/jdbc/ConnectOnlyExample.java` with
```bash
MAIN_CLASS=com.mkyong.jdbc.JDBCExample2
mvn -q exec:java -Dexec.mainClass=$MAIN_CLASS
MAIN_CLASS=com.mkyong.jdbc.ConnectOnlyExample
mvn -q exec:java -Dexec.mainClass=$MAIN_CLASS
```
or

Run the program `src/main/java/com/mkyong/jdbc/ListEmployeeExample.java`
```bash
java -cp $APP_CLASSPATH $MAIN_CLASS
MAIN_CLASS=com.mkyong.jdbc.ListEmployeeExample
mvn -q exec:java -Dexec.mainClass=$MAIN_CLASS
```

Run the program `src/main/java/com/mkyong/jdbc/TransactionExample.java`
```bash
MAIN_CLASS=com.mkyong.jdbc.TransactionExample
mvn -q exec:java -Dexec.mainClass=$MAIN_CLASS
mvn -q exec:java -Dexec.mainClass=$MAIN_CLASS
```

Run the program `src/main/java/com/mkyong/jdbc/ListEmployeeExample.java`
```bash
MAIN_CLASS=com.mkyong.jdbc.ListEmployeeExample
mvn -q exec:java -Dexec.mainClass=$MAIN_CLASS
```
or

> You can replace `./target/classes` by `./target/jdbc-postgresql-0.1.0-SNAPSHOT.jar` into the classpath
```bash
echo $APP_CLASSPATH
MAIN_CLASS=com.mkyong.jdbc.ListEmployeeExample
java -cp $APP_CLASSPATH $MAIN_CLASS
```


## Exercice: pass SELECT query as program argument

Duplicate `src/main/java/com/mkyong/jdbc/JDBCExample2.java` in `src/main/java/com/mkyong/jdbc/GenericQuery.java`
Duplicate `src/main/java/com/mkyong/jdbc/ListEmployeeExample.java` in `src/main/java/com/mkyong/jdbc/GenericQuery.java`

Pass the `SQL_SELECT` string as program argument.

Use `[getObject(int)](https://docs.oracle.com/javase/6/docs/api/java/sql/ResultSet.html#getObject(int))` for printing the column values
First, use `[getObject(int)](https://docs.oracle.com/en/java/javase/23/docs/api/java.sql/java/sql/ResultSet.html)` for printing the column values.

> NB: `boolean wasNull()` - Reports whether the last column read had a value of SQL NULL.

Second, use `[ResultSetMetaData](https://docs.oracle.com/en/java/javase/23/docs/api/java.sql/java/sql/ResultSetMetaData.html)` for printing the column names in order to beautiful the output.

Then use `ResultSetMetaData` for printing the column names.
```java
ResultSetMetaData metaData = rs.getMetaData();
Integer columnCount = metaData.getColumnCount();
String tableName = getTableName(columnNumber); //
String columnName = getColumnName(columnNumber); // to get the name of the column
String columnLabel = getColumnLabel(int columnNumber); // to get the name of the column
String tableName = getColumnLabel(int columnNumber); // to access the label of the column, which is specified after AS in the SQL query

...

System.out.println("("+rs.getRow()+" rows)");
```

The output should be similar to:

```console
id | name | salary | created_date
------+-------------+-----------+-------------------------------
1007 | Lamport | 10000.00 | 2024-11-08 08:25:22.252877+00
1008 | Knuth | 15000.99 | 2024-11-08 08:25:22.252877+00
1009 | Petri | 20000.77 | 2024-11-08 08:25:22.252877+00
1010 | Gray | 30000.11 | 2024-11-08 08:25:22.252877+00
1011 | Codd | 10000.88 | 2024-11-08 08:25:22.252877+00
1012 | Stonebraker | 100000.00 | 2024-11-08 11:51:21.668123+00
(6 rows)
```

## Exercice: Properties file

Use a properties file in [./src/main/resources](./src/main/resources/app.properties) for improving configurability

```java
import java.lang.System;
import java.lang.Thread;
import java.io.FileInputStream;

...
String rootPath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
String appConfigPath = rootPath + "app.properties";

Properties appProps = new Properties();
try {
appProps.load(new FileInputStream(appConfigPath));
} catch (java.io.IOException e) {
e.printStackTrace();
return;
}

String jdbcDriver = appProps.getProperty("jdbc_driver");
System.out.println("driver :"+jdbcDriver);
```

## Exercice: SQL injection

Write a program exposed to [SQL injection](https://fr.wikipedia.org/wiki/Injection_SQL).
Write a JDBC program exposed to [SQL injection (SQLi)](https://fr.wikipedia.org/wiki/Injection_SQL) attack.

![](1705992627213.jpg)
(Source Gizmodo)

## Extra: JDBC URL

Modify the URL `"jdbc:postgresql://127.0.0.1:5432/test"` into the Java classes
## Extra: local ClassLoader

Change
```java
Class.forName("org.postgresql.Driver");
```
tree src/main/java/com/mkyong/jdbc/
grep -r -n "jdbc:postgresql://127.0.0.1:5432/test" src/main/java/com/mkyong/jdbc/
by
```java
final ClassLoader cl = this.getClass().getClassLoader ();
Class theClass = cl.loadClass("org.postgresql.Driver");
```

## Extra : Vérification des vulnérabilités
[Vérification des vulnérabilités](https://mvnrepository.com/artifact/org.owasp/dependency-check-maven) dans le programme Java : https://jeremylong.github.io/DependencyCheck/dependency-check-maven/


## Extra: Mise à jour des dépendances du projet

```bash
Expand All @@ -148,9 +210,6 @@ mvn versions:use-latest-releases
mvn versions:update-properties
git diff pom.xml
```

## Extra : Vérification des vulnérabilités
[Vérification des vulnérabilités](https://mvnrepository.com/artifact/org.owasp/dependency-check-maven) dans le programme Java : https://jeremylong.github.io/DependencyCheck/dependency-check-maven/

## References
* https://jdbc.postgresql.org/documentation/use/
Expand Down
44 changes: 44 additions & 0 deletions jdbc-postgresql/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>github.donsez.bd</groupId>
<artifactId>jdbc-postgresql</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>postgresql</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<postgresql.version>42.7.1</postgresql.version>
<!-- Remark : This Postgres JDBC Driver had vulnerabilities -->
</properties>

<dependencies>

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>

</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.mkyong.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class ConnectOnlyExample {

public static void main(String[] args) {

// https://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html#package.description
// auto java.sql.Driver discovery -- no longer need to load a java.sql.Driver class via Class.forName

// register JDBC driver, optional since java 1.6
/*try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}*/

// auto close connection
try (Connection conn = DriverManager.getConnection(
"jdbc:postgresql://127.0.0.1:5432/test", "postgres", "changeme")) {

if (conn != null) {
System.out.println("Connected to the database!");
} else {
System.out.println("Failed to make connection!");
}

} catch (SQLException e) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
} catch (Exception e) {
e.printStackTrace();
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.mkyong.jdbc;

import com.mkyong.jdbc.model.Employee;

import java.math.BigDecimal;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class ListEmployeeExample {

public static void main(String[] args) {

System.out.println("PostgreSQL JDBC Connection Testing ~");

// https://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html#package.description
// auto java.sql.Driver discovery -- no longer need to load a java.sql.Driver class via Class.forName

// register JDBC driver, optional since java 1.6
// Class.forName("org.postgresql.Driver");

List<Employee> result = new ArrayList<>();

String SQL_SELECT = "Select * from EMPLOYEE";

// auto close connection and preparedStatement
try (Connection conn = DriverManager.getConnection(
"jdbc:postgresql://127.0.0.1:5432/test", "postgres", "changeme");
PreparedStatement preparedStatement = conn.prepareStatement(SQL_SELECT)) {

ResultSet resultSet = preparedStatement.executeQuery();

while (resultSet.next()) {

long id = resultSet.getLong("ID");
String name = resultSet.getString("NAME");
BigDecimal salary = resultSet.getBigDecimal("SALARY");
Timestamp createdDate = resultSet.getTimestamp("CREATED_DATE");

Employee obj = new Employee();
obj.setId(id);
obj.setName(name);
obj.setSalary(salary);
// Timestamp -> LocalDateTime
obj.setCreatedDate(createdDate.toLocalDateTime());

result.add(obj);

}
result.forEach(x -> System.out.println(x));

} catch (SQLException e) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
} catch (Exception e) {
e.printStackTrace();
}

}

}
Loading

0 comments on commit cac67b2

Please sign in to comment.