MovieBookingSystem/src/main/java/datamodel/Database.java
2024-02-09 09:17:22 +01:00

268 lines
9.6 KiB
Java
Executable file

package datamodel;
import java.sql.*;
import java.util.ArrayList;
/**
* Database is a class that specifies the interface to the
* movie database. Uses JDBC and the MySQL Connector/J driver.
*/
public class Database {
/**
* The database connection.
*/
private Connection conn;
/**
* Create the database interface object. Connection to the database
* is performed later.
*/
public Database() {
conn = null;
}
/**
* Open a connection to the database, using the specified user name
* and password.
*
* @param userName The user name.
* @param password The user's password.
* @return true if the connection succeeded, false if the supplied
* user name and password were not recognized. Returns false also
* if the JDBC driver isn't found.
*/
public boolean openConnection(String userName, String password) {
try {
// Connection strings for included DBMS clients:
// [MySQL] jdbc:mysql://[host]/[database]
// [PostgreSQL] jdbc:postgresql://[host]/[database]
// [SQLite] jdbc:sqlite://[filepath]
// Use "jdbc:mysql://puccini.cs.lth.se/" + userName if you using our shared server
// If outside, this statement will hang until timeout.
conn = DriverManager.getConnection
("jdbc:sqlite:movieBookings.db3", userName, password);
}
catch (SQLException e) {
System.err.println(e);
e.printStackTrace();
return false;
}
return true;
}
// Reads a file from the resources folder and returns the content as a string
private String readResourceFile(String fileName) {
String content = "";
try {
content = new String(getClass().getResourceAsStream(fileName).readAllBytes());
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
public void runMigration() {
// This path needs to start with a /
String migration = readResourceFile("/migration.sql");
try {
Statement stmt = conn.createStatement();
stmt.executeUpdate(migration);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* Close the connection to the database.
*/
public void closeConnection() {
try {
if (conn != null)
conn.close();
}
catch (SQLException e) {
e.printStackTrace();
}
conn = null;
System.err.println("Database connection closed.");
}
/**
* Check if the connection to the database has been established
*
* @return true if the connection has been established
*/
public boolean isConnected() {
return conn != null;
}
// Gets the Show object with the given title and date
public Show getShowData(String movie, String date) {
if (!isConnected()) {
System.err.println("getShowData: no connection to database");
return null;
}
try {
// Using prepared statements here to avoid injection, but this is never done anywhere else in this file
String query = "SELECT m.name AS movie_title, s.show_date, t.name AS theater_name, t.total_seats - COUNT(r.reservation_id) AS free_seats " +
"FROM Showings s " +
"JOIN Theaters t ON s.theater_id = t.theater_id " +
"JOIN Movies m ON s.movie_id = m.movie_id " +
"LEFT JOIN Reservations r ON s.showing_id = r.showing_id " +
"WHERE m.name = ? AND s.show_date = ? " +
"GROUP BY s.show_date, t.theater_id";
PreparedStatement pstmt = conn.prepareStatement(query);
pstmt.setString(1, movie);
pstmt.setString(2, date);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
String title = rs.getString("movie_title");
String showDate = rs.getString("show_date");
String venue = rs.getString("theater_name");
int freeSeats = rs.getInt("free_seats");
return new Show(title, showDate, venue, freeSeats);
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public ArrayList<Show> getAllShows() {
ArrayList<Show> shows = new ArrayList<Show>();
if(!isConnected()) {
System.err.println("getAllShows: no connection to database");
return shows;
}
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT *, Theaters.name AS theater_name FROM Showings JOIN Movies ON Showings.movie_id = Movies.movie_id JOIN Theaters ON Showings.theater_id = Theaters.theater_id");
while (rs.next()) {
String mTitle = rs.getString("name");
String mDate = rs.getString("show_date");
Integer mFreeSeats = rs.getInt("total_seats");
String mVenue = rs.getString("theater_name");
shows.add(new Show(mTitle, mDate, mVenue, mFreeSeats));
}
} catch (SQLException e) {
e.printStackTrace();
}
return shows;
}
public ArrayList<String> getDatesForMovie(String mTitle) {
ArrayList<String> dates = new ArrayList<String>();
if(!isConnected()) {
System.err.println("getDatesForMovie: no connection to database");
return dates;
}
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT show_date FROM Showings JOIN Movies ON Showings.movie_id = Movies.movie_id WHERE name = '" + mTitle + "'");
while (rs.next()) {
dates.add(rs.getString("show_date"));
}
} catch (SQLException e) {
e.printStackTrace();
}
return dates;
}
public boolean login(String username) {
if(!isConnected()) {
System.err.println("login: no connection to database");
return false;
}
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users WHERE username = '" + username + "'");
if (rs.next()) {
return true;
}
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
public Reservation addReservation(String username, String movie, String date) {
if(!isConnected()) {
System.err.println("addReservation: no connection to database");
return null;
}
System.out.println("Adding reservation for " + username + " for " + movie + " on " + date);
try(Statement stmt = conn.createStatement()) {
conn.setAutoCommit(false);
Show s = getShowData(movie, date);
if (s.getSeats() <= 0) {
System.err.println("addReservation: no free seats for " + movie + " on " + date);
return null;
}
ResultSet rs = stmt.executeQuery("SELECT * FROM Users WHERE username = '" + username + "'");
if (rs.next()) {
int user_id = rs.getInt("id");
rs = stmt.executeQuery("SELECT * FROM Showings JOIN Movies ON Showings.movie_id = Movies.movie_id WHERE name = '" + movie + "' AND show_date = '" + date + "'");
if (rs.next()) {
System.out.println("Adding reservation");
int showing_id = rs.getInt("showing_id");
String theater = rs.getString("theater_id");
stmt.executeUpdate("INSERT INTO Reservations (user_id, showing_id) VALUES (" + user_id + ", " + showing_id + ")");
System.out.println("Reservation added");
conn.commit();
conn.setAutoCommit(true);
int bookingId = stmt.getGeneratedKeys().getInt(1);
return new Reservation(bookingId, movie, date, theater);
}
rs.close();
}
else {
System.err.println(String.format("addReservation: user %s not found", username));
}
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e2) {
e2.printStackTrace();
}
e.printStackTrace();
}
return null;
}
public ArrayList<Reservation> getReservations(String username) {
ArrayList<Reservation> reservations = new ArrayList<Reservation>();
if(!isConnected()) {
System.err.println("getReservations: no connection to database");
return reservations;
}
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT *, Theaters.name AS theater_name FROM Reservations JOIN Showings ON Reservations.showing_id = Showings.showing_id JOIN Movies ON Showings.movie_id = Movies.movie_id JOIN Theaters ON Showings.theater_id = Theaters.theater_id JOIN users ON Reservations.user_id = Users.id WHERE username = '" + username + "'");
while (rs.next()) {
reservations.add(new Reservation(rs.getInt("reservation_id"), rs.getString("name"), rs.getString("show_date"), rs.getString("theater_name")));
}
} catch (SQLException e) {
e.printStackTrace();
}
return reservations;
}
}