Java Movie Database Tutorial: CRUD App with JDBC and Swing
This tutorial walks through building a simple desktop CRUD (Create, Read, Update, Delete) movie database using Java, JDBC for database access, and Swing for the GUI. It assumes Java 11+ and a relational database (SQLite for simplicity). You’ll get a working app with a movies table, forms to add/edit movies, and a list view with delete functionality.
What you’ll build
- SQLite database with a movies table
- Data Access Object (DAO) using JDBC
- Swing GUI: list of movies, add/edit form, delete action
- Basic validation and exception handling
Project setup
-
Create a Maven project (or plain Java project). Example Maven coordinates:
- GroupId: com.example
- ArtifactId: java-movie-db
- Java version: 11+
-
Add dependency for SQLite (if using Maven):
xml
<dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.42.0.0</version> </dependency>
Database schema (SQLite)
Create a file movies.db in the project root or let the app create it. SQL schema:
sql
CREATE TABLE IF NOT EXISTS movies ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, director TEXT, year INTEGER, genre TEXT, rating REAL );
Data model
Create a simple Movie class.
java
public class Movie { private int id; private String title; private String director; private Integer year; private String genre; private Double rating; // constructors, getters, setters, toString }
JDBC DAO
Create MovieDao with methods: initialize(), listAll(), findById(id), insert(movie), update(movie), delete(id). Example key methods:
java
import java.sql.*; import java.util.ArrayList; import java.util.List; public class MovieDao { private final String url = “jdbc:sqlite:movies.db”; public MovieDao() throws SQLException { initialize(); } public void initialize() throws SQLException { try (Connection conn = DriverManager.getConnection(url); Statement stmt = conn.createStatement()) { String sql = “CREATE TABLE IF NOT EXISTS movies (” + “id INTEGER PRIMARY KEY AUTOINCREMENT,” + “title TEXT NOT NULL,” + “director TEXT,” + “year INTEGER,” + “genre TEXT,” + “rating REAL)”; stmt.execute(sql); } } public List<Movie> listAll() throws SQLException { List<Movie> list = new ArrayList<>(); String sql = “SELECT id, title, director, year, genre, rating FROM movies ORDER BY title”; try (Connection conn = DriverManager.getConnection(url); PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { while (rs.next()) { Movie m = new Movie(); m.setId(rs.getInt(“id”)); m.setTitle(rs.getString(“title”)); m.setDirector(rs.getString(“director”)); int y = rs.getInt(“year”); m.setYear(rs.wasNull() ? null : y); m.setGenre(rs.getString(“genre”)); double r = rs.getDouble(“rating”); m.setRating(rs.wasNull() ? null : r); list.add(m); } } return list; } public Movie findById(int id) throws SQLException { String sql = “SELECT id, title, director, year, genre, rating FROM movies WHERE>; try (Connection conn = DriverManager.getConnection(url); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, id); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { Movie m = new Movie(); m.setId(rs.getInt(“id”)); m.setTitle(rs.getString(“title”)); m.setDirector(rs.getString(“director”)); int y = rs.getInt(“year”); m.setYear(rs.wasNull() ? null : y); m.setGenre(rs.getString(“genre”)); double r = rs.getDouble(“rating”); m.setRating(rs.wasNull() ? null : r); return m; } } } return null; } public void insert(Movie m) throws SQLException { String sql = “INSERT INTO movies(title,director,year,genre,rating) VALUES(?,?,?,?,?)”; try (Connection conn = DriverManager.getConnection(url); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, m.getTitle()); ps.setString(2, m.getDirector()); if (m.getYear() == null) ps.setNull(3, Types.INTEGER); else ps.setInt(3, m.getYear()); ps.setString(4, m.getGenre()); if (m.getRating() == null) ps.setNull(5, Types.REAL); else ps.setDouble(5, m.getRating()); ps.executeUpdate(); } } public void update(Movie m) throws SQLException { String sql = “UPDATE movies SET title=?, director=?, year=?, genre=?, rating=? WHERE>; try (Connection conn = DriverManager.getConnection(url); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, m.getTitle()); ps.setString(2, m.getDirector()); if (m.getYear() == null) ps.setNull(3, Types.INTEGER); else ps.setInt(3, m.getYear()); ps.setString(4, m.getGenre()); if (m.getRating() == null) ps.setNull(5, Types.REAL); else ps.setDouble(5, m.getRating()); ps.setInt(6, m.getId()); ps.executeUpdate(); } } public void delete(int id) throws SQLException { String sql = “DELETE FROM movies WHERE>; try (Connection conn = DriverManager.getConnection(url); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, id); ps.executeUpdate(); } } }
Swing GUI
Create a main frame with:
- JTable to list movies (backed by AbstractTableModel)
- Buttons: Add, Edit, Delete, Refresh
- Modal dialog for Add/Edit with input fields: title, director, year, genre, rating
Key parts:
- MovieTableModel extending AbstractTableModel to wrap List.
- MainFrame: loads list via MovieDao.listAll(), sets table model, wires button actions.
- Add/Edit Dialog: validates title required, year numeric (optional), rating between 0–10 (optional).
Example MovieTableModel skeleton:
java
public class MovieTableModel extends AbstractTableModel { private final List<Movie> movies; private final String[] cols = {“ID”,“Title”,“Director”,“Year”,“Genre”,“Rating”}; public MovieTableModel(List<Movie> movies) { this.movies = movies; } public int getRowCount() { return movies.size(); } public int getColumnCount() { return cols.length; } public String getColumnName(int c) { return cols[c]; } public Object getValueAt(int r, int c) { Movie m = movies.get(r); switch(c) { case 0: return m.getId(); case 1: return m.getTitle(); case 2: return m.getDirector(); case 3: return m.getYear(); case 4: return m.getGenre(); case 5: return m.getRating(); default: return null; } } public Movie getMovieAt(int row) { return movies.get(row); } }
MainFrame action examples:
- Add: open dialog, on OK call dao.insert(movie), refresh table.
- Edit: get selected row, open dialog populated, on OK call dao.update(movie), refresh.
- Delete: confirm, dao.delete(id), refresh.
- Refresh: reload list from dao and update model.
Simple Add/Edit dialog example
Use JDialog with JTextFields and JButtons. On OK parse and validate inputs, construct Movie, close and return.
Validation rules
- Title required (non-empty)
- Year optional; if provided must be integer between 1888 and current year (2026)
- Rating optional; if provided must be number 0.0–10.0
Error handling
- Show JOptionPane dialogs for SQL errors or validation failures.
- Use try-with-resources for JDBC.
- Keep UI responsive: for longer ops consider SwingWorker.
How to run
- Build with Maven: mvn package
- Run: java -cp target/java-movie-db.jar;path/to/sqlite-jdbc.jar com.example.MainFrame (Adjust classpath for your environment.)
Next steps / enhancements
- Use H2 or PostgreSQL for production.
- Add search/filtering, sorting, pagination.
- Replace Swing with JavaFX or convert to a REST API + web frontend.
- Add unit tests for DAO.
This provides the essentials to implement a CRUD Java Movie Database with JDBC and Swing. Use the provided DAO and table model patterns to complete the UI and behavior.
Leave a Reply