diff --git a/src/main/java/edu/group5/app/App.java b/src/main/java/edu/group5/app/App.java index 1f76250..6b74c18 100644 --- a/src/main/java/edu/group5/app/App.java +++ b/src/main/java/edu/group5/app/App.java @@ -1,6 +1,10 @@ package edu.group5.app; +import java.math.BigDecimal; +import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; import java.util.List; import edu.group5.app.control.wrapper.DbWrapper; @@ -12,11 +16,18 @@ public class App { public static void main(String[] args) throws InterruptedException { DbWrapper db = new DbWrapper(false); try { - System.out.println(db.connect()); + Object[] john = new Object[] {1, "Customer", "John", "Doe", "mail", "password"}; + List users = new ArrayList(); + users.add(john); + Object[] row = new Object[] { 1, 1, 39, new BigDecimal(20.0204), new Timestamp(new Date().getTime()), + "Paypal" }; + List data = new ArrayList(); - data.add(new Object[] { 2, 4, "Bernt", "Berntson", "berntberntson123@outlook.com", "wawawa" }); - System.out.println(db.importUsers().toString()); - System.out.println(db.exportUsers(data)); + data.add(row); + db.connect(); + db.exportUsers(users); + db.exportDonations(data); + System.out.println(Arrays.toString(db.importDonations(1).get(0))); } catch (Exception e) { System.out.println(e.getMessage()); } diff --git a/src/main/java/edu/group5/app/control/wrapper/DbWrapper.java b/src/main/java/edu/group5/app/control/wrapper/DbWrapper.java index b546c63..65196dc 100644 --- a/src/main/java/edu/group5/app/control/wrapper/DbWrapper.java +++ b/src/main/java/edu/group5/app/control/wrapper/DbWrapper.java @@ -8,7 +8,12 @@ import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; public class DbWrapper { protected Connection connection; @@ -17,6 +22,7 @@ public class DbWrapper { private String connectionString; private List users; private List donations; + private Logger logger = Logger.getLogger(DbWrapper.class.getName()); public DbWrapper(boolean test) { if (test) { @@ -24,108 +30,203 @@ public DbWrapper(boolean test) { } else { this.connectionString = CONNECTION_TYPE + "file:./help-me-help;" + DB_SCRIPT + "init.sql'"; } + this.logger.info("connectionString constructed"); } - public boolean connect() throws SQLException { + public boolean connect() { try { this.connection = DriverManager.getConnection(this.connectionString); - } catch (SQLException SQLe) { - System.out.println(SQLe.getMessage()); + if (this.connection.isValid(0)) { + this.logger.info("Database connected"); + return true; + } else { + this.logger.warning("Failed to connect to database"); + return false; + } + } catch (SQLException e) { + this.logger.log(Level.SEVERE, "Failed to connect to database due to exception", e); + return false; } - return connection.isValid(0); } - public List importUsers() throws SQLException { - PreparedStatement ps = this.connection.prepareStatement("SELECT * FROM users"); - ResultSet results = ps.executeQuery(); - List data = new ArrayList(); - while (results.next()) { - data.add( - new Object[] { - results.getInt("user_id"), - results.getString("role"), - results.getString("first_name"), - results.getString("last_name"), - results.getString("email"), - results.getString("password_hash") - }); - } - this.users = data; + public boolean disconnect() { + try{ this.connection.close(); } catch (Exception e) {}; + try { + return this.connection.isClosed(); + } catch (Exception e) { + this.logger.log(Level.WARNING, "Failed to check if connection is closed due to exception", e); + return false; + } + } + + private void close(ResultSet results, PreparedStatement ps) { + try { results.close(); } catch (Exception e) {} + try { ps.close(); } catch (Exception e) {} + this.logger.info("results and ps closed"); + } + + public List importUsers() { + PreparedStatement ps = null; + ResultSet results = null; + try{ + ps = this.connection.prepareStatement("SELECT * FROM users"); + results = ps.executeQuery(); + List data = new ArrayList(); + while (results.next()) { + data.add( + new Object[] { + results.getInt("user_id"), + results.getString("role"), + results.getString("first_name"), + results.getString("last_name"), + results.getString("email"), + results.getString("password_hash") + }); + } + this.users = data; + this.logger.info("Users imported"); + } catch (SQLException e) { + this.logger.log(Level.SEVERE, "Unexpected SQL exception", e); + } finally { + this.close(results, ps); + } return this.users; } - public int exportUsers(List data) throws SQLException { + public int exportUsers(List data) { + this.importUsers(); + if (data == null) { throw new IllegalArgumentException("data can't be null"); } if (data.get(0).length != 6) { throw new IllegalArgumentException("data's arrays must have a length of 6"); } - if ((int) data.getLast()[0] <= (int) this.users.getLast()[0]) { - throw new IllegalArgumentException("data can't contain existing rows"); + if (data.stream().anyMatch(i -> Arrays.asList(i).contains(null))) { + throw new IllegalArgumentException("One or more rows in data contains null values"); + } + if (this.users.size() > 0) { + if ((int) data.getLast()[0] <= (int) this.users.getLast()[0]) { + throw new IllegalArgumentException("data can't contain existing rows"); + } } + Set ids = new HashSet<>(); + if (data.stream().anyMatch(i -> !ids.add(i[0]))) { + throw new IllegalArgumentException("data can't contain duplicate rows"); + } + + + PreparedStatement ps = null; int rowsAffected = 0; - PreparedStatement ps = this.connection.prepareStatement( - "INSERT INTO users (user_id, role, first_name, last_name, email, password_hash) VALUES (?, ?, ?, ?, ?, ?)"); - for (Object[] row : data) { - try { - ps.setInt(1, (int) row[0]); - for (int i = 1; i < row.length; i++) { - ps.setString(i + 1, (String) row[i]); + try { + ps = this.connection.prepareStatement( + "INSERT INTO users (user_id, role, first_name, last_name, email, password_hash) VALUES (?, ?, ?, ?, ?, ?)"); + for (Object[] row : data) { + try { + ps.setInt(1, (int) row[0]); + for (int i = 1; i < row.length; i++) { + ps.setString(i + 1, (String) row[i]); + } + } catch (Exception e) { + throw new IllegalArgumentException("One or more rows in data contains a wrong datatype"); } - } catch (Exception e) { - throw new IllegalArgumentException("One or more rows in data contains a wrong datatype"); + rowsAffected += ps.executeUpdate(); } - rowsAffected = ps.executeUpdate(); + this.logger.info("Users exported"); + } catch (SQLException e) { + this.logger.log(Level.SEVERE, "Unexpected SQL exception", e); + } finally { + this.close(null, ps); } return rowsAffected; } - public List importDonations(int user_id) throws SQLException { - PreparedStatement ps = this.connection.prepareStatement("SELECT * FROM donations WHERE user_id = ?"); - ps.setInt(1, user_id); - ResultSet results = ps.executeQuery(); - List data = new ArrayList(); - while (results.next()) { - data.add( - new Object[] { - results.getInt(1), - results.getInt(2), - results.getInt(3), - results.getBigDecimal(4), - results.getTimestamp(5), - results.getString(6) - }); - } - this.donations = data; + private List importDonations() { + return this.importDonations(0, true); + } + + public List importDonations(int user_id) { + return this.importDonations(user_id, false); + } + + private List importDonations(int user_id, boolean all) { + PreparedStatement ps = null; + ResultSet results = null; + try{ + if (all) { + ps = this.connection.prepareStatement("SELECT * FROM donations"); + } else { + ps = this.connection.prepareStatement("SELECT * FROM donations WHERE user_id = ?"); + ps.setInt(1, user_id); + } + results = ps.executeQuery(); + List data = new ArrayList(); + while (results.next()) { + data.add( + new Object[] { + results.getInt(1), + results.getInt(2), + results.getInt(3), + results.getBigDecimal(4), + results.getTimestamp(5), + results.getString(6) + }); + } + this.donations = data; + this.logger.info("Donations imported"); + } catch (SQLException e) { + this.logger.log(Level.SEVERE, "Unexpected SQL exception", e); + } finally { + this.close(results, ps); + } return this.donations; } - public int exportDonations(List data) throws SQLException { + public int exportDonations(List data) { + this.importDonations(); + if (data == null) { throw new IllegalArgumentException("data can't be null"); } - if (data.get(0).length == 6) { + if (data.get(0).length != 6) { throw new IllegalArgumentException("data's arrays must have a length of 6"); } - if ((int) data.getLast()[0] <= (int) this.donations.getLast()[0]) { + if (data.stream().anyMatch(i -> Arrays.asList(i).contains(null))) { + throw new IllegalArgumentException("One or more rows in data contains null values"); + } + if (this.donations.size() > 0 && (int) data.getLast()[0] <= (int) this.donations.getLast()[0]) { throw new IllegalArgumentException("data can't contain existing rows"); } + Set ids = new HashSet<>(); + if (data.stream().anyMatch(i -> !ids.add(i[0]))) { + throw new IllegalArgumentException("data can't contain duplicate rows"); + } + + PreparedStatement ps = null; int rowsAffected = 0; - PreparedStatement ps = this.connection.prepareStatement( - "INSERT INTO donations (donation_id, user_id, organization_id, amount, dating, payment_method) VALUES (?, ?, ?, ?, ?, ?)"); - for (Object[] row : data) { - try { - for (int i = 0; i < 3; i++) { - ps.setInt(i + 1, (int) row[i]); + try { + ps = this.connection.prepareStatement( + "INSERT INTO donations (donation_id, user_id, organization_id, amount, dating, payment_method) VALUES (?, (SELECT user_id FROM users WHERE user_id = ?), ?, ?, ?, ?)"); + for (Object[] row : data) { + try { + for (int i = 0; i < 3; i++) { + ps.setInt(i + 1, (int) row[i]); + } + ps.setBigDecimal(4, (BigDecimal) row[3]); + ps.setTimestamp(5, (Timestamp) row[4]); + ps.setString(6, (String) row[5]); + } catch (Exception e) { + throw new IllegalArgumentException("One or more rows in data contains a wrong datatype"); } - ps.setBigDecimal(4, (BigDecimal) row[3]); - ps.setTimestamp(5, (Timestamp) row[4]); - } catch (Exception e) { - throw new IllegalArgumentException("One or more rows in data contains a wrong datatype"); + rowsAffected += ps.executeUpdate(); } - rowsAffected = ps.executeUpdate(); + this.logger.info("Donations exported"); + } catch (SQLException e) { + this.logger.log(Level.SEVERE, "Unexpected SQL exception", e); + } finally { + this.close(null, ps); } return rowsAffected; } + } diff --git a/src/main/resources/init.sql b/src/main/resources/init.sql index 26a48d6..8b99314 100644 --- a/src/main/resources/init.sql +++ b/src/main/resources/init.sql @@ -1,11 +1,11 @@ CREATE TABLE IF NOT EXISTS users ( user_id INT PRIMARY KEY, - role VARCHAR(32), - first_name VARCHAR(32), - last_name VARCHAR(32), - email VARCHAR(32), - password_hash VARCHAR(72) + role VARCHAR(32) NOT NULL, + first_name VARCHAR(32) NOT NULL, + last_name VARCHAR(32) NOT NULL, + email VARCHAR(32) NOT NULL, + password_hash VARCHAR(72) NOT NULL ); CREATE TABLE IF NOT EXISTS @@ -13,12 +13,11 @@ donations ( donation_id INT PRIMARY KEY, user_id INT NOT NULL, organization_id INT NOT NULL, - amount DECIMAL NOT NULL, + amount DECIMAL(32, 16) NOT NULL, dating TIMESTAMP NOT NULL, - payment_method VARCHAR(32), + payment_method VARCHAR(32) NOT NULL, CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(user_id) ); - diff --git a/src/main/resources/test_init.sql b/src/main/resources/test_init.sql index 40a8460..00670e8 100644 --- a/src/main/resources/test_init.sql +++ b/src/main/resources/test_init.sql @@ -3,11 +3,11 @@ DROP TABLE IF EXISTS users, donations; CREATE TABLE IF NOT EXISTS users ( user_id INT PRIMARY KEY, - role VARCHAR(20), - first_name VARCHAR(20), - last_name VARCHAR(20), - email VARCHAR(20), - password_hash VARCHAR(72) + role VARCHAR(32) NOT NULL, + first_name VARCHAR(32) NOT NULL, + last_name VARCHAR(32) NOT NULL, + email VARCHAR(32) NOT NULL, + password_hash VARCHAR(72) NOT NULL ); CREATE TABLE IF NOT EXISTS @@ -15,10 +15,10 @@ donations ( donation_id INT PRIMARY KEY, user_id INT NOT NULL, organization_id INT NOT NULL, - amount DECIMAL NOT NULL, + amount DECIMAL(32, 16) NOT NULL, dating TIMESTAMP NOT NULL, - payment_method VARCHAR(20), + payment_method VARCHAR(32) NOT NULL, CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(user_id) -);; +);