From 247585d402eeb140d18489e03cead92413d546da Mon Sep 17 00:00:00 2001 From: Dagim02 Date: Wed, 3 Jun 2026 14:27:02 +0200 Subject: [PATCH 1/6] feat: add full library schema --- task-1/schema.sql | 66 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/task-1/schema.sql b/task-1/schema.sql index a3b443b..92d0ac9 100644 --- a/task-1/schema.sql +++ b/task-1/schema.sql @@ -1 +1,65 @@ --- Write here your DDL statements to create the tables for the database. \ No newline at end of file +-- Write here your DDL statements to create the tables for the database. +CREATE TABLE members ( + member_id SERIAL PRIMARY KEY, + email TEXT UNIQUE NOT NULL, + name TEXT NOT NULL, + phone TEXT, + address TEXT +); + +CREATE TABLE library_cards ( + card_id SERIAL PRIMARY KEY, + card_number TEXT UNIQUE NOT NULL, + issued_on DATE NOT NULL, + expires_on DATE NOT NULL CHECK (expires_on > issued_on), + member_id INT UNIQUE NOT NULL REFERENCES members(member_id) +); + +CREATE TABLE publishers ( + publisher_id SERIAL PRIMARY KEY, + name TEXT UNIQUE NOT NULL +); + +CREATE TABLE books ( + book_id SERIAL PRIMARY KEY, + isbn TEXT UNIQUE NOT NULL, + title TEXT NOT NULL, + publisher_id INT REFERENCES publishers(publisher_id) +); +CREATE TABLE authors ( + author_id SERIAL PRIMARY KEY, + name TEXT UNIQUE NOT NULL +); +CREATE TABLE book_authors ( + book_id INT NOT NULL REFERENCES books(book_id), + author_id INT NOT NULL REFERENCES authors(author_id), + PRIMARY KEY (book_id, author_id) +); +CREATE TABLE tags ( + tag_id SERIAL PRIMARY KEY, + name TEXT UNIQUE NOT NULL +); +CREATE TABLE book_tags ( + book_id INT NOT NULL REFERENCES books(book_id), + tag_id INT NOT NULL REFERENCES tags(tag_id), + PRIMARY KEY (book_id, tag_id) +); +CREATE TABLE copies ( + copy_id SERIAL PRIMARY KEY, + barcode TEXT UNIQUE NOT NULL, + shelf_code TEXT, + book_id INT NOT NULL REFERENCES books(book_id) +); + +CREATE TABLE borrowings ( + borrowing_id SERIAL PRIMARY KEY, + copy_id INT NOT NULL REFERENCES copies(copy_id), + member_id INT NOT NULL REFERENCES members(member_id), + borrowed_at TIMESTAMP NOT NULL, + due_date TIMESTAMP NOT NULL, + returned_at TIMESTAMP, + fine_eur NUMERIC DEFAULT 0 CHECK (fine_eur >= 0), + CHECK (returned_at IS NULL OR returned_at >= borrowed_at) +); + + From 3e1478bbed408a4f57c67d98cceba4ccdca70ca0 Mon Sep 17 00:00:00 2001 From: Dagim02 Date: Wed, 3 Jun 2026 15:42:27 +0200 Subject: [PATCH 2/6] feat: successfully create and initialize library_db with DDL --- task-1/schema.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/task-1/schema.sql b/task-1/schema.sql index 92d0ac9..5122d20 100644 --- a/task-1/schema.sql +++ b/task-1/schema.sql @@ -60,6 +60,7 @@ CREATE TABLE borrowings ( returned_at TIMESTAMP, fine_eur NUMERIC DEFAULT 0 CHECK (fine_eur >= 0), CHECK (returned_at IS NULL OR returned_at >= borrowed_at) + ); From ecdef79250a407400cb2ee0e6535d210e1a3cdda Mon Sep 17 00:00:00 2001 From: Dagim02 Date: Wed, 3 Jun 2026 16:36:16 +0200 Subject: [PATCH 3/6] setup: import JDBC tools, set up connection, and prepare insert/fetch methods --- task-2/src/main/java/org/hyf/Main.java | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/task-2/src/main/java/org/hyf/Main.java b/task-2/src/main/java/org/hyf/Main.java index 7be95f2..b21835a 100644 --- a/task-2/src/main/java/org/hyf/Main.java +++ b/task-2/src/main/java/org/hyf/Main.java @@ -1,7 +1,29 @@ package org.hyf; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.PreparedStatement; + public class Main { + + private static Connection getConnection() throws SQLException { + String url = "jdbc:postgresql://localhost:5432/library_db"; + String user = "postgres"; + String pass = "postgres"; + return DriverManager.getConnection(url, user, pass); + } + public static void insertData() { + + } + + public static void fetchData() { + + } + public static void main(String[] args) { - System.out.println("You code goes here :) You can overwrite this entire method."); + insertData(); + fetchData(); } } From 903c74868a8e49ef6d8d95fadcc69675fd7a05bb Mon Sep 17 00:00:00 2001 From: Dagim02 Date: Wed, 3 Jun 2026 16:55:02 +0200 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20implement=20and=20test=20insertData?= =?UTF-8?q?()=20with=202=20CSV=E2=80=91based=20rows=20per=20table?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- task-2/src/main/java/org/hyf/Main.java | 101 +++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/task-2/src/main/java/org/hyf/Main.java b/task-2/src/main/java/org/hyf/Main.java index b21835a..a487d3f 100644 --- a/task-2/src/main/java/org/hyf/Main.java +++ b/task-2/src/main/java/org/hyf/Main.java @@ -15,6 +15,107 @@ private static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, pass); } public static void insertData() { + try (Connection conn = getConnection()) { + + PreparedStatement pub = conn.prepareStatement( + "INSERT INTO publishers (name) VALUES (?) ON CONFLICT (name) DO NOTHING" + ); + pub.setString(1, "O'Reilly"); + pub.executeUpdate(); + pub.setString(1, "Addison-Wesley"); + pub.executeUpdate(); + PreparedStatement auth = conn.prepareStatement( + "INSERT INTO authors (name) VALUES (?) ON CONFLICT (name) DO NOTHING" + ); + auth.setString(1, "Douglas Crockford"); + auth.executeUpdate(); + auth.setString(1, "Eric Freeman"); + auth.executeUpdate(); + PreparedStatement book = conn.prepareStatement( + "INSERT INTO books (isbn, title, publisher_id) VALUES (?, ?, ?) ON CONFLICT (isbn) DO NOTHING" + ); + book.setString(1, "9780596517748"); + book.setString(2, "JavaScript: The Good Parts"); + book.setInt(3, 1); // O'Reilly + book.executeUpdate(); + + book.setString(1, "9780596007126"); + book.setString(2, "Head First Design Patterns"); + book.setInt(3, 1); // O'Reilly + book.executeUpdate(); + + PreparedStatement mem = conn.prepareStatement( + "INSERT INTO members (email, name, phone, address) VALUES (?, ?, ?, ?) ON CONFLICT (email) DO NOTHING" + ); + + mem.setString(1, "omar@example.com"); + mem.setString(2, "Omar"); + mem.setString(3, "+31689012345"); + mem.setString(4, "Rijnkade 19, Utrecht"); + mem.executeUpdate(); + + mem.setString(1, "tom@example.com"); + mem.setString(2, "Tom"); + mem.setString(3, "+31645678901"); + mem.setString(4, "Biltstraat 88, Utrecht"); + mem.executeUpdate(); + + PreparedStatement card = conn.prepareStatement( + "INSERT INTO library_cards (card_number, issued_on, expires_on, member_id) VALUES (?, ?, ?, ?) ON CONFLICT (card_number) DO NOTHING" + ); + + card.setString(1, "C-1008"); + card.setDate(2, java.sql.Date.valueOf("2024-01-30")); + card.setDate(3, java.sql.Date.valueOf("2027-01-30")); + card.setInt(4, 1); + card.executeUpdate(); + + card.setString(1, "C-1004"); + card.setDate(2, java.sql.Date.valueOf("2023-11-20")); + card.setDate(3, java.sql.Date.valueOf("2026-11-20")); + card.setInt(4, 2); + card.executeUpdate(); + + PreparedStatement copy = conn.prepareStatement( + "INSERT INTO copies (barcode, shelf_code, book_id) VALUES (?, ?, ?) ON CONFLICT (barcode) DO NOTHING" + ); + copy.setString(1, "BC-0011"); + copy.setString(2, "B-03"); + copy.setInt(3, 1); + copy.executeUpdate(); + + copy.setString(1, "BC-0013"); + copy.setString(2, "B-03"); + copy.setInt(3, 1); + copy.executeUpdate(); + + PreparedStatement bor = conn.prepareStatement( + "INSERT INTO borrowings (copy_id, member_id, borrowed_at, due_date, returned_at, fine_eur) " + + "VALUES (?, ?, ?, ?, ?, ?)" + ); + + bor.setInt(1, 1); + bor.setInt(2, 1); + bor.setTimestamp(3, java.sql.Timestamp.valueOf("2025-12-02 08:08:00")); + bor.setTimestamp(4, java.sql.Timestamp.valueOf("2025-12-23 08:08:00")); + bor.setTimestamp(5, java.sql.Timestamp.valueOf("2025-12-13 08:08:00")); + bor.setBigDecimal(6, new java.math.BigDecimal("0.00")); + bor.executeUpdate(); + + bor.setInt(1, 2); + bor.setInt(2, 2); + bor.setTimestamp(3, java.sql.Timestamp.valueOf("2026-01-10 08:51:00")); + bor.setTimestamp(4, java.sql.Timestamp.valueOf("2026-01-31 08:51:00")); + bor.setTimestamp(5, java.sql.Timestamp.valueOf("2026-01-25 08:51:00")); + bor.setBigDecimal(6, new java.math.BigDecimal("0.00")); + bor.executeUpdate(); + + System.out.println("Inserted 2 rows per table."); + + } catch (SQLException e) { + e.printStackTrace(); + + } } From b74a59c338f82c178653b74fe596d51efab88b45 Mon Sep 17 00:00:00 2001 From: Dagim02 Date: Wed, 3 Jun 2026 17:12:38 +0200 Subject: [PATCH 5/6] feat: implement fetchData() with JOIN query output --- task-2/src/main/java/org/hyf/Main.java | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/task-2/src/main/java/org/hyf/Main.java b/task-2/src/main/java/org/hyf/Main.java index a487d3f..7767d41 100644 --- a/task-2/src/main/java/org/hyf/Main.java +++ b/task-2/src/main/java/org/hyf/Main.java @@ -120,6 +120,51 @@ public static void insertData() { } public static void fetchData() { + String sql = """ + SELECT + b.title AS book_title, + p.name AS publisher_name, + c.barcode AS copy_barcode, + m.name AS member_name, + br.borrowed_at, + br.returned_at + FROM borrowings br + JOIN copies c ON br.copy_id = c.copy_id + JOIN books b ON c.book_id = b.book_id + JOIN publishers p ON b.publisher_id = p.publisher_id + JOIN members m ON br.member_id = m.member_id + ORDER BY br.borrowed_at + LIMIT 10 + """; + + try (Connection conn = getConnection(); + PreparedStatement ps = conn.prepareStatement(sql); + ResultSet rs = ps.executeQuery()) { + + System.out.println("\n BORROWING RECORDS "); + System.out.println("---------------------------"); + + while (rs.next()) { + String title = rs.getString("book_title"); + String publisher = rs.getString("publisher_name"); + String barcode = rs.getString("copy_barcode"); + String member = rs.getString("member_name"); + String borrowedAt = rs.getString("borrowed_at"); + String returnedAt = rs.getString("returned_at"); + + System.out.println( + "Book: " + title + + " | Publisher: " + publisher + + " | Copy: " + barcode + + " | Member: " + member + + " | Borrowed: " + borrowedAt + + " | Returned: " + returnedAt + ); + } + + } catch (SQLException e) { + e.printStackTrace(); + } } From 2ad606c098a53ca3176dd6b414213c67272c46da Mon Sep 17 00:00:00 2001 From: Dagim02 Date: Wed, 3 Jun 2026 17:29:27 +0200 Subject: [PATCH 6/6] docs: comment insertData() rows for better readability --- task-2/src/main/java/org/hyf/Main.java | 33 ++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/task-2/src/main/java/org/hyf/Main.java b/task-2/src/main/java/org/hyf/Main.java index 7767d41..fd97856 100644 --- a/task-2/src/main/java/org/hyf/Main.java +++ b/task-2/src/main/java/org/hyf/Main.java @@ -14,9 +14,12 @@ private static Connection getConnection() throws SQLException { String pass = "postgres"; return DriverManager.getConnection(url, user, pass); } + + // Inset Data public static void insertData() { try (Connection conn = getConnection()) { + // Publisher 2 rows PreparedStatement pub = conn.prepareStatement( "INSERT INTO publishers (name) VALUES (?) ON CONFLICT (name) DO NOTHING" ); @@ -24,76 +27,100 @@ public static void insertData() { pub.executeUpdate(); pub.setString(1, "Addison-Wesley"); pub.executeUpdate(); + + // Authors 2 rows PreparedStatement auth = conn.prepareStatement( "INSERT INTO authors (name) VALUES (?) ON CONFLICT (name) DO NOTHING" ); + + //row 1 auth.setString(1, "Douglas Crockford"); auth.executeUpdate(); + + //row 2 auth.setString(1, "Eric Freeman"); auth.executeUpdate(); + + // Books PreparedStatement book = conn.prepareStatement( "INSERT INTO books (isbn, title, publisher_id) VALUES (?, ?, ?) ON CONFLICT (isbn) DO NOTHING" ); + + // row 1 book.setString(1, "9780596517748"); book.setString(2, "JavaScript: The Good Parts"); - book.setInt(3, 1); // O'Reilly + book.setInt(3, 1); book.executeUpdate(); + // row 2 book.setString(1, "9780596007126"); book.setString(2, "Head First Design Patterns"); - book.setInt(3, 1); // O'Reilly + book.setInt(3, 1); book.executeUpdate(); + + // Members PreparedStatement mem = conn.prepareStatement( "INSERT INTO members (email, name, phone, address) VALUES (?, ?, ?, ?) ON CONFLICT (email) DO NOTHING" ); + //row 1 mem.setString(1, "omar@example.com"); mem.setString(2, "Omar"); mem.setString(3, "+31689012345"); mem.setString(4, "Rijnkade 19, Utrecht"); mem.executeUpdate(); + //row 2 mem.setString(1, "tom@example.com"); mem.setString(2, "Tom"); mem.setString(3, "+31645678901"); mem.setString(4, "Biltstraat 88, Utrecht"); mem.executeUpdate(); + // Library Cards PreparedStatement card = conn.prepareStatement( "INSERT INTO library_cards (card_number, issued_on, expires_on, member_id) VALUES (?, ?, ?, ?) ON CONFLICT (card_number) DO NOTHING" ); + // row 1 card.setString(1, "C-1008"); card.setDate(2, java.sql.Date.valueOf("2024-01-30")); card.setDate(3, java.sql.Date.valueOf("2027-01-30")); card.setInt(4, 1); card.executeUpdate(); + //row 2 card.setString(1, "C-1004"); card.setDate(2, java.sql.Date.valueOf("2023-11-20")); card.setDate(3, java.sql.Date.valueOf("2026-11-20")); card.setInt(4, 2); card.executeUpdate(); + // Copies PreparedStatement copy = conn.prepareStatement( "INSERT INTO copies (barcode, shelf_code, book_id) VALUES (?, ?, ?) ON CONFLICT (barcode) DO NOTHING" ); + + // row 1 copy.setString(1, "BC-0011"); copy.setString(2, "B-03"); copy.setInt(3, 1); copy.executeUpdate(); + //row 2 copy.setString(1, "BC-0013"); copy.setString(2, "B-03"); copy.setInt(3, 1); copy.executeUpdate(); + // Borrowings PreparedStatement bor = conn.prepareStatement( "INSERT INTO borrowings (copy_id, member_id, borrowed_at, due_date, returned_at, fine_eur) " + "VALUES (?, ?, ?, ?, ?, ?)" ); + // row 1 Omar bor.setInt(1, 1); bor.setInt(2, 1); bor.setTimestamp(3, java.sql.Timestamp.valueOf("2025-12-02 08:08:00")); @@ -102,6 +129,7 @@ public static void insertData() { bor.setBigDecimal(6, new java.math.BigDecimal("0.00")); bor.executeUpdate(); + //row 2 Tom bor.setInt(1, 2); bor.setInt(2, 2); bor.setTimestamp(3, java.sql.Timestamp.valueOf("2026-01-10 08:51:00")); @@ -119,6 +147,7 @@ public static void insertData() { } + // Fetch Data public static void fetchData() { String sql = """ SELECT