From 0e0dc19af04b2d32dd83e0bfdb7886ef07ebf404 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:03:04 +0000 Subject: [PATCH 01/23] add deadline --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5150e50f..05def9a9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/_uV8Mn8f) # 📘 Projektarbete: JPA + Hibernate med GitHub-flöde Projektet genomförs som antingen en Java CLI-applikation eller med hjälp av JavaFX om ni vill ha ett grafiskt gränssnitt. From 18fd14c8847af62ce16a2367d2cbef87a5310f37 Mon Sep 17 00:00:00 2001 From: youneslamia Date: Tue, 16 Dec 2025 09:00:38 +0100 Subject: [PATCH 02/23] -Composer och persistence --- docker-compose.yml | 18 ++++++++++++++++++ pom.xml | 5 +++++ src/main/java/org/example/entity/Booking.java | 4 ++++ .../java/org/example/entity/BookingTable.java | 4 ++++ src/main/java/org/example/entity/Guest.java | 4 ++++ .../java/org/example/entity/Restaurant.java | 4 ++++ src/main/resources/META-INF/persistence.xml | 19 +++++++++++++++++++ 7 files changed, 58 insertions(+) create mode 100644 docker-compose.yml create mode 100644 src/main/java/org/example/entity/Booking.java create mode 100644 src/main/java/org/example/entity/BookingTable.java create mode 100644 src/main/java/org/example/entity/Guest.java create mode 100644 src/main/java/org/example/entity/Restaurant.java create mode 100644 src/main/resources/META-INF/persistence.xml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..3d1e850f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3.8' + +services: + mysql: + image: mysql:9.5 + container_name: restaurant_booking_db + environment: + MYSQL_ROOT_PASSWORD: "" + MYSQL_ALLOW_EMPTY_PASSWORD: "yes" + MYSQL_DATABASE: restaurant_booking + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + restart: unless-stopped + +volumes: + mysql_data: diff --git a/pom.xml b/pom.xml index 909503d0..4b8ae85a 100644 --- a/pom.xml +++ b/pom.xml @@ -50,5 +50,10 @@ classgraph 4.8.184 + + jakarta.persistence + jakarta.persistence-api + 3.1.0 + diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java new file mode 100644 index 00000000..5d14de3c --- /dev/null +++ b/src/main/java/org/example/entity/Booking.java @@ -0,0 +1,4 @@ +package org.example.entity; + +public class Booking { +} diff --git a/src/main/java/org/example/entity/BookingTable.java b/src/main/java/org/example/entity/BookingTable.java new file mode 100644 index 00000000..30632fc6 --- /dev/null +++ b/src/main/java/org/example/entity/BookingTable.java @@ -0,0 +1,4 @@ +package org.example.entity; + +public class BookingTable { +} diff --git a/src/main/java/org/example/entity/Guest.java b/src/main/java/org/example/entity/Guest.java new file mode 100644 index 00000000..8150b2f8 --- /dev/null +++ b/src/main/java/org/example/entity/Guest.java @@ -0,0 +1,4 @@ +package org.example.entity; + +public class Guest { +} diff --git a/src/main/java/org/example/entity/Restaurant.java b/src/main/java/org/example/entity/Restaurant.java new file mode 100644 index 00000000..31829185 --- /dev/null +++ b/src/main/java/org/example/entity/Restaurant.java @@ -0,0 +1,4 @@ +package org.example.entity; + +public class Restaurant { +} diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml new file mode 100644 index 00000000..2718d348 --- /dev/null +++ b/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + From 556f0c0c03d6a5781df03f9cb6da276bed2fb2ae Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Tue, 16 Dec 2025 11:45:57 +0100 Subject: [PATCH 03/23] Table genesis --- README.md | 4 +- pom.xml | 4 +- src/main/java/org/example/App.java | 30 ++++++++++++- src/main/java/org/example/entity/Booking.java | 44 +++++++++++++++++++ .../java/org/example/entity/BookingTable.java | 31 +++++++++++++ src/main/java/org/example/entity/Guest.java | 33 ++++++++++++++ src/main/resources/META-INF/persistence.xml | 5 ++- 7 files changed, 144 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 05def9a9..c06fd23c 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ Kommunikation med databasen ska ske med JPA och Hibernate, enligt code first-met ## 🗓️ Veckoplanering med Checklista ### ✅ Vecka 1 – Grundläggning och struktur -- [ ] Klona GitHub-repo -- [ ] Konfigurera persistence.xml eller använd PersistenceConfiguration i kod +- [x] Klona GitHub-repo +- [x] Konfigurera persistence.xml eller använd PersistenceConfiguration i kod - [ ] Skapa entiteter och verifiera tabellgenerering - [ ] Lägg till relationer (One-to-Many, Many-to-Many) - [ ] Arbeta på feature-branches och använd pull requests för kodgranskning diff --git a/pom.xml b/pom.xml index 4b8ae85a..0a5d65e5 100644 --- a/pom.xml +++ b/pom.xml @@ -37,12 +37,12 @@ org.hibernate.orm hibernate-core - 7.2.0.Final + 6.4.4.Final com.mysql mysql-connector-j - 9.5.0 + 8.3.0 runtime diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 165e5cd5..0195d1c9 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -1,7 +1,33 @@ package org.example; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.Persistence; +import org.example.entity.Booking; +import org.example.entity.BookingTable; +import org.example.entity.Guest; + +import java.time.LocalDateTime; + public class App { - public static void main(String[] args) { - System.out.println("Hello There!"); + static void main(String[] args) { + + EntityManagerFactory emf = Persistence.createEntityManagerFactory("restaurantPU"); + EntityManager em = emf.createEntityManager(); + + try{ + em.getTransaction().begin(); + //BookingTable bookingTable = new BookingTable(6, 8); + //Booking booking = new Booking(0 ,LocalDateTime.now(), 5); + Guest guest = new Guest(); + em.persist(guest); + em.getTransaction().commit(); + } catch (Exception e){ + em.getTransaction().rollback(); + e.printStackTrace(); + } finally { + em.close(); + emf.close(); + } } } diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index 5d14de3c..d4a3a149 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -1,4 +1,48 @@ package org.example.entity; +import jakarta.persistence.*; + +import java.time.LocalDateTime; + +@Entity +@Table(name="bookings") + public class Booking { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne +// @JoinColumn(name="table_id", nullable = false) + private BookingTable tableId; + +// @ManyToMany(mappedBy = "guest") +// @JoinTable(name="guest_id", +// joinColumns = @JoinColumn(name = "booking_id"), +// inverseJoinColumns = @JoinColumn(name= "guest_id")) +// private Guest guestId; + + @Column(name="Booking_Time", nullable = false) + private LocalDateTime time; + + @Column(name="Party", nullable = false) + private int party; + + public Booking(int tableId, LocalDateTime time, int party){ + //this.tableId = tableId; + this.time = time; + this. party = party; + } + + public Booking() {} + + + public void setId(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + } diff --git a/src/main/java/org/example/entity/BookingTable.java b/src/main/java/org/example/entity/BookingTable.java index 30632fc6..c1449086 100644 --- a/src/main/java/org/example/entity/BookingTable.java +++ b/src/main/java/org/example/entity/BookingTable.java @@ -1,4 +1,35 @@ package org.example.entity; +import jakarta.persistence.*; + + +@Entity +@Table(name = "tables") + public class BookingTable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name="table_number", nullable = false, unique = true) + private int tableNumber; + + @Column(name="Capacity", nullable = false) + private int capacity; + + public BookingTable( int capacity, int tableNumber){ + this.capacity = capacity; + this.tableNumber = tableNumber; + } + + public BookingTable() {} + + public void setId(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + } diff --git a/src/main/java/org/example/entity/Guest.java b/src/main/java/org/example/entity/Guest.java index 8150b2f8..6814df01 100644 --- a/src/main/java/org/example/entity/Guest.java +++ b/src/main/java/org/example/entity/Guest.java @@ -1,4 +1,37 @@ package org.example.entity; +import jakarta.persistence.*; + +@Entity +@Table(name = "Guests") + public class Guest { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name="booking_id", nullable = false) + private Booking bookingId; + + @Column(name="Name", nullable = false) + private String name; + + @Column(name="Note", nullable = false) + private String note; + + @Column(name="Contact_info", nullable = false) + private String contact; + + public Guest(){} + + public void setId(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + } diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 2718d348..490ef653 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -1,6 +1,9 @@ + org.example.entity.BookingTable + org.example.entity.Booking + org.example.entity.Guest @@ -11,7 +14,7 @@ - + From 8849fbef59a5c5b934918b18147bf8fd3c33201a Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Tue, 16 Dec 2025 13:59:38 +0100 Subject: [PATCH 04/23] Implimentation of connections --- README.md | 2 +- src/main/java/org/example/App.java | 8 +++--- src/main/java/org/example/entity/Booking.java | 15 +++++++---- .../entity/{BookingTable.java => Table.java} | 27 ++++++++++++++++--- src/main/resources/META-INF/persistence.xml | 2 +- 5 files changed, 39 insertions(+), 15 deletions(-) rename src/main/java/org/example/entity/{BookingTable.java => Table.java} (51%) diff --git a/README.md b/README.md index c06fd23c..bbb12a3e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Kommunikation med databasen ska ske med JPA och Hibernate, enligt code first-met ### ✅ Vecka 1 – Grundläggning och struktur - [x] Klona GitHub-repo - [x] Konfigurera persistence.xml eller använd PersistenceConfiguration i kod -- [ ] Skapa entiteter och verifiera tabellgenerering +- [x] Skapa entiteter och verifiera tabellgenerering - [ ] Lägg till relationer (One-to-Many, Many-to-Many) - [ ] Arbeta på feature-branches och använd pull requests för kodgranskning diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 0195d1c9..24be8eb2 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -4,7 +4,7 @@ import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; import org.example.entity.Booking; -import org.example.entity.BookingTable; +import org.example.entity.Table; import org.example.entity.Guest; import java.time.LocalDateTime; @@ -18,9 +18,9 @@ static void main(String[] args) { try{ em.getTransaction().begin(); //BookingTable bookingTable = new BookingTable(6, 8); - //Booking booking = new Booking(0 ,LocalDateTime.now(), 5); - Guest guest = new Guest(); - em.persist(guest); + Booking booking = new Booking(2L ,LocalDateTime.now(), 6); + //Guest guest = new Guest(); + em.persist(booking); em.getTransaction().commit(); } catch (Exception e){ em.getTransaction().rollback(); diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index d4a3a149..d9589451 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -1,7 +1,6 @@ package org.example.entity; import jakarta.persistence.*; - import java.time.LocalDateTime; @Entity @@ -13,8 +12,10 @@ public class Booking { private Long id; @ManyToOne -// @JoinColumn(name="table_id", nullable = false) - private BookingTable tableId; + @JoinColumn(name="TableId", nullable = false) + private Table table; + + // @ManyToMany(mappedBy = "guest") // @JoinTable(name="guest_id", @@ -22,14 +23,18 @@ public class Booking { // inverseJoinColumns = @JoinColumn(name= "guest_id")) // private Guest guestId; + + @Column(nullable = false) + private long tableId; + @Column(name="Booking_Time", nullable = false) private LocalDateTime time; @Column(name="Party", nullable = false) private int party; - public Booking(int tableId, LocalDateTime time, int party){ - //this.tableId = tableId; + public Booking(Long tableId, LocalDateTime time, int party){ + this.tableId = tableId; this.time = time; this. party = party; } diff --git a/src/main/java/org/example/entity/BookingTable.java b/src/main/java/org/example/entity/Table.java similarity index 51% rename from src/main/java/org/example/entity/BookingTable.java rename to src/main/java/org/example/entity/Table.java index c1449086..1eee8d4b 100644 --- a/src/main/java/org/example/entity/BookingTable.java +++ b/src/main/java/org/example/entity/Table.java @@ -2,27 +2,46 @@ import jakarta.persistence.*; +import java.util.ArrayList; +import java.util.List; + @Entity -@Table(name = "tables") +@Table(name = "Tables") -public class BookingTable { +public class Table { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @ManyToOne + @JoinColumn(name = "table_id") + private Table table; + + @OneToMany(mappedBy = "table", cascade = CascadeType.PERSIST) + private List bookings = new ArrayList<>(); + + @Column(name="table_number", nullable = false, unique = true) private int tableNumber; @Column(name="Capacity", nullable = false) private int capacity; - public BookingTable( int capacity, int tableNumber){ + public Table getTable() { + return table; + } + + public void setTable(Table table) { + this.table = table; + } + + public Table( int capacity, int tableNumber){ this.capacity = capacity; this.tableNumber = tableNumber; } - public BookingTable() {} + public Table() {} public void setId(Long id) { this.id = id; diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 490ef653..f4bd5f4d 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -1,7 +1,7 @@ - org.example.entity.BookingTable + org.example.entity.Table org.example.entity.Booking org.example.entity.Guest From 8f680f6e45038073288771de4940a66d0c8f5c4c Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:51:29 +0100 Subject: [PATCH 05/23] Name changes --- src/main/java/org/example/App.java | 2 -- src/main/java/org/example/entity/Booking.java | 2 +- .../{Table.java => RestaurantTable.java} | 20 +++++++++---------- src/main/resources/META-INF/persistence.xml | 2 +- 4 files changed, 12 insertions(+), 14 deletions(-) rename src/main/java/org/example/entity/{Table.java => RestaurantTable.java} (62%) diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 24be8eb2..2a0c215b 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -4,8 +4,6 @@ import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; import org.example.entity.Booking; -import org.example.entity.Table; -import org.example.entity.Guest; import java.time.LocalDateTime; diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index d9589451..54c6ab9b 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -13,7 +13,7 @@ public class Booking { @ManyToOne @JoinColumn(name="TableId", nullable = false) - private Table table; + private RestaurantTable restaurantTable; diff --git a/src/main/java/org/example/entity/Table.java b/src/main/java/org/example/entity/RestaurantTable.java similarity index 62% rename from src/main/java/org/example/entity/Table.java rename to src/main/java/org/example/entity/RestaurantTable.java index 1eee8d4b..f8a90e1d 100644 --- a/src/main/java/org/example/entity/Table.java +++ b/src/main/java/org/example/entity/RestaurantTable.java @@ -7,16 +7,16 @@ @Entity -@Table(name = "Tables") +@Table(name = "restaurant_tables") -public class Table { +public class RestaurantTable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne @JoinColumn(name = "table_id") - private Table table; + private RestaurantTable restaurantTable; @OneToMany(mappedBy = "table", cascade = CascadeType.PERSIST) private List bookings = new ArrayList<>(); @@ -25,23 +25,23 @@ public class Table { @Column(name="table_number", nullable = false, unique = true) private int tableNumber; - @Column(name="Capacity", nullable = false) + @Column(name="capacity", nullable = false) private int capacity; - public Table getTable() { - return table; + public RestaurantTable getTable() { + return restaurantTable; } - public void setTable(Table table) { - this.table = table; + public void setTable(RestaurantTable restaurantTable) { + this.restaurantTable = restaurantTable; } - public Table( int capacity, int tableNumber){ + public RestaurantTable(int capacity, int tableNumber){ this.capacity = capacity; this.tableNumber = tableNumber; } - public Table() {} + public RestaurantTable() {} public void setId(Long id) { this.id = id; diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index f4bd5f4d..3176e18d 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -1,7 +1,7 @@ - org.example.entity.Table + org.example.entity.RestaurantTable org.example.entity.Booking org.example.entity.Guest From c08cf1e793a098f3aac1d53f7ee425dee992f368 Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Thu, 18 Dec 2025 10:13:08 +0100 Subject: [PATCH 06/23] Stuff --- .gitignore | 1 + src/main/java/org/example/entity/Booking.java | 12 ++++++------ src/main/java/org/example/entity/Guest.java | 6 ++++++ .../java/org/example/entity/RestaurantTable.java | 15 ++------------- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 6ac465db..d59149fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ /.idea/ +docker-compose.yml diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index 54c6ab9b..56220896 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -12,16 +12,16 @@ public class Booking { private Long id; @ManyToOne - @JoinColumn(name="TableId", nullable = false) + @JoinColumn(name="tableId", nullable = false) private RestaurantTable restaurantTable; -// @ManyToMany(mappedBy = "guest") -// @JoinTable(name="guest_id", -// joinColumns = @JoinColumn(name = "booking_id"), -// inverseJoinColumns = @JoinColumn(name= "guest_id")) -// private Guest guestId; + @ManyToMany(mappedBy = "guest") + @JoinTable(name="guest_id", + joinColumns = @JoinColumn(name = "booking_id"), + inverseJoinColumns = @JoinColumn(name= "guest_id")) + private Guest guestId; @Column(nullable = false) diff --git a/src/main/java/org/example/entity/Guest.java b/src/main/java/org/example/entity/Guest.java index 6814df01..11a74366 100644 --- a/src/main/java/org/example/entity/Guest.java +++ b/src/main/java/org/example/entity/Guest.java @@ -23,6 +23,12 @@ public class Guest { @Column(name="Contact_info", nullable = false) private String contact; + public Guest(String name, String note, String contact){ + this.name = name; + this.note = note; + this.contact = contact; + } + public Guest(){} public void setId(Long id) { diff --git a/src/main/java/org/example/entity/RestaurantTable.java b/src/main/java/org/example/entity/RestaurantTable.java index f8a90e1d..ec2bda80 100644 --- a/src/main/java/org/example/entity/RestaurantTable.java +++ b/src/main/java/org/example/entity/RestaurantTable.java @@ -14,29 +14,18 @@ public class RestaurantTable { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne - @JoinColumn(name = "table_id") - private RestaurantTable restaurantTable; - @OneToMany(mappedBy = "table", cascade = CascadeType.PERSIST) private List bookings = new ArrayList<>(); @Column(name="table_number", nullable = false, unique = true) - private int tableNumber; + private String tableNumber; @Column(name="capacity", nullable = false) private int capacity; - public RestaurantTable getTable() { - return restaurantTable; - } - - public void setTable(RestaurantTable restaurantTable) { - this.restaurantTable = restaurantTable; - } - public RestaurantTable(int capacity, int tableNumber){ + public RestaurantTable(int capacity, String tableNumber){ this.capacity = capacity; this.tableNumber = tableNumber; } From 6013ee10c085b914ff80639f94a08e5231aa68ec Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Thu, 18 Dec 2025 10:17:28 +0100 Subject: [PATCH 07/23] App Try changes --- src/main/java/org/example/App.java | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 2a0c215b..1e36b998 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -10,22 +10,22 @@ public class App { static void main(String[] args) { - EntityManagerFactory emf = Persistence.createEntityManagerFactory("restaurantPU"); - EntityManager em = emf.createEntityManager(); + try (EntityManagerFactory emf = Persistence.createEntityManagerFactory("restaurantPU"); + EntityManager em = emf.createEntityManager()) { - try{ - em.getTransaction().begin(); - //BookingTable bookingTable = new BookingTable(6, 8); - Booking booking = new Booking(2L ,LocalDateTime.now(), 6); - //Guest guest = new Guest(); - em.persist(booking); - em.getTransaction().commit(); - } catch (Exception e){ - em.getTransaction().rollback(); + try { + em.getTransaction().begin(); + //BookingTable bookingTable = new BookingTable(6, 8); + Booking booking = new Booking(2L, LocalDateTime.now(), 6); + //Guest guest = new Guest(); + em.persist(booking); + em.getTransaction().commit(); + } catch (Exception e) { + em.getTransaction().rollback(); + e.printStackTrace(); + } + } catch (Exception e) { e.printStackTrace(); - } finally { - em.close(); - emf.close(); } } } From c49ab4915e421e44fa0f19f7f25d6c95298e385d Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Thu, 18 Dec 2025 10:43:45 +0100 Subject: [PATCH 08/23] Relationer --- README.md | 4 +- src/main/java/org/example/App.java | 2 +- src/main/java/org/example/entity/Booking.java | 79 +++++++++++++++---- src/main/java/org/example/entity/Guest.java | 44 ++++++++++- .../org/example/entity/RestaurantTable.java | 28 ++++++- 5 files changed, 131 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index bbb12a3e..2ab82cb2 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ Kommunikation med databasen ska ske med JPA och Hibernate, enligt code first-met - [x] Klona GitHub-repo - [x] Konfigurera persistence.xml eller använd PersistenceConfiguration i kod - [x] Skapa entiteter och verifiera tabellgenerering -- [ ] Lägg till relationer (One-to-Many, Many-to-Many) -- [ ] Arbeta på feature-branches och använd pull requests för kodgranskning +- [x] Lägg till relationer (One-to-Many, Many-to-Many) +- [x] Arbeta på feature-branches och använd pull requests för kodgranskning ### ✅ Vecka 2 – Funktionalitet och relationer - [ ] Dela upp funktioner mellan gruppmedlemmar diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 1e36b998..333df2a3 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -16,7 +16,7 @@ static void main(String[] args) { try { em.getTransaction().begin(); //BookingTable bookingTable = new BookingTable(6, 8); - Booking booking = new Booking(2L, LocalDateTime.now(), 6); + Booking booking = new Booking(); //Guest guest = new Guest(); em.persist(booking); em.getTransaction().commit(); diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index 56220896..9da9c7ca 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -2,45 +2,85 @@ import jakarta.persistence.*; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Entity @Table(name="bookings") public class Booking { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne - @JoinColumn(name="tableId", nullable = false) - private RestaurantTable restaurantTable; + @Column(name="booking_Time", nullable = false) + private LocalDateTime time; + @Column(name="party_size", nullable = false) + private int party; + @ManyToOne + @JoinColumn(name="table_id", nullable = false) + private RestaurantTable table; - @ManyToMany(mappedBy = "guest") - @JoinTable(name="guest_id", + @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) + @JoinTable( + name = "booking_guests", joinColumns = @JoinColumn(name = "booking_id"), - inverseJoinColumns = @JoinColumn(name= "guest_id")) - private Guest guestId; + inverseJoinColumns = @JoinColumn (name = "guest_id")) + private List guests = new ArrayList<>(); + + public Booking(RestaurantTable table, LocalDateTime time, int party){ + this.table = table; + this.time = time; + this.party = party; + } + public void addGuest(Guest guest){ + guests.add(guest); + guest.getBookings().add(this); + } - @Column(nullable = false) - private long tableId; + public void removeGuest(Guest guest){ + guests.remove(guest); + guest.getBookings().remove(this); + } - @Column(name="Booking_Time", nullable = false) - private LocalDateTime time; + public Booking() {} - @Column(name="Party", nullable = false) - private int party; + public LocalDateTime getTime() { + return time; + } - public Booking(Long tableId, LocalDateTime time, int party){ - this.tableId = tableId; + public void setTime(LocalDateTime time) { this.time = time; - this. party = party; } - public Booking() {} + public int getParty() { + return party; + } + + public void setParty(int party) { + this.party = party; + } + + public RestaurantTable getTable() { + return table; + } + public void setTable(RestaurantTable table) { + this.table = table; + } + + public List getGuests() { + return guests; + } + + public void setGuests(List guests) { + this.guests = guests; + } public void setId(Long id) { this.id = id; @@ -50,4 +90,9 @@ public Long getId() { return id; } + @Override + public String toString(){ + return "Booking id = " + id + ", time = " + time + ", party = " + party + ", table = " + (table != null ? table.getTableNumber() : "N/A") + "."; + } + } diff --git a/src/main/java/org/example/entity/Guest.java b/src/main/java/org/example/entity/Guest.java index 11a74366..d7e948a1 100644 --- a/src/main/java/org/example/entity/Guest.java +++ b/src/main/java/org/example/entity/Guest.java @@ -2,6 +2,9 @@ import jakarta.persistence.*; +import java.util.ArrayList; +import java.util.List; + @Entity @Table(name = "Guests") @@ -10,10 +13,6 @@ public class Guest { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne - @JoinColumn(name="booking_id", nullable = false) - private Booking bookingId; - @Column(name="Name", nullable = false) private String name; @@ -23,6 +22,9 @@ public class Guest { @Column(name="Contact_info", nullable = false) private String contact; + @ManyToMany(mappedBy = "guests") + private List bookings = new ArrayList<>(); + public Guest(String name, String note, String contact){ this.name = name; this.note = note; @@ -31,6 +33,40 @@ public Guest(String name, String note, String contact){ public Guest(){} + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + public String getNote() { + return note; + } + + public void setNote(String note) { + this.note = note; + } + + public String getContact() { + return contact; + } + + public void setContact(String contact) { + this.contact = contact; + } + + public List getBookings() { + return bookings; + } + + public void setBookings(List bookings) { + this.bookings = bookings; + } + public void setId(Long id) { this.id = id; } diff --git a/src/main/java/org/example/entity/RestaurantTable.java b/src/main/java/org/example/entity/RestaurantTable.java index ec2bda80..856b5faa 100644 --- a/src/main/java/org/example/entity/RestaurantTable.java +++ b/src/main/java/org/example/entity/RestaurantTable.java @@ -7,14 +7,14 @@ @Entity -@Table(name = "restaurant_tables") +@Table(name = "restaurant_table") public class RestaurantTable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToMany(mappedBy = "table", cascade = CascadeType.PERSIST) + @OneToMany(mappedBy = "restaurant_table", cascade = CascadeType.PERSIST) private List bookings = new ArrayList<>(); @@ -30,6 +30,30 @@ public RestaurantTable(int capacity, String tableNumber){ this.tableNumber = tableNumber; } + public List getBookings() { + return bookings; + } + + public void setBookings(List bookings) { + this.bookings = bookings; + } + + public String getTableNumber() { + return tableNumber; + } + + public void setTableNumber(String tableNumber) { + this.tableNumber = tableNumber; + } + + public int getCapacity() { + return capacity; + } + + public void setCapacity(int capacity) { + this.capacity = capacity; + } + public RestaurantTable() {} public void setId(Long id) { From 4e61a618f6a6ceef0e2f9a2117f8140c0818dcab Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:17:37 +0100 Subject: [PATCH 09/23] Stuff #2 --- src/main/java/org/example/App.java | 10 +++++++--- src/main/java/org/example/entity/RestaurantTable.java | 2 +- src/main/resources/META-INF/persistence.xml | 5 +---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 333df2a3..cf262668 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -4,6 +4,8 @@ import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; import org.example.entity.Booking; +import org.example.entity.Guest; +import org.example.entity.RestaurantTable; import java.time.LocalDateTime; @@ -15,9 +17,11 @@ static void main(String[] args) { try { em.getTransaction().begin(); - //BookingTable bookingTable = new BookingTable(6, 8); - Booking booking = new Booking(); - //Guest guest = new Guest(); + RestaurantTable table = new RestaurantTable(8, "Table 8"); + em.persist(table); + Guest guest = new Guest("John Smith", "N/A", "johnsmith.email.com"); + em.persist(guest); + Booking booking = new Booking(table, LocalDateTime.now(), 5); em.persist(booking); em.getTransaction().commit(); } catch (Exception e) { diff --git a/src/main/java/org/example/entity/RestaurantTable.java b/src/main/java/org/example/entity/RestaurantTable.java index 856b5faa..bdd1a848 100644 --- a/src/main/java/org/example/entity/RestaurantTable.java +++ b/src/main/java/org/example/entity/RestaurantTable.java @@ -14,7 +14,7 @@ public class RestaurantTable { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToMany(mappedBy = "restaurant_table", cascade = CascadeType.PERSIST) + @OneToMany(mappedBy = "table", cascade = CascadeType.PERSIST) private List bookings = new ArrayList<>(); diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 3176e18d..fd6c37c5 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -1,14 +1,11 @@ - org.example.entity.RestaurantTable - org.example.entity.Booking - org.example.entity.Guest - + From 0e545feda68f81f3a54eec1e627153c134478347 Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:59:20 +0100 Subject: [PATCH 10/23] Week 1 implimentations --- docker-compose.yml | 3 +-- pom.xml | 6 +++--- src/main/java/org/example/App.java | 5 +++-- src/main/resources/META-INF/persistence.xml | 3 +++ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3d1e850f..a619a9e9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,8 +5,7 @@ services: image: mysql:9.5 container_name: restaurant_booking_db environment: - MYSQL_ROOT_PASSWORD: "" - MYSQL_ALLOW_EMPTY_PASSWORD: "yes" + MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: restaurant_booking ports: - "3306:3306" diff --git a/pom.xml b/pom.xml index 0a5d65e5..4769bd01 100644 --- a/pom.xml +++ b/pom.xml @@ -37,12 +37,12 @@ org.hibernate.orm hibernate-core - 6.4.4.Final + 7.2.0.Final com.mysql mysql-connector-j - 8.3.0 + 9.5.0 runtime @@ -53,7 +53,7 @@ jakarta.persistence jakarta.persistence-api - 3.1.0 + 3.2.0 diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index cf262668..efbb2d77 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -17,11 +17,12 @@ static void main(String[] args) { try { em.getTransaction().begin(); - RestaurantTable table = new RestaurantTable(8, "Table 8"); + RestaurantTable table = new RestaurantTable(5, "Table 6"); em.persist(table); - Guest guest = new Guest("John Smith", "N/A", "johnsmith.email.com"); + Guest guest = new Guest("Johnnathan Smith", "N/A", "johnnysmith.email.com"); em.persist(guest); Booking booking = new Booking(table, LocalDateTime.now(), 5); + booking.addGuest(guest); em.persist(booking); em.getTransaction().commit(); } catch (Exception e) { diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index fd6c37c5..6b83e713 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -1,6 +1,9 @@ + org.example.entity.RestaurantTable + org.example.entity.Guest + org.example.entity.Booking From 59acdec2ca6598a30c644e4e4e70c6fc795cb412 Mon Sep 17 00:00:00 2001 From: Gabriela Aguirre Date: Fri, 9 Jan 2026 09:15:03 +0100 Subject: [PATCH 11/23] new entity TimeSlot --- docker-compose.yml | 3 +- pom.xml | 16 +- src/main/java/org/example/App.java | 150 +++++++++++++++--- src/main/java/org/example/entity/Booking.java | 63 +++++--- src/main/java/org/example/entity/Guest.java | 5 +- .../java/org/example/entity/Restaurant.java | 4 - .../{RestaurantTable.java => Table.java} | 33 +++- .../java/org/example/entity/TimeSlot.java | 59 +++++++ src/main/resources/META-INF/persistence.xml | 23 ++- 9 files changed, 289 insertions(+), 67 deletions(-) delete mode 100644 src/main/java/org/example/entity/Restaurant.java rename src/main/java/org/example/entity/{RestaurantTable.java => Table.java} (54%) create mode 100644 src/main/java/org/example/entity/TimeSlot.java diff --git a/docker-compose.yml b/docker-compose.yml index 3d1e850f..a619a9e9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,8 +5,7 @@ services: image: mysql:9.5 container_name: restaurant_booking_db environment: - MYSQL_ROOT_PASSWORD: "" - MYSQL_ALLOW_EMPTY_PASSWORD: "yes" + MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: restaurant_booking ports: - "3306:3306" diff --git a/pom.xml b/pom.xml index 0a5d65e5..20c6f873 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,16 @@ 5.21.0 + + com.zaxxer + HikariCP + 7.0.2 + + + org.hibernate.orm + hibernate-hikaricp + 7.2.0.Final + org.junit.jupiter junit-jupiter @@ -37,12 +47,12 @@ org.hibernate.orm hibernate-core - 6.4.4.Final + 7.2.0.Final com.mysql mysql-connector-j - 8.3.0 + 9.5.0 runtime @@ -53,7 +63,7 @@ jakarta.persistence jakarta.persistence-api - 3.1.0 + 3.2.0 diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 333df2a3..9b6af6f3 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -1,31 +1,139 @@ package org.example; -import jakarta.persistence.EntityManager; -import jakarta.persistence.EntityManagerFactory; -import jakarta.persistence.Persistence; -import org.example.entity.Booking; +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ScanResult; +import jakarta.persistence.*; +import org.example.entity.*; +import org.example.entity.Table; +import org.hibernate.jpa.HibernatePersistenceConfiguration; -import java.time.LocalDateTime; +import java.util.List; public class App { static void main(String[] args) { - try (EntityManagerFactory emf = Persistence.createEntityManagerFactory("restaurantPU"); - EntityManager em = emf.createEntityManager()) { - - try { - em.getTransaction().begin(); - //BookingTable bookingTable = new BookingTable(6, 8); - Booking booking = new Booking(); - //Guest guest = new Guest(); - em.persist(booking); - em.getTransaction().commit(); - } catch (Exception e) { - em.getTransaction().rollback(); - e.printStackTrace(); - } - } catch (Exception e) { - e.printStackTrace(); + List> entities = getEntities("org.example.entity"); + + final PersistenceConfiguration cfg = new HibernatePersistenceConfiguration("emf") + .jdbcUrl("jdbc:mysql://localhost:3306/restaurant_booking") + .jdbcUsername("root") + .jdbcPassword("root123") + + .property("hibernate.connection.provider_class", "org.hibernate.hikaricp.internal.HikariCPConnectionProvider") + + .property("hibernate.hikari.maximumPoolSize", "10") //Max antal anslutningar + .property("hibernate.hikari.minimumIdle", "5") //Minsta antal lediga anslutningar + .property("hibernate.hikari.idleTimeout", "300000") // 5 minuter innan ledig anslutning stängs + .property("hibernate.hikari.connectionTimeout", "20000") // Max väntetid på anslutning (20s) + + .property("hibernate.hbm2ddl.auto", "create") + .property("hibernate.show_sql", "true") + .property("hibernate.format_sql", "true") + .property("hibernate.highlight_sql", "true") + .managedClasses(entities); + + try (EntityManagerFactory emf = cfg.createEntityManagerFactory()) { + + hours(emf); + createTable(emf); + createGuest(emf); + + + //Show all the hours available + emf.runInTransaction(em -> { + var query = em.createQuery("select h from TimeSlot h"); + query.getResultList().forEach(System.out::println); + }); + } + } + + private static void createGuest (EntityManagerFactory emf){ + emf.runInTransaction(em -> { + + Guest guest = new Guest("Gabriela", "Bord för fyra", "072762668"); + em.persist(guest); + + guest = new Guest("Samuel", "Bord för 3", "072778882"); + em.persist(guest); + + }); + } + + private static void createTable(EntityManagerFactory emf) { + emf.runInTransaction(em -> { + + Table table = new Table(); + table.setTableNumber("1"); + table.setCapacity(4); + em.persist(table); + + table = new Table(); + table.setTableNumber("2"); + table.setCapacity(2); + em.persist(table); + + table = new Table(); + table.setTableNumber("3"); + table.setCapacity(3); + em.persist(table); + + table = new Table(); + table.setTableNumber("4"); + table.setCapacity(6); + em.persist(table); + + table = new Table(); + table.setTableNumber("5"); + table.setCapacity(2); + em.persist(table); + + }); + } + + private static void hours(EntityManagerFactory emf){ + emf.runInTransaction(em -> { + + TimeSlot hour = new TimeSlot("16:00", "18:00"); + em.persist(hour); + + hour = new TimeSlot("16:30", "18:30"); + em.persist(hour); + + hour = new TimeSlot("17:00", "19:00"); + em.persist(hour); + + hour = new TimeSlot("17:30", "19:30"); + em.persist(hour); + + hour = new TimeSlot("18:00", "20:00"); + em.persist(hour); + + hour = new TimeSlot("18:30", "20:30"); + em.persist(hour); + + hour = new TimeSlot("19:00", "21:00"); + em.persist(hour); + + }); + } + + private static List> getEntities(String pkg) { + List> entities; + + //Esto es para scannear todas las entities clases que existen en tal paquete. Es para no hacerlo uno por uno + //Agregar dependency + + try (ScanResult scanResult = + new ClassGraph() + .enableClassInfo() + .enableAnnotationInfo() + .acceptPackages(pkg) + .scan()) { + entities = scanResult.getClassesWithAnnotation(Entity.class).loadClasses(); + } + return entities; + } + } diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index 9da9c7ca..5d696486 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -1,29 +1,33 @@ package org.example.entity; import jakarta.persistence.*; -import java.time.LocalDateTime; + +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @Entity -@Table(name="bookings") +@jakarta.persistence.Table(name="Bookings") public class Booking { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(name="booking_Time", nullable = false) - private LocalDateTime time; + @Column(name="booking_date", nullable = false) + private LocalDate date; //day of the reservation + + @ManyToOne + @JoinColumn(name="timeslot_id") + private TimeSlot timeSlot; //time selected from the determited times @Column(name="party_size", nullable = false) - private int party; + private int partySize; @ManyToOne @JoinColumn(name="table_id", nullable = false) - private RestaurantTable table; + private Table table; @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) @JoinTable( @@ -32,10 +36,13 @@ public class Booking { inverseJoinColumns = @JoinColumn (name = "guest_id")) private List guests = new ArrayList<>(); - public Booking(RestaurantTable table, LocalDateTime time, int party){ + public Booking(Long id, LocalDate date, TimeSlot timeSlot, int partySize, Table table, List guests) { + this.id = id; + this.date = date; + this.timeSlot = timeSlot; + this.partySize = partySize; this.table = table; - this.time = time; - this.party = party; + this.guests = guests; } public void addGuest(Guest guest){ @@ -50,27 +57,35 @@ public void removeGuest(Guest guest){ public Booking() {} - public LocalDateTime getTime() { - return time; + public LocalDate getDate() { + return date; } - public void setTime(LocalDateTime time) { - this.time = time; + public void setTime(LocalDate time) { + this.date = date; + } + + public TimeSlot getTimeSlot() { + return timeSlot; + } + + public void setTimeSlot(TimeSlot timeSlot) { + this.timeSlot = timeSlot; } public int getParty() { - return party; + return partySize; } public void setParty(int party) { - this.party = party; + this.partySize = partySize; } - public RestaurantTable getTable() { + public Table getTable() { return table; } - public void setTable(RestaurantTable table) { + public void setTable(Table table) { this.table = table; } @@ -91,8 +106,14 @@ public Long getId() { } @Override - public String toString(){ - return "Booking id = " + id + ", time = " + time + ", party = " + party + ", table = " + (table != null ? table.getTableNumber() : "N/A") + "."; + public String toString() { + return "Booking{" + + "id=" + id + + ", date=" + date + + ", timeSlot=" + timeSlot + + ", party=" + partySize + + ", table=" + table + + ", guests=" + guests + + '}'; } - } diff --git a/src/main/java/org/example/entity/Guest.java b/src/main/java/org/example/entity/Guest.java index d7e948a1..804b5c61 100644 --- a/src/main/java/org/example/entity/Guest.java +++ b/src/main/java/org/example/entity/Guest.java @@ -2,11 +2,12 @@ import jakarta.persistence.*; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @Entity -@Table(name = "Guests") +@jakarta.persistence.Table(name = "Guests") public class Guest { @Id @@ -33,7 +34,6 @@ public Guest(String name, String note, String contact){ public Guest(){} - public String getName() { return name; } @@ -75,5 +75,4 @@ public Long getId() { return id; } - } diff --git a/src/main/java/org/example/entity/Restaurant.java b/src/main/java/org/example/entity/Restaurant.java deleted file mode 100644 index 31829185..00000000 --- a/src/main/java/org/example/entity/Restaurant.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.example.entity; - -public class Restaurant { -} diff --git a/src/main/java/org/example/entity/RestaurantTable.java b/src/main/java/org/example/entity/Table.java similarity index 54% rename from src/main/java/org/example/entity/RestaurantTable.java rename to src/main/java/org/example/entity/Table.java index 856b5faa..6e4c91c8 100644 --- a/src/main/java/org/example/entity/RestaurantTable.java +++ b/src/main/java/org/example/entity/Table.java @@ -4,17 +4,18 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; @Entity -@Table(name = "restaurant_table") +@jakarta.persistence.Table(name = "Tables") -public class RestaurantTable { +public class Table { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToMany(mappedBy = "restaurant_table", cascade = CascadeType.PERSIST) + @OneToMany(mappedBy = "table", cascade = CascadeType.PERSIST) private List bookings = new ArrayList<>(); @@ -25,9 +26,10 @@ public class RestaurantTable { private int capacity; - public RestaurantTable(int capacity, String tableNumber){ + public Table(int capacity, String tableNumber){ this.capacity = capacity; this.tableNumber = tableNumber; + } public List getBookings() { @@ -54,7 +56,7 @@ public void setCapacity(int capacity) { this.capacity = capacity; } - public RestaurantTable() {} + public Table() {} public void setId(Long id) { this.id = id; @@ -64,4 +66,25 @@ public Long getId() { return id; } + @Override + public String toString() { + return "Table{" + + "id=" + id + + ", bookings=" + bookings + + ", tableNumber='" + tableNumber + '\'' + + ", capacity=" + capacity + + '}'; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Table table = (Table) o; + return capacity == table.capacity && Objects.equals(id, table.id) && Objects.equals(bookings, table.bookings) && Objects.equals(tableNumber, table.tableNumber); + } + + @Override + public int hashCode() { + return Objects.hash(id, bookings, tableNumber, capacity); + } } diff --git a/src/main/java/org/example/entity/TimeSlot.java b/src/main/java/org/example/entity/TimeSlot.java new file mode 100644 index 00000000..c9f96cd7 --- /dev/null +++ b/src/main/java/org/example/entity/TimeSlot.java @@ -0,0 +1,59 @@ +package org.example.entity; + +import jakarta.persistence.*; + +@Entity +public class TimeSlot { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, unique = true) + private String startTime; + + @Column(nullable = false, unique = true) + private String finishTime; + + public TimeSlot(String startTime, String finishTime) { + this.startTime = startTime; + this.finishTime = finishTime; + } + + public TimeSlot() { + } + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getStartTime() { + return startTime; + } + + public void setStartTime(String startTime) { + this.startTime = startTime; + } + + public String getFinishTime() { + return finishTime; + } + + public void setFinishTime(String finishTime) { + this.finishTime = finishTime; + } + + @Override + public String toString() { + return "TimeSlot{" + + "id=" + id + + ", startTime='" + startTime + '\'' + + ", finishTime='" + finishTime + '\'' + + '}'; + } +} diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 3176e18d..308e91e6 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -1,22 +1,29 @@ - - + + - org.example.entity.RestaurantTable + org.example.entity.Table org.example.entity.Booking org.example.entity.Guest + org.example.entity.TimeSlot - - + + + - + + + + + From 7462839c09c4469142f3d0f90085546156e0e353 Mon Sep 17 00:00:00 2001 From: youneslamia Date: Fri, 9 Jan 2026 09:26:57 +0100 Subject: [PATCH 12/23] BookingStatus --- docker-compose.yml | 2 +- src/main/java/org/example/App.java | 172 +++++------------- .../org/example/entity/BookingStatus.java | 9 + 3 files changed, 52 insertions(+), 131 deletions(-) create mode 100644 src/main/java/org/example/entity/BookingStatus.java diff --git a/docker-compose.yml b/docker-compose.yml index a619a9e9..437bcf83 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.8' services: mysql: - image: mysql:9.5 + image: mysql:9.5.0 container_name: restaurant_booking_db environment: MYSQL_ROOT_PASSWORD: root123 diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 9b6af6f3..36a49e49 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -1,139 +1,51 @@ package org.example; -import io.github.classgraph.ClassGraph; -import io.github.classgraph.ScanResult; -import jakarta.persistence.*; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.Persistence; import org.example.entity.*; -import org.example.entity.Table; -import org.hibernate.jpa.HibernatePersistenceConfiguration; -import java.util.List; +import java.time.LocalDateTime; public class App { - static void main(String[] args) { - - List> entities = getEntities("org.example.entity"); - - final PersistenceConfiguration cfg = new HibernatePersistenceConfiguration("emf") - .jdbcUrl("jdbc:mysql://localhost:3306/restaurant_booking") - .jdbcUsername("root") - .jdbcPassword("root123") - - .property("hibernate.connection.provider_class", "org.hibernate.hikaricp.internal.HikariCPConnectionProvider") - - .property("hibernate.hikari.maximumPoolSize", "10") //Max antal anslutningar - .property("hibernate.hikari.minimumIdle", "5") //Minsta antal lediga anslutningar - .property("hibernate.hikari.idleTimeout", "300000") // 5 minuter innan ledig anslutning stängs - .property("hibernate.hikari.connectionTimeout", "20000") // Max väntetid på anslutning (20s) - - .property("hibernate.hbm2ddl.auto", "create") - .property("hibernate.show_sql", "true") - .property("hibernate.format_sql", "true") - .property("hibernate.highlight_sql", "true") - .managedClasses(entities); - - try (EntityManagerFactory emf = cfg.createEntityManagerFactory()) { - - hours(emf); - createTable(emf); - createGuest(emf); - - - //Show all the hours available - emf.runInTransaction(em -> { - var query = em.createQuery("select h from TimeSlot h"); - query.getResultList().forEach(System.out::println); - }); - - } - - } - - private static void createGuest (EntityManagerFactory emf){ - emf.runInTransaction(em -> { - - Guest guest = new Guest("Gabriela", "Bord för fyra", "072762668"); - em.persist(guest); - - guest = new Guest("Samuel", "Bord för 3", "072778882"); - em.persist(guest); - - }); - } - - private static void createTable(EntityManagerFactory emf) { - emf.runInTransaction(em -> { - - Table table = new Table(); - table.setTableNumber("1"); - table.setCapacity(4); - em.persist(table); - - table = new Table(); - table.setTableNumber("2"); - table.setCapacity(2); - em.persist(table); - - table = new Table(); - table.setTableNumber("3"); - table.setCapacity(3); - em.persist(table); - - table = new Table(); - table.setTableNumber("4"); - table.setCapacity(6); - em.persist(table); - - table = new Table(); - table.setTableNumber("5"); - table.setCapacity(2); - em.persist(table); - - }); - } - - private static void hours(EntityManagerFactory emf){ - emf.runInTransaction(em -> { - - TimeSlot hour = new TimeSlot("16:00", "18:00"); - em.persist(hour); - - hour = new TimeSlot("16:30", "18:30"); - em.persist(hour); - - hour = new TimeSlot("17:00", "19:00"); - em.persist(hour); - - hour = new TimeSlot("17:30", "19:30"); - em.persist(hour); - - hour = new TimeSlot("18:00", "20:00"); - em.persist(hour); - - hour = new TimeSlot("18:30", "20:30"); - em.persist(hour); - - hour = new TimeSlot("19:00", "21:00"); - em.persist(hour); - - }); - } - - private static List> getEntities(String pkg) { - List> entities; - - //Esto es para scannear todas las entities clases que existen en tal paquete. Es para no hacerlo uno por uno - //Agregar dependency - - try (ScanResult scanResult = - new ClassGraph() - .enableClassInfo() - .enableAnnotationInfo() - .acceptPackages(pkg) - .scan()) { - entities = scanResult.getClassesWithAnnotation(Entity.class).loadClasses(); + public static void main(String[] args) { + try (EntityManagerFactory emf = Persistence.createEntityManagerFactory("restaurantPU"); + EntityManager em = emf.createEntityManager()) { + + try { + em.getTransaction().begin(); + + RestaurantTable table2 = new RestaurantTable("T2", 5); + em.persist(table2); + + Guest guest3 = new Guest("Martin Martinsson", "martin@hotmail.se", "0707939910", "Gillar äpplen"); + Booking booking = new Booking( + table2, + LocalDateTime.now().plusDays(1).withHour(18).withMinute(0), + 4 + ); + booking.addGuest(guest3); + + booking.confirm(); + em.persist(booking); + + em.getTransaction().commit(); + + System.out.println("Data created successfully!"); + System.out.println(table2); + System.out.println(booking); + System.out.println("Guests in booking: " + booking.getGuests().size()); + + } catch (Exception e) { + if (em.getTransaction().isActive()) { + em.getTransaction().rollback(); + } + throw e; + } + + } catch (Exception e) { + System.err.println("Error:"); + e.printStackTrace(); } - return entities; } - } diff --git a/src/main/java/org/example/entity/BookingStatus.java b/src/main/java/org/example/entity/BookingStatus.java new file mode 100644 index 00000000..38e8fb0d --- /dev/null +++ b/src/main/java/org/example/entity/BookingStatus.java @@ -0,0 +1,9 @@ +package org.example.entity; + +public enum BookingStatus { + PENDING, + CONFIRMED, + CANCELLED, + COMPLETED, + NO_SHOW +} From 7a5da4b5e67fc0c82bed9cb439301d3b53bc68db Mon Sep 17 00:00:00 2001 From: youneslamia Date: Fri, 9 Jan 2026 09:31:16 +0100 Subject: [PATCH 13/23] Booking status system --- src/main/java/org/example/entity/Booking.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index 5d696486..45022121 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -25,6 +25,10 @@ public class Booking { @Column(name="party_size", nullable = false) private int partySize; + @Enumerated(EnumType.STRING) + @Column(name = "status", nullable = false) + private BookingStatus status = BookingStatus.PENDING; + @ManyToOne @JoinColumn(name="table_id", nullable = false) private Table table; @@ -43,6 +47,8 @@ public Booking(Long id, LocalDate date, TimeSlot timeSlot, int partySize, Table this.partySize = partySize; this.table = table; this.guests = guests; + this.status = BookingStatus.PENDING; + } public void addGuest(Guest guest){ @@ -55,6 +61,24 @@ public void removeGuest(Guest guest){ guest.getBookings().remove(this); } + public BookingStatus getStatus() { + return status; + } + public void confirmBooking(){ + this.status = BookingStatus.CONFIRMED; + } + public void cancelBooking(){ + this.status = BookingStatus.CANCELLED; + } + public void completeBooking(){ + this.status = BookingStatus.COMPLETED; + } + public void noShowBooking(){ + this.status = BookingStatus.NO_SHOW; + } + + public void setStatus(BookingStatus status) {} + public Booking() {} public LocalDate getDate() { From d848b44714daeac299c2de8b67761a7dbe28bfc3 Mon Sep 17 00:00:00 2001 From: youneslamia Date: Fri, 9 Jan 2026 09:34:22 +0100 Subject: [PATCH 14/23] Booking status system --- src/main/java/org/example/entity/Booking.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index 45022121..bf8ddafe 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -76,9 +76,6 @@ public void completeBooking(){ public void noShowBooking(){ this.status = BookingStatus.NO_SHOW; } - - public void setStatus(BookingStatus status) {} - public Booking() {} public LocalDate getDate() { From 9b7d0ea97d243728b2027f089c67d1dfc4e29bc3 Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Fri, 9 Jan 2026 10:06:21 +0100 Subject: [PATCH 15/23] Menu options --- src/main/java/org/example/Writer.java | 48 +++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/org/example/Writer.java diff --git a/src/main/java/org/example/Writer.java b/src/main/java/org/example/Writer.java new file mode 100644 index 00000000..ccdc80ab --- /dev/null +++ b/src/main/java/org/example/Writer.java @@ -0,0 +1,48 @@ +package org.example; + +import java.util.Locale; + +public class Writer { + + public void mainMenu(){ + String select; + + String menu = """ + CREATE BOOKING + UPDATE BOOKING + READ BOOKING + DELETE BOOKING + + CREATE TABLES* + CREATE GUESTS* + """; + select = IO.readln(menu).toLowerCase(); + + switch (select) { + case "create booking", "cb" -> createMenu(); + case "update booking", "ub" -> updateMenu(); + case "read booking", "rb" -> readMenu(); + case "delete booking", "db" -> deleteMenu(); + default -> mainMenu(); + } + + + + + } + + private void deleteMenu() { + + } + + private void readMenu() { + } + + private void updateMenu() { + } + + private void createMenu() { + } + + +} From edd1f76c13f509b49e992c93a28e8abfd454799c Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Fri, 9 Jan 2026 10:49:36 +0100 Subject: [PATCH 16/23] Menu system in app --- src/main/java/org/example/App.java | 30 +++++++++++++++++ src/main/java/org/example/Writer.java | 48 --------------------------- 2 files changed, 30 insertions(+), 48 deletions(-) delete mode 100644 src/main/java/org/example/Writer.java diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 9b6af6f3..c7aa4f11 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -37,6 +37,7 @@ static void main(String[] args) { hours(emf); createTable(emf); createGuest(emf); + mainMenu(); //Show all the hours available @@ -136,4 +137,33 @@ private static List> getEntities(String pkg) { return entities; } + public static void mainMenu() { + boolean running = true; + while (running) { + String select; + + String menu = """ + 1 CREATE BOOKING + 2 UPDATE BOOKING + 3 READ BOOKING + 4 DELETE BOOKING + + CREATE TABLES* + CREATE GUESTS* + + 7 EXIT + """; + select = IO.readln(menu).toLowerCase(); + + switch (select) { + case "create booking", "cb", "1" -> System.out.println("1"); + case "update booking", "ub", "2" -> System.out.println("2"); + case "read booking", "rb", "3" -> System.out.println("3"); + case "delete booking", "db", "4" -> System.out.println("4"); + case "7" -> running = false; + default -> mainMenu(); + } + } + } + } diff --git a/src/main/java/org/example/Writer.java b/src/main/java/org/example/Writer.java deleted file mode 100644 index ccdc80ab..00000000 --- a/src/main/java/org/example/Writer.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.example; - -import java.util.Locale; - -public class Writer { - - public void mainMenu(){ - String select; - - String menu = """ - CREATE BOOKING - UPDATE BOOKING - READ BOOKING - DELETE BOOKING - - CREATE TABLES* - CREATE GUESTS* - """; - select = IO.readln(menu).toLowerCase(); - - switch (select) { - case "create booking", "cb" -> createMenu(); - case "update booking", "ub" -> updateMenu(); - case "read booking", "rb" -> readMenu(); - case "delete booking", "db" -> deleteMenu(); - default -> mainMenu(); - } - - - - - } - - private void deleteMenu() { - - } - - private void readMenu() { - } - - private void updateMenu() { - } - - private void createMenu() { - } - - -} From 88194e24ad417f4e13220acce3cbeb963cd49c44 Mon Sep 17 00:00:00 2001 From: youneslamia Date: Fri, 9 Jan 2026 11:02:30 +0100 Subject: [PATCH 17/23] Booking status system v2 --- src/main/java/org/example/entity/BookingStatus.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/example/entity/BookingStatus.java b/src/main/java/org/example/entity/BookingStatus.java index 38e8fb0d..8bf2935c 100644 --- a/src/main/java/org/example/entity/BookingStatus.java +++ b/src/main/java/org/example/entity/BookingStatus.java @@ -7,3 +7,4 @@ public enum BookingStatus { COMPLETED, NO_SHOW } +// Status system From d5fcb10f164f45c73543eebd54eb678f18089d4c Mon Sep 17 00:00:00 2001 From: youneslamia Date: Fri, 9 Jan 2026 12:52:31 +0100 Subject: [PATCH 18/23] =?UTF-8?q?Meny=20och=20service=20f=C3=B6r=20bokning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/example/App.java | 306 ++++++++++++------ .../org/example/entity/BookingService.java | 115 +++++++ 2 files changed, 321 insertions(+), 100 deletions(-) create mode 100644 src/main/java/org/example/entity/BookingService.java diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index c7aa4f11..0d152885 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -5,12 +5,16 @@ import jakarta.persistence.*; import org.example.entity.*; import org.example.entity.Table; +import org.example.service.BookingService; import org.hibernate.jpa.HibernatePersistenceConfiguration; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.List; public class App { - static void main(String[] args) { + public static void main(String[] args) { List> entities = getEntities("org.example.entity"); @@ -18,15 +22,12 @@ static void main(String[] args) { .jdbcUrl("jdbc:mysql://localhost:3306/restaurant_booking") .jdbcUsername("root") .jdbcPassword("root123") - .property("hibernate.connection.provider_class", "org.hibernate.hikaricp.internal.HikariCPConnectionProvider") - - .property("hibernate.hikari.maximumPoolSize", "10") //Max antal anslutningar - .property("hibernate.hikari.minimumIdle", "5") //Minsta antal lediga anslutningar - .property("hibernate.hikari.idleTimeout", "300000") // 5 minuter innan ledig anslutning stängs - .property("hibernate.hikari.connectionTimeout", "20000") // Max väntetid på anslutning (20s) - - .property("hibernate.hbm2ddl.auto", "create") + .property("hibernate.hikari.maximumPoolSize", "10") + .property("hibernate.hikari.minimumIdle", "5") + .property("hibernate.hikari.idleTimeout", "300000") + .property("hibernate.hikari.connectionTimeout", "20000") + .property("hibernate.hbm2ddl.auto", "update") .property("hibernate.show_sql", "true") .property("hibernate.format_sql", "true") .property("hibernate.highlight_sql", "true") @@ -34,136 +35,241 @@ static void main(String[] args) { try (EntityManagerFactory emf = cfg.createEntityManagerFactory()) { - hours(emf); - createTable(emf); - createGuest(emf); - mainMenu(); - + // Skapa initial data om den inte finns + createInitialData(emf); - //Show all the hours available - emf.runInTransaction(em -> { - var query = em.createQuery("select h from TimeSlot h"); - query.getResultList().forEach(System.out::println); - }); + // Starta huvudmeny + BookingService bookingService = new BookingService(emf); + mainMenu(bookingService, emf); } - } - private static void createGuest (EntityManagerFactory emf){ - emf.runInTransaction(em -> { - - Guest guest = new Guest("Gabriela", "Bord för fyra", "072762668"); - em.persist(guest); + private static void createInitialData(EntityManagerFactory emf) { + // Kolla om data redan finns + Long count = emf.callInTransaction(em -> + em.createQuery("SELECT COUNT(t) FROM Table t", Long.class).getSingleResult() + ); - guest = new Guest("Samuel", "Bord för 3", "072778882"); - em.persist(guest); + if (count == 0) { + hours(emf); + createTable(emf); + createGuest(emf); + System.out.println("✅ Initial data created!"); + } + } + private static void createGuest(EntityManagerFactory emf) { + emf.runInTransaction(em -> { + em.persist(new Guest("Gabriela", "Bord för fyra", "072762668")); + em.persist(new Guest("Samuel", "Bord för 3", "072778882")); + em.persist(new Guest("Anna", "VIP", "0701234567")); + em.persist(new Guest("Erik", "Allergisk mot nötter", "0709876543")); }); } private static void createTable(EntityManagerFactory emf) { emf.runInTransaction(em -> { + for (int i = 1; i <= 5; i++) { + Table table = new Table(); + table.setTableNumber(String.valueOf(i)); + table.setCapacity(i == 4 ? 6 : (i % 2 == 0 ? 2 : 4)); + em.persist(table); + } + }); + } - Table table = new Table(); - table.setTableNumber("1"); - table.setCapacity(4); - em.persist(table); + private static void hours(EntityManagerFactory emf) { + emf.runInTransaction(em -> { + String[] times = {"16:00", "16:30", "17:00", "17:30", "18:00", "18:30", "19:00"}; + for (int i = 0; i < times.length; i++) { + String start = times[i]; + String[] parts = start.split(":"); + int hour = Integer.parseInt(parts[0]) + 2; + String end = hour + ":" + parts[1]; + em.persist(new TimeSlot(start, end)); + } + }); + } - table = new Table(); - table.setTableNumber("2"); - table.setCapacity(2); - em.persist(table); + private static List> getEntities(String pkg) { + try (ScanResult scanResult = new ClassGraph() + .enableClassInfo() + .enableAnnotationInfo() + .acceptPackages(pkg) + .scan()) { + return scanResult.getClassesWithAnnotation(Entity.class).loadClasses(); + } + } - table = new Table(); - table.setTableNumber("3"); - table.setCapacity(3); - em.persist(table); + public static void mainMenu(BookingService bookingService, EntityManagerFactory emf) { + boolean running = true; + while (running) { + String menu = """ - table = new Table(); - table.setTableNumber("4"); - table.setCapacity(6); - em.persist(table); + ╔════════════════════════════════════╗ + ║ RESTAURANT BOOKING SYSTEM ║ + ╠════════════════════════════════════╣ + ║ 1. CREATE BOOKING ║ + ║ 2. UPDATE BOOKING ║ + ║ 3. VIEW ALL BOOKINGS ║ + ║ 4. DELETE BOOKING ║ + ║ 5. VIEW TABLES ║ + ║ 6. VIEW GUESTS ║ + ║ 7. EXIT ║ + ╚════════════════════════════════════╝ + """; - table = new Table(); - table.setTableNumber("5"); - table.setCapacity(2); - em.persist(table); + String select = IO.readln(menu + "\nSelect option: ").toLowerCase(); - }); + switch (select) { + case "create booking", "cb", "1" -> createBookingMenu(bookingService); + case "update booking", "ub", "2" -> updateBookingMenu(bookingService); + case "view all bookings", "rb", "3" -> viewAllBookings(bookingService); + case "delete booking", "db", "4" -> deleteBookingMenu(bookingService); + case "view tables", "5" -> viewTables(bookingService); + case "view guests", "6" -> viewGuests(bookingService); + case "exit", "7" -> { + System.out.println("👋 Goodbye!"); + running = false; + } + default -> System.out.println("❌ Invalid option!"); + } + } } - private static void hours(EntityManagerFactory emf){ - emf.runInTransaction(em -> { + private static void createBookingMenu(BookingService bookingService) { + System.out.println("\n═══ CREATE NEW BOOKING ═══"); - TimeSlot hour = new TimeSlot("16:00", "18:00"); - em.persist(hour); + // Visa tillgängliga bord + List tables = bookingService.getAllTables(); + System.out.println("\n📋 Available Tables:"); + tables.forEach(t -> System.out.println(" " + t.getId() + ". Table " + t.getTableNumber() + " (Capacity: " + t.getCapacity() + ")")); - hour = new TimeSlot("16:30", "18:30"); - em.persist(hour); + Long tableId = Long.parseLong(IO.readln("\nEnter Table ID: ")); - hour = new TimeSlot("17:00", "19:00"); - em.persist(hour); + // Visa tillgängliga tider + List timeSlots = bookingService.getAllTimeSlots(); + System.out.println("\n⏰ Available Time Slots:"); + timeSlots.forEach(ts -> System.out.println(" " + ts.getId() + ". " + ts.getStartTime() + " - " + ts.getFinishTime())); - hour = new TimeSlot("17:30", "19:30"); - em.persist(hour); + Long timeSlotId = Long.parseLong(IO.readln("\nEnter TimeSlot ID: ")); - hour = new TimeSlot("18:00", "20:00"); - em.persist(hour); + // Datum + String dateStr = IO.readln("\nEnter date (YYYY-MM-DD): "); + LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE); - hour = new TimeSlot("18:30", "20:30"); - em.persist(hour); + // Antal gäster + int partySize = Integer.parseInt(IO.readln("\nEnter party size: ")); - hour = new TimeSlot("19:00", "21:00"); - em.persist(hour); + // Visa tillgängliga gäster + List guests = bookingService.getAllGuests(); + System.out.println("\n👥 Available Guests:"); + guests.forEach(g -> System.out.println(" " + g.getId() + ". " + g.getName() + " (" + g.getContact() + ")")); - }); + List guestIds = new ArrayList<>(); + String addMore = "y"; + while (addMore.equalsIgnoreCase("y")) { + Long guestId = Long.parseLong(IO.readln("\nEnter Guest ID: ")); + guestIds.add(guestId); + addMore = IO.readln("Add another guest? (y/n): "); + } + + try { + bookingService.createBooking(tableId, timeSlotId, date, partySize, guestIds); + } catch (Exception e) { + System.out.println("❌ Error: " + e.getMessage()); + } } - private static List> getEntities(String pkg) { - List> entities; - - //Esto es para scannear todas las entities clases que existen en tal paquete. Es para no hacerlo uno por uno - //Agregar dependency - - try (ScanResult scanResult = - new ClassGraph() - .enableClassInfo() - .enableAnnotationInfo() - .acceptPackages(pkg) - .scan()) { - entities = scanResult.getClassesWithAnnotation(Entity.class).loadClasses(); + private static void updateBookingMenu(BookingService bookingService) { + System.out.println("\n═══ UPDATE BOOKING ═══"); + + viewAllBookings(bookingService); + + Long bookingId = Long.parseLong(IO.readln("\nEnter Booking ID to update: ")); + + String statusMenu = """ + + Select new status: + 1. PENDING + 2. CONFIRMED + 3. CANCELLED + 4. COMPLETED + 5. NO_SHOW + """; + + String choice = IO.readln(statusMenu + "\nEnter choice: "); + + BookingStatus newStatus = switch (choice) { + case "1" -> BookingStatus.PENDING; + case "2" -> BookingStatus.CONFIRMED; + case "3" -> BookingStatus.CANCELLED; + case "4" -> BookingStatus.COMPLETED; + case "5" -> BookingStatus.NO_SHOW; + default -> null; + }; + + if (newStatus != null) { + try { + bookingService.updateBookingStatus(bookingId, newStatus); + } catch (Exception e) { + System.out.println("❌ Error: " + e.getMessage()); + } + } else { + System.out.println("❌ Invalid status!"); } - return entities; } - public static void mainMenu() { - boolean running = true; - while (running) { - String select; + private static void viewAllBookings(BookingService bookingService) { + System.out.println("\n═══ ALL BOOKINGS ═══"); + List bookings = bookingService.getAllBookings(); + + if (bookings.isEmpty()) { + System.out.println("No bookings found."); + } else { + bookings.forEach(b -> { + System.out.println("\n📅 Booking ID: " + b.getId()); + System.out.println(" Date: " + b.getDate()); + System.out.println(" Time: " + b.getTimeSlot().getStartTime() + " - " + b.getTimeSlot().getFinishTime()); + System.out.println(" Table: " + b.getTable().getTableNumber()); + System.out.println(" Party Size: " + b.getParty()); + System.out.println(" Status: " + b.getStatus()); + System.out.println(" Guests: " + b.getGuests().stream().map(Guest::getName).toList()); + }); + } + } - String menu = """ - 1 CREATE BOOKING - 2 UPDATE BOOKING - 3 READ BOOKING - 4 DELETE BOOKING + private static void deleteBookingMenu(BookingService bookingService) { + System.out.println("\n═══ DELETE BOOKING ═══"); - CREATE TABLES* - CREATE GUESTS* + viewAllBookings(bookingService); - 7 EXIT - """; - select = IO.readln(menu).toLowerCase(); + Long bookingId = Long.parseLong(IO.readln("\nEnter Booking ID to delete: ")); + String confirm = IO.readln("Are you sure? (y/n): "); - switch (select) { - case "create booking", "cb", "1" -> System.out.println("1"); - case "update booking", "ub", "2" -> System.out.println("2"); - case "read booking", "rb", "3" -> System.out.println("3"); - case "delete booking", "db", "4" -> System.out.println("4"); - case "7" -> running = false; - default -> mainMenu(); + if (confirm.equalsIgnoreCase("y")) { + try { + bookingService.deleteBooking(bookingId); + } catch (Exception e) { + System.out.println("❌ Error: " + e.getMessage()); } + } else { + System.out.println("❌ Deletion cancelled."); } } + private static void viewTables(BookingService bookingService) { + System.out.println("\n═══ ALL TABLES ═══"); + bookingService.getAllTables().forEach(t -> + System.out.println("Table " + t.getTableNumber() + " - Capacity: " + t.getCapacity()) + ); + } + + private static void viewGuests(BookingService bookingService) { + System.out.println("\n═══ ALL GUESTS ═══"); + bookingService.getAllGuests().forEach(g -> + System.out.println(g.getName() + " - " + g.getContact() + " (" + g.getNote() + ")") + ); + } } diff --git a/src/main/java/org/example/entity/BookingService.java b/src/main/java/org/example/entity/BookingService.java new file mode 100644 index 00000000..b3124dbd --- /dev/null +++ b/src/main/java/org/example/entity/BookingService.java @@ -0,0 +1,115 @@ +package org.example.service; + +import jakarta.persistence.EntityManagerFactory; +import org.example.entity.*; + +import java.time.LocalDate; +import java.util.List; + +public class BookingService { + + private final EntityManagerFactory emf; + + public BookingService(EntityManagerFactory emf) { + this.emf = emf; + } + + // Visa alla tillgängliga bord + public List
getAllTables() { + return emf.callInTransaction(em -> + em.createQuery("SELECT t FROM Table t", Table.class).getResultList() + ); + } + + // Visa alla tillgängliga tider + public List getAllTimeSlots() { + return emf.callInTransaction(em -> + em.createQuery("SELECT ts FROM TimeSlot ts", TimeSlot.class).getResultList() + ); + } + + // Visa alla gäster + public List getAllGuests() { + return emf.callInTransaction(em -> + em.createQuery("SELECT g FROM Guest g", Guest.class).getResultList() + ); + } + + // Skapa ny bokning + public void createBooking(Long tableId, Long timeSlotId, LocalDate date, int partySize, List guestIds) { + emf.runInTransaction(em -> { + // Hämta bord + Table table = em.find(Table.class, tableId); + if (table == null) { + throw new IllegalArgumentException("Table not found!"); + } + + // Hämta tidslucka + TimeSlot timeSlot = em.find(TimeSlot.class, timeSlotId); + if (timeSlot == null) { + throw new IllegalArgumentException("TimeSlot not found!"); + } + + // Skapa bokning + Booking booking = new Booking(); + booking.setTime(date); + booking.setTimeSlot(timeSlot); + booking.setParty(partySize); + booking.setTable(table); + + // Lägg till gäster + for (Long guestId : guestIds) { + Guest guest = em.find(Guest.class, guestId); + if (guest != null) { + booking.addGuest(guest); + } + } + + em.persist(booking); + System.out.println("Booking created successfully!"); + }); + } + + // Visa alla bokningar + public List getAllBookings() { + return emf.callInTransaction(em -> + em.createQuery("SELECT b FROM Booking b", Booking.class).getResultList() + ); + } + + // Visa en specifik bokning + public Booking getBooking(Long id) { + return emf.callInTransaction(em -> em.find(Booking.class, id)); + } + + // Uppdatera bokningsstatus + public void updateBookingStatus(Long bookingId, BookingStatus newStatus) { + emf.runInTransaction(em -> { + Booking booking = em.find(Booking.class, bookingId); + if (booking == null) { + throw new IllegalArgumentException("Booking not found!"); + } + + switch (newStatus) { + case CONFIRMED -> booking.confirmBooking(); + case CANCELLED -> booking.cancelBooking(); + case COMPLETED -> booking.completeBooking(); + case NO_SHOW -> booking.noShowBooking(); + } + + System.out.println("Booking status updated to: " + newStatus); + }); + } + + // Ta bort bokning + public void deleteBooking(Long bookingId) { + emf.runInTransaction(em -> { + Booking booking = em.find(Booking.class, bookingId); + if (booking == null) { + throw new IllegalArgumentException("Booking not found!"); + } + em.remove(booking); + System.out.println("Booking deleted successfully!"); + }); + } +} From 988c6e25d9dba6cb62110a03b3b7549aae0dd45b Mon Sep 17 00:00:00 2001 From: youneslamia Date: Fri, 9 Jan 2026 12:54:26 +0100 Subject: [PATCH 19/23] =?UTF-8?q?Meny=20och=20service=20f=C3=B6r=20bokning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/example/App.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 0d152885..07de77a8 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -55,7 +55,7 @@ private static void createInitialData(EntityManagerFactory emf) { hours(emf); createTable(emf); createGuest(emf); - System.out.println("✅ Initial data created!"); + System.out.println("Initial data created!"); } } @@ -130,10 +130,10 @@ public static void mainMenu(BookingService bookingService, EntityManagerFactory case "view tables", "5" -> viewTables(bookingService); case "view guests", "6" -> viewGuests(bookingService); case "exit", "7" -> { - System.out.println("👋 Goodbye!"); + System.out.println("Goodbye!"); running = false; } - default -> System.out.println("❌ Invalid option!"); + default -> System.out.println("Invalid option!"); } } } @@ -178,7 +178,7 @@ private static void createBookingMenu(BookingService bookingService) { try { bookingService.createBooking(tableId, timeSlotId, date, partySize, guestIds); } catch (Exception e) { - System.out.println("❌ Error: " + e.getMessage()); + System.out.println("Error: " + e.getMessage()); } } @@ -214,10 +214,10 @@ private static void updateBookingMenu(BookingService bookingService) { try { bookingService.updateBookingStatus(bookingId, newStatus); } catch (Exception e) { - System.out.println("❌ Error: " + e.getMessage()); + System.out.println("Error: " + e.getMessage()); } } else { - System.out.println("❌ Invalid status!"); + System.out.println("Invalid status!"); } } @@ -229,7 +229,7 @@ private static void viewAllBookings(BookingService bookingService) { System.out.println("No bookings found."); } else { bookings.forEach(b -> { - System.out.println("\n📅 Booking ID: " + b.getId()); + System.out.println("\n Booking ID: " + b.getId()); System.out.println(" Date: " + b.getDate()); System.out.println(" Time: " + b.getTimeSlot().getStartTime() + " - " + b.getTimeSlot().getFinishTime()); System.out.println(" Table: " + b.getTable().getTableNumber()); @@ -252,10 +252,10 @@ private static void deleteBookingMenu(BookingService bookingService) { try { bookingService.deleteBooking(bookingId); } catch (Exception e) { - System.out.println("❌ Error: " + e.getMessage()); + System.out.println("Error: " + e.getMessage()); } } else { - System.out.println("❌ Deletion cancelled."); + System.out.println("Deletion cancelled."); } } From 5a39fed956503c668f949e148c9ac367fc295237 Mon Sep 17 00:00:00 2001 From: youneslamia Date: Mon, 12 Jan 2026 09:30:52 +0100 Subject: [PATCH 20/23] mer funktionalitet, validering felhantering --- src/main/java/org/example/App.java | 244 ++++++++++++------ src/main/java/org/example/entity/Booking.java | 4 +- .../org/example/entity/BookingService.java | 174 ++++++++++--- 3 files changed, 303 insertions(+), 119 deletions(-) diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 07de77a8..c4557009 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -125,7 +125,7 @@ public static void mainMenu(BookingService bookingService, EntityManagerFactory switch (select) { case "create booking", "cb", "1" -> createBookingMenu(bookingService); case "update booking", "ub", "2" -> updateBookingMenu(bookingService); - case "view all bookings", "rb", "3" -> viewAllBookings(bookingService); + case "view all bookings", "rb", "3" -> showBookings(bookingService); case "delete booking", "db", "4" -> deleteBookingMenu(bookingService); case "view tables", "5" -> viewTables(bookingService); case "view guests", "6" -> viewGuests(bookingService); @@ -141,42 +141,99 @@ public static void mainMenu(BookingService bookingService, EntityManagerFactory private static void createBookingMenu(BookingService bookingService) { System.out.println("\n═══ CREATE NEW BOOKING ═══"); - // Visa tillgängliga bord - List
tables = bookingService.getAllTables(); - System.out.println("\n📋 Available Tables:"); - tables.forEach(t -> System.out.println(" " + t.getId() + ". Table " + t.getTableNumber() + " (Capacity: " + t.getCapacity() + ")")); - - Long tableId = Long.parseLong(IO.readln("\nEnter Table ID: ")); - - // Visa tillgängliga tider - List timeSlots = bookingService.getAllTimeSlots(); - System.out.println("\n⏰ Available Time Slots:"); - timeSlots.forEach(ts -> System.out.println(" " + ts.getId() + ". " + ts.getStartTime() + " - " + ts.getFinishTime())); - - Long timeSlotId = Long.parseLong(IO.readln("\nEnter TimeSlot ID: ")); - - // Datum - String dateStr = IO.readln("\nEnter date (YYYY-MM-DD): "); - LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE); + try { + // Visa tillgängliga bord + List
tables = bookingService.getAllTables(); + System.out.println("\n📋 Available Tables:"); + tables.forEach(t -> System.out.println(" " + t.getId() + ". Table " + t.getTableNumber() + " (Capacity: " + t.getCapacity() + ")")); + + Long tableId = Long.parseLong(IO.readln("\nEnter Table ID: ")); + + // Visa tillgängliga tider + List timeSlots = bookingService.getAllTimeSlots(); + System.out.println("\n⏰ Available Time Slots:"); + timeSlots.forEach(ts -> System.out.println(" " + ts.getId() + ". " + ts.getStartTime() + " - " + ts.getFinishTime())); + + Long timeSlotId = Long.parseLong(IO.readln("\nEnter TimeSlot ID: ")); + + // Datum med validering + LocalDate date = null; + while (date == null) { + String dateStr = IO.readln("\nEnter date (YYYY-MM-DD): "); + try { + date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE); + + // Validera att datumet är korrekt + LocalDate today = LocalDate.now(); + // hur många månader fram man kan boka + LocalDate maxDate = today.plusMonths(3); + + if (date.isBefore(today)) { + System.out.println("Date cannot be in the past! Please enter a future date."); + date = null; + } else if (date.isAfter(maxDate)) { + System.out.println("Date cannot be more than 3 months in the future! (Max: " + maxDate + ")"); + date = null; + } + } catch (Exception e) { + System.out.println("Invalid date format! Please use YYYY-MM-DD"); + } + } - // Antal gäster - int partySize = Integer.parseInt(IO.readln("\nEnter party size: ")); + // Antal gäster + int partySize = Integer.parseInt(IO.readln("\nEnter party size: ")); + + // Lägg till gäster + List guestIds = new ArrayList<>(); + String addMore = "y"; + + while (addMore.equalsIgnoreCase("y")) { + System.out.println("\n👥 ADD GUEST:"); + System.out.println("1. Select existing guest"); + System.out.println("2. Create new guest"); + + String guestChoice = IO.readln("Choose option (1 or 2): ").trim(); + + if (guestChoice.equals("1")) { + // Välj befintlig gäst + List guests = bookingService.getAllGuests(); + System.out.println("\n📋 Available Guests:"); + guests.forEach(g -> System.out.println(" " + g.getId() + ". " + g.getName() + " (" + g.getContact() + ")")); + + Long guestId = Long.parseLong(IO.readln("\nEnter Guest ID: ")); + guestIds.add(guestId); + + } else if (guestChoice.equals("2")) { + // Skapa ny gäst + System.out.println("\n═══ CREATE NEW GUEST ═══"); + String name = IO.readln("Enter guest name: "); + String contact = IO.readln("Enter contact (phone/email): "); + String note = IO.readln("Enter note (allergies, preferences, etc.): "); + + try { + Long newGuestId = bookingService.createGuest(name, note, contact); + guestIds.add(newGuestId); + System.out.println("Guest created successfully!"); + } catch (Exception e) { + System.out.println("Error creating guest: " + e.getMessage()); + } + } else { + System.out.println("Invalid option! Please enter 1 or 2."); + continue; + } - // Visa tillgängliga gäster - List guests = bookingService.getAllGuests(); - System.out.println("\n👥 Available Guests:"); - guests.forEach(g -> System.out.println(" " + g.getId() + ". " + g.getName() + " (" + g.getContact() + ")")); + addMore = IO.readln("\nAdd another guest? (y/n): ").trim(); + } - List guestIds = new ArrayList<>(); - String addMore = "y"; - while (addMore.equalsIgnoreCase("y")) { - Long guestId = Long.parseLong(IO.readln("\nEnter Guest ID: ")); - guestIds.add(guestId); - addMore = IO.readln("Add another guest? (y/n): "); - } + // Skapa bokning med validering + try { + bookingService.createBooking(tableId, timeSlotId, date, partySize, guestIds); + } catch (IllegalArgumentException e) { + System.out.println("Booking failed: " + e.getMessage()); + } - try { - bookingService.createBooking(tableId, timeSlotId, date, partySize, guestIds); + } catch (NumberFormatException e) { + System.out.println("Invalid input! Please enter valid numbers."); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } @@ -185,11 +242,20 @@ private static void createBookingMenu(BookingService bookingService) { private static void updateBookingMenu(BookingService bookingService) { System.out.println("\n═══ UPDATE BOOKING ═══"); - viewAllBookings(bookingService); + List bookings = bookingService.getAllBookings(); + + if (bookings.isEmpty()) { + System.out.println("No bookings found to update."); + return; + } - Long bookingId = Long.parseLong(IO.readln("\nEnter Booking ID to update: ")); + // visar alla bokningar + showBookings(bookings); - String statusMenu = """ + try { + Long bookingId = Long.parseLong(IO.readln("\nEnter Booking ID to update: ")); + + String statusMenu = """ Select new status: 1. PENDING @@ -199,66 +265,84 @@ private static void updateBookingMenu(BookingService bookingService) { 5. NO_SHOW """; - String choice = IO.readln(statusMenu + "\nEnter choice: "); - - BookingStatus newStatus = switch (choice) { - case "1" -> BookingStatus.PENDING; - case "2" -> BookingStatus.CONFIRMED; - case "3" -> BookingStatus.CANCELLED; - case "4" -> BookingStatus.COMPLETED; - case "5" -> BookingStatus.NO_SHOW; - default -> null; - }; - - if (newStatus != null) { - try { - bookingService.updateBookingStatus(bookingId, newStatus); - } catch (Exception e) { - System.out.println("Error: " + e.getMessage()); + String choice = IO.readln(statusMenu + "\nEnter choice: "); + + BookingStatus newStatus = switch (choice) { + case "1" -> BookingStatus.PENDING; + case "2" -> BookingStatus.CONFIRMED; + case "3" -> BookingStatus.CANCELLED; + case "4" -> BookingStatus.COMPLETED; + case "5" -> BookingStatus.NO_SHOW; + default -> null; + }; + + if (newStatus != null) { + try { + bookingService.updateBookingStatus(bookingId, newStatus); + } catch (Exception e) { + System.out.println("Error: " + e.getMessage()); + } + } else { + System.out.println("Invalid status!"); } - } else { - System.out.println("Invalid status!"); + } catch (NumberFormatException e) { + System.out.println("Invalid ID format!"); } } - private static void viewAllBookings(BookingService bookingService) { - System.out.println("\n═══ ALL BOOKINGS ═══"); - List bookings = bookingService.getAllBookings(); - if (bookings.isEmpty()) { - System.out.println("No bookings found."); - } else { - bookings.forEach(b -> { - System.out.println("\n Booking ID: " + b.getId()); - System.out.println(" Date: " + b.getDate()); - System.out.println(" Time: " + b.getTimeSlot().getStartTime() + " - " + b.getTimeSlot().getFinishTime()); - System.out.println(" Table: " + b.getTable().getTableNumber()); - System.out.println(" Party Size: " + b.getParty()); - System.out.println(" Status: " + b.getStatus()); - System.out.println(" Guests: " + b.getGuests().stream().map(Guest::getName).toList()); - }); - } - } private static void deleteBookingMenu(BookingService bookingService) { System.out.println("\n═══ DELETE BOOKING ═══"); - viewAllBookings(bookingService); + List bookings = bookingService.getAllBookings(); + + if (bookings.isEmpty()) { + System.out.println("No bookings found to delete."); + return; + } + //Visar alla bokningar - metod längre ner + showBookings(bookings); - Long bookingId = Long.parseLong(IO.readln("\nEnter Booking ID to delete: ")); - String confirm = IO.readln("Are you sure? (y/n): "); + try { + Long bookingId = Long.parseLong(IO.readln("\nEnter Booking ID to delete: ")); + String confirm = IO.readln("Are you sure? (y/n): "); - if (confirm.equalsIgnoreCase("y")) { - try { + if (confirm.equalsIgnoreCase("y")) { bookingService.deleteBooking(bookingId); - } catch (Exception e) { - System.out.println("Error: " + e.getMessage()); + } else { + System.out.println("Deletion cancelled."); } - } else { - System.out.println("Deletion cancelled."); + } catch (NumberFormatException e) { + System.out.println("Invalid ID format!"); } } + private static void showBookings(BookingService bookingService) { + System.out.println("\n═══ ALL BOOKINGS ═══"); + + List bookings = bookingService.getAllBookings(); + + if (bookings.isEmpty()) { + System.out.println("📭 No bookings found."); + return; + } + + showBookings(bookings); + } + + private static void showBookings(List bookings) { + bookings.forEach(b -> { + System.out.println("\n📅 Booking ID: " + b.getId()); + System.out.println(" Date: " + b.getDate()); + System.out.println(" Time: " + b.getTimeSlot().getStartTime() + " - " + b.getTimeSlot().getFinishTime()); + System.out.println(" Table: " + b.getTable().getTableNumber()); + System.out.println(" Party Size: " + b.getParty()); + System.out.println(" Status: " + b.getStatus()); + System.out.println(" Guests: " + b.getGuests().stream().map(Guest::getName).toList()); + }); + } + private static void viewTables(BookingService bookingService) { System.out.println("\n═══ ALL TABLES ═══"); bookingService.getAllTables().forEach(t -> diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index bf8ddafe..388a21e7 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -82,7 +82,7 @@ public LocalDate getDate() { return date; } - public void setTime(LocalDate time) { + public void setDate(LocalDate date) { this.date = date; } @@ -98,7 +98,7 @@ public int getParty() { return partySize; } - public void setParty(int party) { + public void setParty(int partySize) { this.partySize = partySize; } diff --git a/src/main/java/org/example/entity/BookingService.java b/src/main/java/org/example/entity/BookingService.java index b3124dbd..04e15830 100644 --- a/src/main/java/org/example/entity/BookingService.java +++ b/src/main/java/org/example/entity/BookingService.java @@ -14,54 +14,95 @@ public BookingService(EntityManagerFactory emf) { this.emf = emf; } - // Visa alla tillgängliga bord - public List
getAllTables() { - return emf.callInTransaction(em -> - em.createQuery("SELECT t FROM Table t", Table.class).getResultList() - ); - } - - // Visa alla tillgängliga tider - public List getAllTimeSlots() { - return emf.callInTransaction(em -> - em.createQuery("SELECT ts FROM TimeSlot ts", TimeSlot.class).getResultList() - ); - } - - // Visa alla gäster - public List getAllGuests() { - return emf.callInTransaction(em -> - em.createQuery("SELECT g FROM Guest g", Guest.class).getResultList() - ); + // Skapa gäst + public Long createGuest(String name, String note, String contact) { + return emf.callInTransaction(em -> { + Guest guest = new Guest(name, note, contact); + em.persist(guest); + em.flush(); + return guest.getId(); + }); } - // Skapa ny bokning + // Skapa bokning MED validering public void createBooking(Long tableId, Long timeSlotId, LocalDate date, int partySize, List guestIds) { emf.runInTransaction(em -> { - // Hämta bord + // 1. Hämta bord Table table = em.find(Table.class, tableId); if (table == null) { throw new IllegalArgumentException("Table not found!"); } - // Hämta tidslucka + // 2. Hämta tidslucka TimeSlot timeSlot = em.find(TimeSlot.class, timeSlotId); if (timeSlot == null) { throw new IllegalArgumentException("TimeSlot not found!"); } - // Skapa bokning + // 3. VALIDERA KAPACITET + if (partySize > table.getCapacity()) { + throw new IllegalArgumentException( + "Party size (" + partySize + ") exceeds table capacity (" + table.getCapacity() + ")!" + ); + } + + if (partySize < 1) { + throw new IllegalArgumentException("Party size must be at least 1!"); + } + + // 4. VALIDERA DATUM + LocalDate today = LocalDate.now(); + LocalDate maxDate = today.plusMonths(3); + + if (date.isBefore(today)) { + throw new IllegalArgumentException("Cannot book a date in the past!"); + } + + if (date.isAfter(maxDate)) { + throw new IllegalArgumentException("Cannot book more than 3 months in advance!"); + } + + // 5. VALIDERA ATT BORDET INTE ÄR BOKAT FÖR SAMMA TID/DATUM + Long existingBookings = em.createQuery( + "SELECT COUNT(b) FROM Booking b " + + "WHERE b.table.id = :tableId " + + "AND b.date = :date " + + "AND b.timeSlot.id = :timeSlotId " + + "AND b.status != 'CANCELLED'", + Long.class + ) + .setParameter("tableId", tableId) + .setParameter("date", date) + .setParameter("timeSlotId", timeSlotId) + .getSingleResult(); + + if (existingBookings > 0) { + throw new IllegalArgumentException( + "Table " + table.getTableNumber() + + " is already booked for " + date + + " at " + timeSlot.getStartTime() + "!" + ); + } + + // 6. Validera att minst en gäst finns + if (guestIds == null || guestIds.isEmpty()) { + throw new IllegalArgumentException("Booking must have at least one guest!"); + } + + // 7. Skapa bokning Booking booking = new Booking(); - booking.setTime(date); + booking.setDate(date); booking.setTimeSlot(timeSlot); booking.setParty(partySize); booking.setTable(table); - // Lägg till gäster + // 8. Lägg till gäster for (Long guestId : guestIds) { Guest guest = em.find(Guest.class, guestId); if (guest != null) { booking.addGuest(guest); + } else { + throw new IllegalArgumentException("Guest with ID " + guestId + " not found!"); } } @@ -70,24 +111,57 @@ public void createBooking(Long tableId, Long timeSlotId, LocalDate date, int par }); } - // Visa alla bokningar + public List
getAllTables() { + return emf.callInTransaction(em -> + em.createQuery("SELECT t FROM Table t", Table.class).getResultList() + ); + } + + public List getAllTimeSlots() { + return emf.callInTransaction(em -> + em.createQuery("SELECT ts FROM TimeSlot ts", TimeSlot.class).getResultList() + ); + } + + public List getAllGuests() { + return emf.callInTransaction(em -> + em.createQuery("SELECT g FROM Guest g", Guest.class).getResultList() + ); + } + public List getAllBookings() { return emf.callInTransaction(em -> - em.createQuery("SELECT b FROM Booking b", Booking.class).getResultList() + em.createQuery( + "SELECT DISTINCT b FROM Booking b " + + "LEFT JOIN FETCH b.guests " + + "LEFT JOIN FETCH b.table " + + "LEFT JOIN FETCH b.timeSlot", + Booking.class + ).getResultList() ); } - // Visa en specifik bokning public Booking getBooking(Long id) { - return emf.callInTransaction(em -> em.find(Booking.class, id)); + return emf.callInTransaction(em -> + em.createQuery( + "SELECT b FROM Booking b " + + "LEFT JOIN FETCH b.guests " + + "LEFT JOIN FETCH b.table " + + "LEFT JOIN FETCH b.timeSlot " + + "WHERE b.id = :id", + Booking.class + ) + .setParameter("id", id) + .getSingleResult() + ); } - // Uppdatera bokningsstatus public void updateBookingStatus(Long bookingId, BookingStatus newStatus) { emf.runInTransaction(em -> { Booking booking = em.find(Booking.class, bookingId); if (booking == null) { - throw new IllegalArgumentException("Booking not found!"); + System.out.println("Booking with ID " + bookingId + " not found!"); + return; } switch (newStatus) { @@ -101,15 +175,41 @@ public void updateBookingStatus(Long bookingId, BookingStatus newStatus) { }); } - // Ta bort bokning public void deleteBooking(Long bookingId) { emf.runInTransaction(em -> { - Booking booking = em.find(Booking.class, bookingId); - if (booking == null) { - throw new IllegalArgumentException("Booking not found!"); + try { + Booking booking = em.createQuery( + "SELECT b FROM Booking b " + + "LEFT JOIN FETCH b.guests " + + "WHERE b.id = :id", + Booking.class + ) + .setParameter("id", bookingId) + .getSingleResult(); + + em.remove(booking); + System.out.println("Booking deleted successfully!"); + + } catch (jakarta.persistence.NoResultException e) { + System.out.println("Booking with ID " + bookingId + " not found!"); } - em.remove(booking); - System.out.println("Booking deleted successfully!"); }); } + + // Hitta lediga bord för ett specifikt datum/tid + public List
getAvailableTables(LocalDate date, Long timeSlotId) { + return emf.callInTransaction(em -> + em.createQuery( + "SELECT t FROM Table t WHERE t.id NOT IN " + + "(SELECT b.table.id FROM Booking b " + + "WHERE b.date = :date " + + "AND b.timeSlot.id = :timeSlotId " + + "AND b.status != 'CANCELLED')", + Table.class + ) + .setParameter("date", date) + .setParameter("timeSlotId", timeSlotId) + .getResultList() + ); + } } From a8a2cc7db17a5a4856f3504d7747a2ba260e7ef0 Mon Sep 17 00:00:00 2001 From: youneslamia Date: Mon, 12 Jan 2026 10:03:53 +0100 Subject: [PATCH 21/23] tog bort bordsskapande --- src/main/java/org/example/App.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index c4557009..e6fa8d9d 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -53,7 +53,6 @@ private static void createInitialData(EntityManagerFactory emf) { if (count == 0) { hours(emf); - createTable(emf); createGuest(emf); System.out.println("Initial data created!"); } @@ -68,17 +67,6 @@ private static void createGuest(EntityManagerFactory emf) { }); } - private static void createTable(EntityManagerFactory emf) { - emf.runInTransaction(em -> { - for (int i = 1; i <= 5; i++) { - Table table = new Table(); - table.setTableNumber(String.valueOf(i)); - table.setCapacity(i == 4 ? 6 : (i % 2 == 0 ? 2 : 4)); - em.persist(table); - } - }); - } - private static void hours(EntityManagerFactory emf) { emf.runInTransaction(em -> { String[] times = {"16:00", "16:30", "17:00", "17:30", "18:00", "18:30", "19:00"}; From 3e6d5bbd23f843acebeb8398e8d87e8150f91516 Mon Sep 17 00:00:00 2001 From: youneslamia Date: Mon, 12 Jan 2026 10:35:51 +0100 Subject: [PATCH 22/23] =?UTF-8?q?refaktorisering,=20tog=20bort=20metoders?= =?UTF-8?q?=20som=20inte=20anv=C3=A4nds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/example/App.java | 8 ++--- src/main/java/org/example/entity/Booking.java | 15 +-------- .../org/example/entity/BookingService.java | 32 ------------------- src/main/java/org/example/entity/Table.java | 21 ------------ 4 files changed, 5 insertions(+), 71 deletions(-) diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index e6fa8d9d..416d5551 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -48,13 +48,14 @@ public static void main(String[] args) { private static void createInitialData(EntityManagerFactory emf) { // Kolla om data redan finns Long count = emf.callInTransaction(em -> - em.createQuery("SELECT COUNT(t) FROM Table t", Long.class).getSingleResult() + em.createQuery("SELECT COUNT(ts) FROM TimeSlot ts", Long.class).getSingleResult() ); if (count == 0) { hours(emf); createGuest(emf); System.out.println("Initial data created!"); + System.out.println("Create tables manually in the database if necessary!"); } } @@ -70,8 +71,7 @@ private static void createGuest(EntityManagerFactory emf) { private static void hours(EntityManagerFactory emf) { emf.runInTransaction(em -> { String[] times = {"16:00", "16:30", "17:00", "17:30", "18:00", "18:30", "19:00"}; - for (int i = 0; i < times.length; i++) { - String start = times[i]; + for (String start : times) { String[] parts = start.split(":"); int hour = Integer.parseInt(parts[0]) + 2; String end = hour + ":" + parts[1]; @@ -153,7 +153,7 @@ private static void createBookingMenu(BookingService bookingService) { // Validera att datumet är korrekt LocalDate today = LocalDate.now(); - // hur många månader fram man kan boka + // hur många månader fram man kan boka(kan ä LocalDate maxDate = today.plusMonths(3); if (date.isBefore(today)) { diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index 388a21e7..850c787a 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -40,17 +40,6 @@ public class Booking { inverseJoinColumns = @JoinColumn (name = "guest_id")) private List guests = new ArrayList<>(); - public Booking(Long id, LocalDate date, TimeSlot timeSlot, int partySize, Table table, List guests) { - this.id = id; - this.date = date; - this.timeSlot = timeSlot; - this.partySize = partySize; - this.table = table; - this.guests = guests; - this.status = BookingStatus.PENDING; - - } - public void addGuest(Guest guest){ guests.add(guest); guest.getBookings().add(this); @@ -131,10 +120,8 @@ public String toString() { return "Booking{" + "id=" + id + ", date=" + date + - ", timeSlot=" + timeSlot + ", party=" + partySize + - ", table=" + table + - ", guests=" + guests + + ", status=" + status + '}'; } } diff --git a/src/main/java/org/example/entity/BookingService.java b/src/main/java/org/example/entity/BookingService.java index 04e15830..fc9dc86e 100644 --- a/src/main/java/org/example/entity/BookingService.java +++ b/src/main/java/org/example/entity/BookingService.java @@ -141,21 +141,6 @@ public List getAllBookings() { ); } - public Booking getBooking(Long id) { - return emf.callInTransaction(em -> - em.createQuery( - "SELECT b FROM Booking b " + - "LEFT JOIN FETCH b.guests " + - "LEFT JOIN FETCH b.table " + - "LEFT JOIN FETCH b.timeSlot " + - "WHERE b.id = :id", - Booking.class - ) - .setParameter("id", id) - .getSingleResult() - ); - } - public void updateBookingStatus(Long bookingId, BookingStatus newStatus) { emf.runInTransaction(em -> { Booking booking = em.find(Booking.class, bookingId); @@ -195,21 +180,4 @@ public void deleteBooking(Long bookingId) { } }); } - - // Hitta lediga bord för ett specifikt datum/tid - public List
getAvailableTables(LocalDate date, Long timeSlotId) { - return emf.callInTransaction(em -> - em.createQuery( - "SELECT t FROM Table t WHERE t.id NOT IN " + - "(SELECT b.table.id FROM Booking b " + - "WHERE b.date = :date " + - "AND b.timeSlot.id = :timeSlotId " + - "AND b.status != 'CANCELLED')", - Table.class - ) - .setParameter("date", date) - .setParameter("timeSlotId", timeSlotId) - .getResultList() - ); - } } diff --git a/src/main/java/org/example/entity/Table.java b/src/main/java/org/example/entity/Table.java index 6e4c91c8..8fe91186 100644 --- a/src/main/java/org/example/entity/Table.java +++ b/src/main/java/org/example/entity/Table.java @@ -66,25 +66,4 @@ public Long getId() { return id; } - @Override - public String toString() { - return "Table{" + - "id=" + id + - ", bookings=" + bookings + - ", tableNumber='" + tableNumber + '\'' + - ", capacity=" + capacity + - '}'; - } - - @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; - Table table = (Table) o; - return capacity == table.capacity && Objects.equals(id, table.id) && Objects.equals(bookings, table.bookings) && Objects.equals(tableNumber, table.tableNumber); - } - - @Override - public int hashCode() { - return Objects.hash(id, bookings, tableNumber, capacity); - } } From f12317c4b9c4d40646bc581fbd596b30c42df033 Mon Sep 17 00:00:00 2001 From: Samuel Fjellet <229708690+Samuel-Fjellet@users.noreply.github.com> Date: Wed, 14 Jan 2026 12:10:58 +0100 Subject: [PATCH 23/23] =?UTF-8?q?Code=20Rabbit=20=C3=84ndringar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- docker-compose.yml | 4 ++-- src/main/java/org/example/App.java | 6 +++--- src/main/java/org/example/entity/Booking.java | 3 ++- .../org/example/entity/{ => service}/BookingService.java | 6 ++++-- src/main/resources/META-INF/persistence.xml | 4 ++-- 6 files changed, 14 insertions(+), 11 deletions(-) rename src/main/java/org/example/entity/{ => service}/BookingService.java (96%) diff --git a/.gitignore b/.gitignore index d59149fe..244268f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ target/ /.idea/ -docker-compose.yml +.env diff --git a/docker-compose.yml b/docker-compose.yml index 437bcf83..afd5779f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,8 +5,8 @@ services: image: mysql:9.5.0 container_name: restaurant_booking_db environment: - MYSQL_ROOT_PASSWORD: root123 - MYSQL_DATABASE: restaurant_booking + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + MYSQL_DATABASE: ${MYSQL_DATABASE} ports: - "3306:3306" volumes: diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java index 416d5551..6e0a41dd 100644 --- a/src/main/java/org/example/App.java +++ b/src/main/java/org/example/App.java @@ -5,7 +5,7 @@ import jakarta.persistence.*; import org.example.entity.*; import org.example.entity.Table; -import org.example.service.BookingService; +import org.example.entity.service.BookingService; import org.hibernate.jpa.HibernatePersistenceConfiguration; import java.time.LocalDate; @@ -20,8 +20,8 @@ public static void main(String[] args) { final PersistenceConfiguration cfg = new HibernatePersistenceConfiguration("emf") .jdbcUrl("jdbc:mysql://localhost:3306/restaurant_booking") - .jdbcUsername("root") - .jdbcPassword("root123") + .jdbcUsername(System.getenv("MYSQL_USER")) + .jdbcPassword(System.getenv("MYSQL_ROOT_PASSWORD")) .property("hibernate.connection.provider_class", "org.hibernate.hikaricp.internal.HikariCPConnectionProvider") .property("hibernate.hikari.maximumPoolSize", "10") .property("hibernate.hikari.minimumIdle", "5") diff --git a/src/main/java/org/example/entity/Booking.java b/src/main/java/org/example/entity/Booking.java index 850c787a..84df01e9 100644 --- a/src/main/java/org/example/entity/Booking.java +++ b/src/main/java/org/example/entity/Booking.java @@ -19,7 +19,7 @@ public class Booking { private LocalDate date; //day of the reservation @ManyToOne - @JoinColumn(name="timeslot_id") + @JoinColumn(name="timeslot_id", nullable = false) private TimeSlot timeSlot; //time selected from the determited times @Column(name="party_size", nullable = false) @@ -62,6 +62,7 @@ public void cancelBooking(){ public void completeBooking(){ this.status = BookingStatus.COMPLETED; } + public void pendingBooking() { this.status = BookingStatus.PENDING; } public void noShowBooking(){ this.status = BookingStatus.NO_SHOW; } diff --git a/src/main/java/org/example/entity/BookingService.java b/src/main/java/org/example/entity/service/BookingService.java similarity index 96% rename from src/main/java/org/example/entity/BookingService.java rename to src/main/java/org/example/entity/service/BookingService.java index fc9dc86e..7468b542 100644 --- a/src/main/java/org/example/entity/BookingService.java +++ b/src/main/java/org/example/entity/service/BookingService.java @@ -1,4 +1,4 @@ -package org.example.service; +package org.example.entity.service; import jakarta.persistence.EntityManagerFactory; import org.example.entity.*; @@ -68,12 +68,13 @@ public void createBooking(Long tableId, Long timeSlotId, LocalDate date, int par "WHERE b.table.id = :tableId " + "AND b.date = :date " + "AND b.timeSlot.id = :timeSlotId " + - "AND b.status != 'CANCELLED'", + "AND b.status != :cancelledStatus", Long.class ) .setParameter("tableId", tableId) .setParameter("date", date) .setParameter("timeSlotId", timeSlotId) + .setParameter("cancelledStatus", BookingStatus.CANCELLED) .getSingleResult(); if (existingBookings > 0) { @@ -153,6 +154,7 @@ public void updateBookingStatus(Long bookingId, BookingStatus newStatus) { case CONFIRMED -> booking.confirmBooking(); case CANCELLED -> booking.cancelBooking(); case COMPLETED -> booking.completeBooking(); + case PENDING -> booking.pendingBooking(); case NO_SHOW -> booking.noShowBooking(); } diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 308e91e6..df99ab67 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -11,8 +11,8 @@ - - + +