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 Course entities in the database. 009 * Demonstrates basic JDBC operations: CREATE, READ, UPDATE. 010 */ 011public class CourseDAOImpl implements CourseDAO { 012 013 private final Connection connection; 014 015 /** 016 * Creates a new CourseDAOImpl with the specified database connection. 017 * 018 * @param connection the database connection to use 019 */ 020 public CourseDAOImpl(Connection connection) { 021 this.connection = connection; 022 } 023 024 /** 025 * Drops the courses 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 courses"); 033 } 034 } 035 036 /** 037 * Creates the courses table in the database. 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 courses (" + 046 " id IDENTITY PRIMARY KEY," + 047 " title VARCHAR(255) NOT NULL," + 048 " department_id INTEGER NOT NULL," + 049 " credits INTEGER NOT NULL," + 050 " FOREIGN KEY (department_id) REFERENCES departments(id)" + 051 ")" 052 ); 053 } 054 } 055 056 /** 057 * Saves a course to the database. 058 * The course's ID will be automatically generated by the database and set on the object. 059 * 060 * @param course the course to save 061 * @throws SQLException if a database error occurs 062 */ 063 @Override 064 public void save(Course course) throws SQLException { 065 String sql = "INSERT INTO courses (title, department_id, credits) VALUES (?, ?, ?)"; 066 067 try (PreparedStatement statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { 068 statement.setString(1, course.getTitle()); 069 statement.setInt(2, course.getDepartmentId()); 070 statement.setInt(3, course.getCredits()); 071 statement.executeUpdate(); 072 073 // Retrieve the auto-generated ID and set it on the course object 074 try (ResultSet generatedKeys = statement.getGeneratedKeys()) { 075 if (generatedKeys.next()) { 076 int generatedId = generatedKeys.getInt(1); 077 course.setId(generatedId); 078 } else { 079 throw new SQLException("Creating course failed, no ID obtained."); 080 } 081 } 082 } 083 } 084 085 /** 086 * Finds a course by its title. 087 * 088 * @param title the title to search for 089 * @return the course with the given title, or null if not found 090 * @throws SQLException if a database error occurs 091 */ 092 @Override 093 public Course findByTitle(String title) throws SQLException { 094 String sql = "SELECT id, title, department_id, credits FROM courses WHERE title = ?"; 095 096 try (PreparedStatement statement = connection.prepareStatement(sql)) { 097 statement.setString(1, title); 098 099 try (ResultSet resultSet = statement.executeQuery()) { 100 if (resultSet.next()) { 101 return extractCourseFromResultSet(resultSet); 102 } 103 } 104 } 105 106 return null; 107 } 108 109 /** 110 * Finds all courses associated with a specific department. 111 * 112 * @param departmentId the department ID to search for 113 * @return a list of courses in the department 114 * @throws SQLException if a database error occurs 115 */ 116 @Override 117 public List<Course> findByDepartmentId(int departmentId) throws SQLException { 118 List<Course> courses = new ArrayList<>(); 119 String sql = "SELECT id, title, department_id, credits FROM courses WHERE department_id = ?"; 120 121 try (PreparedStatement statement = connection.prepareStatement(sql)) { 122 statement.setInt(1, departmentId); 123 124 try (ResultSet resultSet = statement.executeQuery()) { 125 while (resultSet.next()) { 126 courses.add(extractCourseFromResultSet(resultSet)); 127 } 128 } 129 } 130 131 return courses; 132 } 133 134 /** 135 * Extracts a Course object from the current row of a ResultSet. 136 * 137 * @param resultSet the result set positioned at a course row 138 * @return a Course object with data from the result set 139 * @throws SQLException if a database error occurs 140 */ 141 private Course extractCourseFromResultSet(ResultSet resultSet) throws SQLException { 142 int id = resultSet.getInt("id"); 143 String title = resultSet.getString("title"); 144 int departmentId = resultSet.getInt("department_id"); 145 int credits = resultSet.getInt("credits"); 146 147 Course course = new Course(title, departmentId, credits); 148 course.setId(id); 149 return course; 150 } 151 152 /** 153 * Updates an existing course in the database. 154 * Uses the course's ID to identify which record to update. 155 * 156 * @param course the course to update 157 * @throws SQLException if a database error occurs 158 */ 159 @Override 160 public void update(Course course) throws SQLException { 161 String sql = "UPDATE courses SET title = ?, department_id = ?, credits = ? WHERE id = ?"; 162 163 try (PreparedStatement statement = connection.prepareStatement(sql)) { 164 statement.setString(1, course.getTitle()); 165 statement.setInt(2, course.getDepartmentId()); 166 statement.setInt(3, course.getCredits()); 167 statement.setInt(4, course.getId()); 168 169 int rowsAffected = statement.executeUpdate(); 170 if (rowsAffected == 0) { 171 throw new SQLException("Update failed, no course found with ID: " + course.getId()); 172 } 173 } 174 } 175} 176 177