Skip to content

Commit

Permalink
Feat: Manager can only create tables if needed (for now)
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrianBalunan committed Mar 11, 2026
1 parent 8bce5de commit 609ca49
Showing 1 changed file with 10 additions and 171 deletions.
Original file line number Diff line number Diff line change
@@ -1,87 +1,27 @@
package ntnu.sytemutvikling.team6.database;

import ntnu.sytemutvikling.team6.DAO.APICharityData;
import ntnu.sytemutvikling.team6.scraper.APICharityData;

import java.sql.*;
import java.util.List;

/**
* Manages creation and synchronization of database tables in a MySQL database.
* Manages creation of MySQL tables (for now)
* <p>
* This class is responsible for establishing connections using environment variables
* This class is responsible for creating the tables needed for the application, if not done already
* and maintaining the {@code charities} table based on data retrieved from the IK API.
* </p>
*/

public class DatabaseManager {
private final String databaseURL;
private final String username;
private final String password;
private final DatabaseConnection connection;

/**
Constructs a new {@code DatabaseManager} using database credentials
* retrieved from system environment variables.
* <p>
* Required environment variables:
* <ul>
* <li>{@code HMH_DB_URL}</li>
* <li>{@code HMH_DB_USERNAME}</li>
* <li>{@code HMH_DB_PASSWORD}</li>
* </ul>
* </p>
*
* @throws IllegalStateException if either databaseURL, username, or password is {@code null} or blank
*/

// Values stored in system environment variables for security (using ntnu's phpmyadmin for this project)
public DatabaseManager() {
this.databaseURL = System.getenv("HMH_DB_URL");
this.username = System.getenv("HMH_DB_USERNAME");
this.password = System.getenv("HMH_DB_PASSWORD");

if (this.databaseURL == null || this.databaseURL.isBlank()) {
throw new IllegalStateException("Database environment variable URL has not been set");
}

if (this.username == null || this.username.isBlank()) {
throw new IllegalStateException("Username environment variable has not been set");
}

if (this.password == null || this.password.isBlank()) {
throw new IllegalStateException("Password environment variable has not been set");
}
}

/**
* Constructs a new {@code DatabaseManager} using database credentials
* <p>
* Used primarily for JUnit tests. Production should use the constructor
* using environment variables.
* </p>
*
* @param databaseURL the url to the database
* @param username the username used to log in to the database
* @param password the password used to log in to the database
* @throws IllegalArgumentException if databaseURL, username, or password is
* {@code null} or blank
* Contractor for DatabaseManager. It uses a DatabaseConnection object that contains a connection credentials
* using environment variables in the DatabaseConnection.
*/

public DatabaseManager(String databaseURL, String username, String password) {
this.databaseURL = databaseURL;
this.username = username;
this.password = password;

if (this.databaseURL == null || this.databaseURL.isBlank()) {
throw new IllegalArgumentException("Database environment variable URL has not been set");
}

if (this.username == null || this.username.isBlank()) {
throw new IllegalArgumentException("Username environment variable has not been set");
}

if (this.password == null || this.password.isBlank()) {
throw new IllegalArgumentException("Password environment variable has not been set");
}
public DatabaseManager(){
this.connection = new DatabaseConnection();
}

/**
Expand All @@ -92,7 +32,7 @@ public DatabaseManager(String databaseURL, String username, String password) {
* @throws RuntimeException if a {@link SQLException} occurs while creating the table
*/

public void createCharitiesTable() {
public void createTables() {
String sql_query = """
-- MySQL Workbench Forward Engineering
Expand Down Expand Up @@ -148,7 +88,7 @@ FOREIGN KEY (`Charities_UUID`)
""";

try (Connection conn = DriverManager.getConnection(databaseURL, username, password);
try (Connection conn = connection.getMySqlConnection();
Statement s = conn.createStatement()) {

s.execute(sql_query);
Expand All @@ -158,106 +98,5 @@ FOREIGN KEY (`Charities_UUID`)
}
}

/**
* Synchronizes the {@code charities} table with the provided list of APICharityData.
* <p>
* Summary of function:
* <ul>
* <li>Inserts new records</li>
* <li>Updates existing records using {@code ON DUPLICATE KEY UPDATE}</li>
* <li>Removes database records that are not present in the provided list</li>
* </ul>
* A temporary table is used to determine which records should be deleted.
* </p>
*
* @param charities a list of ApiCharityDaya objects
* @throws RuntimeException if a {@link SQLException} occurs during database synchronization
*/

public void updateCharities(List<APICharityData> charities) {
Connection conn = null;
try {
conn = DriverManager.getConnection(databaseURL, username, password);
conn.setAutoCommit(false);
// Inserts objects values into charities
String sql_query = """
INSERT INTO charities (org_number, name, status, url, is_pre_approved)
VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
status = VALUES(status),
url = VALUES(url),
is_pre_approved = VALUES(is_pre_approved)
""";

try (PreparedStatement s = conn.prepareStatement(sql_query)) {
for (APICharityData charity : charities) {
s.setString(1, charity.getOrg_number().replaceAll("\\s", ""));
s.setString(2, charity.getName());
s.setString(3, charity.getStatus());
s.setString(4, charity.getUrl());
s.setBoolean(5, charity.getIs_pre_approved());

s.addBatch();
}
s.executeBatch();
}


// Temporary table for parity check
sql_query = "CREATE TEMPORARY TABLE temp (org_number VARCHAR(100) PRIMARY KEY)";
try (PreparedStatement temp_create = conn.prepareStatement(sql_query)) {
temp_create.execute();
}

String sql_update_temp_table = "INSERT INTO temp (org_number) VALUES (?)";
try (PreparedStatement temp_update = conn.prepareStatement(sql_update_temp_table)) {
for (APICharityData charity : charities) {
temp_update.setString(1, charity.getOrg_number().replaceAll("\\s", ""));
temp_update.addBatch();
}
temp_update.executeBatch();
}



// Removes records not found in the list from charities table
sql_query = """
DELETE FROM charities c
WHERE NOT EXISTS (
SELECT 1
FROM temp t
WHERE c.org_number = t.org_number
)
""";

try (PreparedStatement delete_old_records = conn.prepareStatement(sql_query)){
delete_old_records.execute();
}

conn.commit();
} catch (SQLException e) {

if (conn != null) {
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}

e.printStackTrace();
throw new RuntimeException("ERROR: Something went wrong during updating charities table.");
} finally {
if (conn != null) {
try {
conn.setAutoCommit(true);
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

}
}

0 comments on commit 609ca49

Please sign in to comment.