001package edu.pdx.cs.joy.jdbc;
002
003import java.sql.*;
004import java.util.ArrayList;
005import java.util.List;
006
007/**
008 * Data Access Object implementation for managing Department entities in the database.
009 * Demonstrates JDBC operations with auto-generated keys: CREATE, READ, UPDATE, DELETE.
010 */
011public class DepartmentDAOImpl implements DepartmentDAO {
012
013  private final Connection connection;
014
015  /**
016   * Creates a new DepartmentDAOImpl with the specified database connection.
017   *
018   * @param connection the database connection to use
019   */
020  public DepartmentDAOImpl(Connection connection) {
021    this.connection = connection;
022  }
023
024  /**
025   * Drops the departments table from the database if it exists.
026   *
027   * @param connection the database connection to use
028   * @throws SQLException if a database error occurs
029   */
030  public static void dropTable(Connection connection) throws SQLException {
031    try (Statement statement = connection.createStatement()) {
032      statement.execute("DROP TABLE IF EXISTS departments");
033    }
034  }
035
036  /**
037   * Creates the departments table in the database if it does not already exist.
038   *
039   * @param connection the database connection to use
040   * @throws SQLException if a database error occurs
041   */
042  public static void createTable(Connection connection) throws SQLException {
043    try (Statement statement = connection.createStatement()) {
044      statement.execute(
045        "CREATE TABLE IF NOT EXISTS departments (" +
046        "  id IDENTITY PRIMARY KEY," +
047        "  name VARCHAR(255) NOT NULL" +
048        ")"
049      );
050    }
051  }
052
053  /**
054   * Saves a department to the database.
055   * The department's ID will be automatically generated by the database.
056   *
057   * @param department the department to save
058   * @throws SQLException if a database error occurs
059   */
060  @Override
061  public void save(Department department) throws SQLException {
062    String sql = "INSERT INTO departments (name) VALUES (?)";
063
064    try (PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
065      statement.setString(1, department.getName());
066      statement.executeUpdate();
067
068      // Retrieve the auto-generated ID and set it on the department object
069      try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
070        if (generatedKeys.next()) {
071          int generatedId = generatedKeys.getInt(1);
072          department.setId(generatedId);
073        } else {
074          throw new SQLException("Creating department failed, no ID obtained.");
075        }
076      }
077    }
078  }
079
080  /**
081   * Finds a department by its ID.
082   *
083   * @param id the ID to search for
084   * @return the department with the given ID, or null if not found
085   * @throws SQLException if a database error occurs
086   */
087  @Override
088  public Department findById(int id) throws SQLException {
089    String sql = "SELECT id, name FROM departments WHERE id = ?";
090
091    try (PreparedStatement statement = connection.prepareStatement(sql)) {
092      statement.setInt(1, id);
093
094      try (ResultSet resultSet = statement.executeQuery()) {
095        if (resultSet.next()) {
096          return extractDepartmentFromResultSet(resultSet);
097        }
098      }
099    }
100
101    return null;
102  }
103
104  /**
105   * Finds a department by its name.
106   *
107   * @param name the name to search for
108   * @return the department with the given name, or null if not found
109   * @throws SQLException if a database error occurs
110   */
111  @Override
112  public Department findByName(String name) throws SQLException {
113    String sql = "SELECT id, name FROM departments WHERE name = ?";
114
115    try (PreparedStatement statement = connection.prepareStatement(sql)) {
116      statement.setString(1, name);
117
118      try (ResultSet resultSet = statement.executeQuery()) {
119        if (resultSet.next()) {
120          return extractDepartmentFromResultSet(resultSet);
121        }
122      }
123    }
124
125    return null;
126  }
127
128  /**
129   * Finds all departments in the database.
130   *
131   * @return a list of all departments
132   * @throws SQLException if a database error occurs
133   */
134  @Override
135  public List<Department> findAll() throws SQLException {
136    List<Department> departments = new ArrayList<>();
137    String sql = "SELECT id, name FROM departments ORDER BY id";
138
139    try (Statement statement = connection.createStatement();
140         ResultSet resultSet = statement.executeQuery(sql)) {
141      while (resultSet.next()) {
142        departments.add(extractDepartmentFromResultSet(resultSet));
143      }
144    }
145
146    return departments;
147  }
148
149  /**
150   * Extracts a Department object from the current row of a ResultSet.
151   *
152   * @param resultSet the result set positioned at a department row
153   * @return a Department object with data from the result set
154   * @throws SQLException if a database error occurs
155   */
156  private Department extractDepartmentFromResultSet(ResultSet resultSet) throws SQLException {
157    int id = resultSet.getInt("id");
158    String name = resultSet.getString("name");
159    return new Department(id, name);
160  }
161
162  /**
163   * Updates an existing department in the database.
164   *
165   * @param department the department to update
166   * @throws SQLException if a database error occurs
167   */
168  @Override
169  public void update(Department department) throws SQLException {
170    String sql = "UPDATE departments SET name = ? WHERE id = ?";
171
172    try (PreparedStatement statement = connection.prepareStatement(sql)) {
173      statement.setString(1, department.getName());
174      statement.setInt(2, department.getId());
175      int rowsAffected = statement.executeUpdate();
176
177      if (rowsAffected == 0) {
178        throw new SQLException("Update failed, no department found with ID: " + department.getId());
179      }
180    }
181  }
182
183  /**
184   * Deletes a department from the database by ID.
185   *
186   * @param id the ID of the department to delete
187   * @throws SQLException if a database error occurs
188   */
189  @Override
190  public void delete(int id) throws SQLException {
191    String sql = "DELETE FROM departments WHERE id = ?";
192
193    try (PreparedStatement statement = connection.prepareStatement(sql)) {
194      statement.setInt(1, id);
195      int rowsAffected = statement.executeUpdate();
196
197      if (rowsAffected == 0) {
198        throw new SQLException("Delete failed, no department found with ID: " + id);
199      }
200    }
201  }
202}
203
204