Skip to content

Entity/restaurant#6

Open
AnnaZiafar wants to merge 10 commits intomainfrom
entity/Restaurant
Open

Entity/restaurant#6
AnnaZiafar wants to merge 10 commits intomainfrom
entity/Restaurant

Conversation

@AnnaZiafar
Copy link

@AnnaZiafar AnnaZiafar commented Dec 17, 2025

Summary by CodeRabbit

  • New Features

    • Added Docker containerization support with sample Dockerfiles and compose configurations.
    • Integrated a MySQL service with persistent volume and automatic schema settings.
    • Introduced restaurant and opening-hours entities for tracking operating times.
  • Chores

    • Ignore local environment file (.env).
    • Added a review-deadline badge to the README.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 17, 2025

Warning

Rate limit exceeded

@AnnaZiafar has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 1 minutes and 37 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between e51c6ec and 8651770.

📒 Files selected for processing (1)
  • src/main/java/org/example/entities/OpeningHours.java (1 hunks)

Walkthrough

Adds Dockerfiles and docker-compose configs for MySQL, introduces JPA entity classes Restaurant and OpeningHours with getters/setters and validation, adds persistence.xml for a JPA persistence unit, and updates repository metadata (.gitignore and README badge).

Changes

Cohort / File(s) Summary
Repository metadata
\.gitignore, README.md, dfg
.env added to .gitignore; review-assignment badge added to README.md; dfg contains commit history/metadata entries.
Root Docker definitions
Dockerfile, docker-compose.yaml
New root Dockerfile (eclipse-temurin:21-jdk, copies src/main/java/org/example/App.java to /App.java, entrypoint java /App.java); root docker-compose.yaml adds a mysql:9.5.0 service with env vars (root/user/db), exposes 3306, and declares mysql_data volume.
Project-level Docker artifacts
src/docker/Dockerfile, src/docker/docker-compose.yml
New src/docker/Dockerfile (eclipse-temurin:25-jdk, copies compiled App.class to /app/Docker/App.class, entrypoint runs Docker.Demo with classpath /app); src/docker/docker-compose.yml adds a mysql:9.5.0 service with similar env vars, exposed port 3306, and mysql_data volume.
JPA entities
src/main/java/org/example/entities/Restaurant.java, src/main/java/org/example/entities/OpeningHours.java
Adds Restaurant entity (id, name, category, address, priceRange BigDecimal, rating double, List<OpeningHours> annotated @OneToMany with @JoinColumn(name = "openingHoursId")), plus constructors, getters/setters, and toString. Adds OpeningHours entity (id, Weekday enum, openingTime and closingTime LocalTime) with constructors, getters/setters, toString, and validation that openingTime is not after closingTime. No @ManyToOne/Restaurant reference present on OpeningHours.
JPA configuration
src/main/resources/META-INF/persistence.xml
Adds persistence.xml defining persistence-unit jpa-hibernate-mysql with JDBC URL jdbc:mysql://localhost:3306/test, user/password root, Hibernate auto schema update and SQL logging; lists mapped class org.example.Product (no Product entity in this diff).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to entity relationship correctness and mappings:
    • OpeningHours has no Restaurant/@ManyToOne field despite Restaurant holding a List<OpeningHours> with @JoinColumn; verify ownership and schema intent.
    • Restaurant uses @OneToMany with @JoinColumn(name = "openingHoursId") — confirm desired unidirectional mapping and column name.
  • persistence.xml references org.example.Product while new entities are under org.example.entities — update mapped-class entries if needed.
  • Docker inconsistencies to validate:
    • Root Dockerfile (temurin:21) vs src/docker/Dockerfile (temurin:25) and differing copy/entrypoint approaches (source .java vs compiled .class and differing main classes).
    • Duplicate docker-compose files; ensure MySQL credentials, ports, and volume usage are consistent.

Poem

🐇 I hopped in with a Docker song,
MySQL burrowed cozy and strong,
JPA leaves unfolded with care,
Timetables checked in the evening air,
A little rabbit cheers: build, persist, and share! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Entity/restaurant' is vague and generic, using a branch-like naming convention that doesn't clearly convey the specific changes made in the changeset. Use a more descriptive title that summarizes the main changes, such as 'Add Restaurant and OpeningHours JPA entities with Docker configuration' or 'Introduce Restaurant entity with opening hours and database setup'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (9)
.gitignore (1)

3-3: Good catch adding .env to gitignore.

Adding the .env file to gitignore is appropriate given the docker-compose and deployment setup in this PR—it prevents accidental commits of sensitive environment variables (database credentials, API keys, etc.).

For minor consistency with the /.idea/ pattern above it, consider using /.env instead to explicitly match files only at the repository root. That said, the current pattern will work fine.

src/main/java/org/example/entities/Restaurant.java (3)

6-6: Remove unused import.

LocalTime is imported but not used in this class.

-import java.time.LocalTime;

8-19: Consider adding the bidirectional relationship to OpeningHours.

OpeningHours has a @ManyToOne to Restaurant, but Restaurant lacks the inverse @OneToMany. A bidirectional mapping simplifies navigation and is common for parent entities.

+import java.util.ArrayList;
+import java.util.List;
+
 @Entity
 public class Restaurant {

     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id;

     private String name;
     private String category;
     private String address;
     private BigDecimal priceRange;
     private double rating;
+
+    @OneToMany(mappedBy = "restaurant", cascade = CascadeType.ALL, orphanRemoval = true)
+    private List<OpeningHours> openingHours = new ArrayList<>();

Add corresponding getter/setter for the collection.


21-28: Reconsider constructor accepting id parameter.

The id field is auto-generated by the database (GenerationType.IDENTITY). Accepting id in the constructor may cause confusion or unintended behavior if a non-null value is passed for new entities. Consider a constructor without id for creating new entities.

public Restaurant(String name, String category, String address, BigDecimal priceRange, double rating) {
    this.name = name;
    this.category = category;
    this.address = address;
    this.priceRange = priceRange;
    this.rating = rating;
}
src/main/java/org/example/entities/OpeningHours.java (5)

14-16: Consider specifying fetch type for the relationship.

The @ManyToOne relationship uses the default FetchType.EAGER, which may cause performance issues if opening hours are loaded frequently without needing the associated restaurant. Consider whether FetchType.LAZY would be more appropriate for your use case. Additionally, if a restaurant is always required, add optional = false to enforce this constraint.

Example:

-    @ManyToOne
+    @ManyToOne(fetch = FetchType.LAZY, optional = false)
     @JoinColumn(name = "restaurant_id")
     private Restaurant restaurant;

18-18: Consider using an enum for weekday instead of String.

Using a String for weekday allows inconsistent values like "Monday", "monday", "Mon", "MON", etc., which can lead to data quality issues and complicate queries. Consider defining a DayOfWeek enum or using java.time.DayOfWeek to ensure consistency.

Example:

+import java.time.DayOfWeek;
+
-    private String weekday;
+    private DayOfWeek weekday;

Then update the constructor, getters, and setters accordingly.


19-20: Add validation to ensure opening time is before closing time.

The entity allows openingTime to be equal to or after closingTime, which would represent invalid opening hours. Consider adding validation in the setters or using a bean validation constraint to ensure data integrity.

Example for setter validation:

public void setOpeningTime(LocalTime openingTime) {
    if (closingTime != null && openingTime != null && !openingTime.isBefore(closingTime)) {
        throw new IllegalArgumentException("Opening time must be before closing time");
    }
    this.openingTime = openingTime;
}

public void setClosingTime(LocalTime closingTime) {
    if (openingTime != null && closingTime != null && !openingTime.isBefore(closingTime)) {
        throw new IllegalArgumentException("Closing time must be after opening time");
    }
    this.closingTime = closingTime;
}

56-57: Use camelCase for parameter names.

The parameters opening_time and closing_time use snake_case, which is inconsistent with Java naming conventions. Consider renaming to openingTime and closingTime for consistency with the field names and Java standards.

-    public void setOpeningTime(LocalTime opening_time) {
-        this.openingTime = opening_time;
+    public void setOpeningTime(LocalTime openingTime) {
+        this.openingTime = openingTime;
     }

-    public void setClosingTime(LocalTime closing_time) {
-        this.closingTime = closing_time;
+    public void setClosingTime(LocalTime closingTime) {
+        this.closingTime = closingTime;
     }

Also applies to: 64-65


68-77: Include full entity references in toString is acceptable here, but using the ID would be a minor best practice improvement.

The current implementation includes the restaurant object directly (line 72). While this works correctly with the default @ManyToOne fetch type (which is EAGER), following best practices to include only the restaurant ID would simplify the output and make the code more resilient to future relationship changes.

The suggested change is optional:

     @Override
     public String toString() {
         return "OpeningHours{" +
             "id=" + id +
-            ", restaurant=" + restaurant +
+            ", restaurantId=" + (restaurant != null ? restaurant.getId() : null) +
             ", weekday='" + weekday + '\'' +
             ", openingTime=" + openingTime +
             ", closingTime=" + closingTime +
             '}';
     }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8794408 and 929e8bc.

📒 Files selected for processing (10)
  • .gitignore (1 hunks)
  • Dockerfile (1 hunks)
  • README.md (1 hunks)
  • dfg (1 hunks)
  • docker-compose.yaml (1 hunks)
  • src/docker/Dockerfile (1 hunks)
  • src/docker/docker-compose.yml (1 hunks)
  • src/main/java/org/example/entities/OpeningHours.java (1 hunks)
  • src/main/java/org/example/entities/Restaurant.java (1 hunks)
  • src/main/resources/META-INF/persistence.xml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/org/example/entities/Restaurant.java (1)
src/main/java/org/example/entities/OpeningHours.java (1)
  • Entity (7-78)
🔇 Additional comments (2)
README.md (1)

1-1: LGTM!

The GitHub Classroom deadline badge is properly formatted and links to the assignment.

docker-compose.yaml (1)

3-3: MySQL 9.5.0 is a valid and available Docker image version. No action needed on this line.

dfg
Comment on lines +1 to +42
commit 149e0caf9a2d36b0dfd9254b37c62c2bb73d2f0c (HEAD -> main, origin/main, origin/HEAD)
Author: github-classroom[bot] <66690702+github-classroom[bot]@users.noreply.github.com>
Date: Mon Dec 15 09:40:48 2025 +0000

add deadline

commit 879440803daa45b536e2ea5f3ec269d1be62bf04 (upstream/main, upstream/HEAD)
Author: Martin Blomberg <martin.blomberg@outlook.com>
Date: Sun Dec 14 16:07:37 2025 +0100

Setup for JPA application

commit 539e1a559ab7607b40651315e45ef50074c51b8c
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sun Dec 14 12:52:36 2025 +0000

Bump org.mockito:mockito-junit-jupiter in the maven-deps group (#1)

Bumps the maven-deps group with 1 update: [org.mockito:mockito-junit-jupiter](https://github.com/mockito/mockito).


Updates `org.mockito:mockito-junit-jupiter` from 5.20.0 to 5.21.0
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v5.20.0...v5.21.0)

---
updated-dependencies:
- dependency-name: org.mockito:mockito-junit-jupiter
dependency-version: 5.21.0
dependency-type: direct:development
update-type: version-update:semver-minor
dependency-group: maven-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

commit c9a2be0c3d4286e6322bb017f66aa77bbaaa5a00
Author: github-classroom[bot] <66690702+github-classroom[bot]@users.noreply.github.com>
Date: Sun Dec 14 12:51:33 2025 +0000

Initial commit
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove this accidentally committed file.

This file appears to be git log output that was accidentally committed. The filename dfg suggests it may have been created during debugging. It contains ANSI escape codes and commit metadata that should not be part of the repository.

Remove this file from the PR:

git rm dfg
🤖 Prompt for AI Agents
In file dfg lines 1-42: this file is accidental git log output with ANSI escape
codes and commit metadata; remove it from the repository and the PR by deleting
the file and committing that change (run git rm dfg, commit with a clear message
like "remove accidental dfg log file", and push the branch), ensuring no other
valid code is removed and the commit only contains the removal.

Comment on lines +1 to +17
services:
mysql:
image: mysql:9.5.0
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_ROOT_HOST: "%"
MYSQL_DATABASE: app_db
MYSQL_USER: grupp2
MYSQL_PASSWORD: ${PASSWORD}
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Inconsistent docker-compose configurations and hardcoded credentials.

There are two docker-compose files with conflicting configurations:

  • Root docker-compose.yaml: database app_db, password via ${PASSWORD} env var
  • src/docker/docker-compose.yml: database test, hardcoded password morot7

Also, MYSQL_ROOT_PASSWORD is hardcoded on line 6. Consider using environment variables consistently for all sensitive values.

 services:
   mysql:
     image: mysql:9.5.0
     container_name: mysql
     environment:
-      MYSQL_ROOT_PASSWORD: rootpassword
+      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
       MYSQL_ROOT_HOST: "%"
       MYSQL_DATABASE: app_db
       MYSQL_USER: grupp2
       MYSQL_PASSWORD: ${PASSWORD}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
services:
mysql:
image: mysql:9.5.0
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_ROOT_HOST: "%"
MYSQL_DATABASE: app_db
MYSQL_USER: grupp2
MYSQL_PASSWORD: ${PASSWORD}
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
services:
mysql:
image: mysql:9.5.0
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_ROOT_HOST: "%"
MYSQL_DATABASE: app_db
MYSQL_USER: grupp2
MYSQL_PASSWORD: ${PASSWORD}
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
🤖 Prompt for AI Agents
In docker-compose.yaml around lines 1–17, the file hardcodes MYSQL_ROOT_PASSWORD
and uses an env var for MYSQL_PASSWORD while a different compose under
src/docker/docker-compose.yml hardcodes other DB settings, causing inconsistent
configuration and exposure of secrets; update this file to read
MYSQL_ROOT_PASSWORD, MYSQL_DATABASE and MYSQL_PASSWORD from environment
variables (e.g. ${MYSQL_ROOT_PASSWORD}, ${MYSQL_DATABASE}, ${MYSQL_PASSWORD})
instead of literals, then update src/docker/docker-compose.yml to use the same
env variable names (remove the hardcoded password "morot7" and hardcoded DB name
"test"), and add or document a single .env file (or CI secrets) that defines
these variables so both compose files stay consistent and no credentials are
hardcoded.

Comment on lines +1 to +6
FROM eclipse-temurin:21-jdk

COPY src/main/java/org/example/App.java /App.java

ENTRYPOINT ["java", "/App.java"]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Source-file execution won't work with JPA dependencies.

Running java /App.java uses Java's single-file source execution, which doesn't support external dependencies. Since the application uses JPA/Hibernate, this approach will fail.

Consider building with Maven and running the compiled application:

-FROM eclipse-temurin:21-jdk
+FROM eclipse-temurin:21-jdk AS build
+WORKDIR /build
+COPY pom.xml .
+COPY src ./src
+RUN ./mvnw package -DskipTests

-COPY src/main/java/org/example/App.java /App.java
-
-ENTRYPOINT ["java", "/App.java"]
+FROM eclipse-temurin:21-jre
+WORKDIR /app
+COPY --from=build /build/target/*.jar app.jar
+ENTRYPOINT ["java", "-jar", "app.jar"]

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In Dockerfile lines 1-6, the current ENTRYPOINT uses Java's single-file source
execution which cannot load external JPA/Hibernate dependencies; replace this
with a build-and-run flow: use a multi-stage Dockerfile (or build artifact
externally) that runs Maven to compile/package the app into a fat/uber JAR (mvn
package or mvn -DskipTests package with a plugin like
maven-shade/spring-boot-maven-plugin), copy the resulting JAR into a slim JRE
base image, and change ENTRYPOINT to run java -jar /app.jar so the JVM can load
all JPA dependencies at runtime.

Comment on lines +4 to +9
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_ROOT_HOST: "%"
MYSQL_DATABASE: test
MYSQL_USER: grupp2
MYSQL_PASSWORD: morot7
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Hardcoded database credentials committed to repository.

Sensitive credentials (root, morot7) are hardcoded and will be visible in version control history. Use environment variables or Docker secrets instead.

 services:
   mysql:
     image: mysql:9.5.0
     environment:
-      MYSQL_ROOT_PASSWORD: root
+      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
       MYSQL_ROOT_HOST: "%"
-      MYSQL_DATABASE: test
+      MYSQL_DATABASE: ${MYSQL_DATABASE:-app_db}
       MYSQL_USER: grupp2
-      MYSQL_PASSWORD: morot7
+      MYSQL_PASSWORD: ${MYSQL_PASSWORD}

Add a .env.example file to document required variables without exposing actual values.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/docker/docker-compose.yml around lines 4 to 9, the MySQL credentials are
hardcoded which exposes secrets in VCS; replace the literal values with
references to environment variables or Docker secrets (e.g., use
${MYSQL_ROOT_PASSWORD}, ${MYSQL_DATABASE}, ${MYSQL_USER}, ${MYSQL_PASSWORD} or
configure docker secrets) and update docker-compose to read from an env_file or
secrets block; add a .env.example committed to the repo that lists the required
variable names (with placeholder values) and update README or compose docs to
instruct developers to create a real .env (or secrets) with actual credentials
outside of version control.

Comment on lines +1 to +4
FROM eclipse-temurin:25-jdk
COPY target/classes/org/example/App.class /app/Docker/App.class
ENTRYPOINT ["java", "-cp", "/app", "Docker.Demo"]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Class mismatch will cause runtime failure.

The Dockerfile copies App.class to /app/Docker/App.class but the entrypoint attempts to run Docker.Demo. This will fail with ClassNotFoundException since no Demo.class exists.

Either copy the correct class file or fix the entrypoint to match:

 FROM eclipse-temurin:25-jdk
-COPY target/classes/org/example/App.class /app/Docker/App.class
-ENTRYPOINT ["java", "-cp", "/app", "Docker.Demo"]
+COPY target/classes/org/example/App.class /app/org/example/App.class
+ENTRYPOINT ["java", "-cp", "/app", "org.example.App"]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FROM eclipse-temurin:25-jdk
COPY target/classes/org/example/App.class /app/Docker/App.class
ENTRYPOINT ["java", "-cp", "/app", "Docker.Demo"]
FROM eclipse-temurin:25-jdk
COPY target/classes/org/example/App.class /app/org/example/App.class
ENTRYPOINT ["java", "-cp", "/app", "org.example.App"]
🤖 Prompt for AI Agents
In src/docker/Dockerfile lines 1-4: the Dockerfile copies App.class to
/app/Docker/App.class but ENTRYPOINT tries to run Docker.Demo, causing
ClassNotFoundException. Fix by making the copied class and the entrypoint match:
either copy the Demo.class (from the build output) into /app/Docker/Demo.class
if you intend to run Docker.Demo, or change the ENTRYPOINT to the actual class
you copied (e.g., the package-qualified org.example.App) and ensure the -cp
includes /app; update paths/names accordingly so the class on disk matches the
runtime class name.

Comment on lines +22 to +28
public OpeningHours(Long id, Restaurant restaurant, String weekday, LocalTime openingTime, LocalTime closingTime) {
this.id = id;
this.restaurant = restaurant;
this.weekday = weekday;
this.openingTime = openingTime;
this.closingTime = closingTime;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove id parameter from constructor to prevent misuse of auto-generated field.

The constructor accepts an id parameter for a field annotated with @GeneratedValue, which is problematic. When creating new entities, the ID should be managed by the persistence provider, not set manually. Allowing manual ID assignment can lead to:

  • Primary key conflicts
  • Confusion about entity state (transient vs managed)
  • Bypassing database ID generation logic

Apply this diff to create a constructor without the id parameter:

-    public OpeningHours(Long id, Restaurant restaurant, String weekday, LocalTime openingTime, LocalTime closingTime) {
-        this.id = id;
+    public OpeningHours(Restaurant restaurant, String weekday, LocalTime openingTime, LocalTime closingTime) {
         this.restaurant = restaurant;
         this.weekday = weekday;
         this.openingTime = openingTime;
         this.closingTime = closingTime;
     }

If you need to reconstruct entities with existing IDs (e.g., for testing), consider using a separate static factory method or builder pattern instead.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public OpeningHours(Long id, Restaurant restaurant, String weekday, LocalTime openingTime, LocalTime closingTime) {
this.id = id;
this.restaurant = restaurant;
this.weekday = weekday;
this.openingTime = openingTime;
this.closingTime = closingTime;
}
public OpeningHours(Restaurant restaurant, String weekday, LocalTime openingTime, LocalTime closingTime) {
this.restaurant = restaurant;
this.weekday = weekday;
this.openingTime = openingTime;
this.closingTime = closingTime;
}
🤖 Prompt for AI Agents
In src/main/java/org/example/entities/OpeningHours.java around lines 22 to 28,
remove the Long id parameter from the constructor signature and stop assigning
this.id inside the constructor so the JPA @GeneratedValue field is not set
manually; keep parameters for Restaurant, weekday, openingTime, and closingTime
and assign those to their fields, and if you need to reconstruct entities with
existing IDs (e.g., tests), add a separate static factory or builder that sets
the id explicitly rather than using this constructor.

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_2.xsd">
<persistence-unit name="jpa-hibernate-mysql">
<class>org.example.Product</class>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing entity class registrations.

The persistence unit references org.example.Product, but this PR introduces Restaurant and OpeningHours entities that are not registered. These entities won't be managed by JPA.

     <persistence-unit name="jpa-hibernate-mysql">
-        <class>org.example.Product</class>
+        <class>org.example.entities.Restaurant</class>
+        <class>org.example.entities.OpeningHours</class>
         <properties>

Alternatively, if Product is also needed, add all three classes.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<class>org.example.Product</class>
<persistence-unit name="jpa-hibernate-mysql">
<class>org.example.entities.Restaurant</class>
<class>org.example.entities.OpeningHours</class>
<properties>
🤖 Prompt for AI Agents
In src/main/resources/META-INF/persistence.xml around line 7 the
persistence-unit only registers org.example.Product but the PR also introduces
Restaurant and OpeningHours entities; update the <class> entries to include
org.example.Restaurant and org.example.OpeningHours (or include all three if
Product is still needed) so JPA will manage the new entities, and ensure
fully-qualified class names match the package declarations.

Comment on lines +10 to +12
<property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test"/>
<property name="jakarta.persistence.jdbc.user" value="root"/>
<property name="jakarta.persistence.jdbc.password" value="root"/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Hardcoded database credentials in persistence configuration.

Database username and password are hardcoded. For production, consider using environment variable substitution or a separate configuration mechanism.

For development, this is acceptable if credentials match the docker-compose setup. However, note that the database name test only matches src/docker/docker-compose.yml, not the root docker-compose.yaml which uses app_db.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/main/java/org/example/entities/Restaurant.java (1)

82-90: Consider including openingHours in the toString method.

The toString method doesn't include the openingHours field. While omitting it may be intentional to avoid lazy loading issues, including it would provide a more complete representation for debugging purposes.

🔎 Suggested enhancement:
 @Override
 public String toString() {
     return "Restaurant{" +
         "id=" + id +
         ", name='" + name + '\'' +
         ", category='" + category + '\'' +
         ", address='" + address + '\'' +
         ", priceRange=" + priceRange +
         ", rating=" + rating +
+        ", openingHours=" + openingHours +
         '}';
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 929e8bc and 1b0618e.

📒 Files selected for processing (2)
  • src/main/java/org/example/entities/OpeningHours.java (1 hunks)
  • src/main/java/org/example/entities/Restaurant.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/org/example/entities/OpeningHours.java

Comment on lines +16 to +18
@OneToMany
@JoinColumn(name = "openingHoursId")
private List<OpeningHours> openingHours = new ArrayList<>();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix the join column name to reflect the correct relationship.

The join column name "openingHoursId" is semantically incorrect. In a @OneToMany relationship from Restaurant to OpeningHours, the foreign key column in the OpeningHours table should reference the owning Restaurant, so it should be named "restaurantId" (or "restaurant_id" if using snake_case), not "openingHoursId".

🔎 Apply this diff to fix the join column name:
 @OneToMany
-@JoinColumn(name = "openingHoursId")
+@JoinColumn(name = "restaurantId")
 private List<OpeningHours> openingHours = new ArrayList<>();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@OneToMany
@JoinColumn(name = "openingHoursId")
private List<OpeningHours> openingHours = new ArrayList<>();
@OneToMany
@JoinColumn(name = "restaurantId")
private List<OpeningHours> openingHours = new ArrayList<>();
🤖 Prompt for AI Agents
In src/main/java/org/example/entities/Restaurant.java around lines 16 to 18, the
@JoinColumn is using the incorrect name "openingHoursId"; change it to the
foreign-key column that should live on the OpeningHours table referencing
Restaurant (e.g., "restaurantId" or "restaurant_id" following project naming
conventions). Update the @JoinColumn name value accordingly so the OneToMany
mapping uses the correct FK column on OpeningHours and verify database
schema/naming strategy consistency.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find src/main/java -type f -name "*.java" | head -20

Repository: ithsjava25/ithsjava25-java-project-jpa-maven-java-template

Length of output: 240


🏁 Script executed:

cat -n src/main/java/org/example/entities/OpeningHours.java

Repository: ithsjava25/ithsjava25-java-project-jpa-maven-java-template

Length of output: 1975


🏁 Script executed:

cat -n src/main/java/org/example/entities/Restaurant.java

Repository: ithsjava25/ithsjava25-java-project-jpa-maven-java-template

Length of output: 2746


Fix the bidirectional relationship configuration between Restaurant and OpeningHours.

The relationship is incomplete and incorrectly configured:

  1. Incorrect @joincolumn name: The name "openingHoursId" is backwards. The foreign key should reference the Restaurant, typically named "restaurant_id".

  2. Missing @manytoone in OpeningHours: The OpeningHours entity lacks a @ManyToOne field referencing Restaurant, and the constructor parameter restaurant (line 18) is never assigned to any field—indicating an incomplete mapping.

  3. Proper bidirectional setup should be:

    • Restaurant: @OneToMany(mappedBy = "restaurant") (remove @joincolumn)
    • OpeningHours: Add @ManyToOne field with @JoinColumn(name = "restaurant_id") and update the constructor to assign it

this.rating = rating;
}

@Override
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add missing getters and setters for the openingHours field.

The openingHours collection field is missing its getter and setter methods, making it inaccessible to external code. This prevents adding, removing, or querying opening hours for a restaurant.

🔎 Add these methods before the toString:
+public List<OpeningHours> getOpeningHours() {
+    return openingHours;
+}
+
+public void setOpeningHours(List<OpeningHours> openingHours) {
+    this.openingHours = openingHours;
+}
+
 @Override
 public String toString() {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Override
public List<OpeningHours> getOpeningHours() {
return openingHours;
}
public void setOpeningHours(List<OpeningHours> openingHours) {
this.openingHours = openingHours;
}
@Override
public String toString() {
🤖 Prompt for AI Agents
In src/main/java/org/example/entities/Restaurant.java around line 81, the
openingHours collection field lacks public getter and setter methods which
prevents external access and modification; add a public List<OpeningHour>
getOpeningHours() and a public void setOpeningHours(List<OpeningHour>
openingHours) (or appropriate collection type) directly above the toString
method, ensuring imports and null-safety if needed, and keep method visibility
and generics consistent with the field declaration.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (1)
src/main/java/org/example/entities/OpeningHours.java (1)

20-21: Remove id parameter from constructor to prevent misuse of auto-generated field.

The constructor accepts an id parameter for a field annotated with @GeneratedValue, which is problematic. When creating new entities, the ID should be managed by the persistence provider, not set manually. This can lead to:

  • Primary key conflicts
  • Confusion about entity state (transient vs managed)
  • Bypassing database ID generation logic
🔎 Apply this diff to remove the id parameter:
-    public OpeningHours(Long id, Weekday weekday, LocalTime openingTime, LocalTime closingTime) {
-        this.id = id;
+    public OpeningHours(Weekday weekday, LocalTime openingTime, LocalTime closingTime) {
         this.weekday = weekday;
         this.openingTime = openingTime;
         this.closingTime = closingTime;
🧹 Nitpick comments (2)
src/main/java/org/example/entities/OpeningHours.java (2)

17-18: Consider adding validation annotations to prevent null values.

The openingTime and closingTime fields lack validation annotations. If these fields are required, consider adding @Column(nullable = false) or Jakarta Bean Validation annotations like @NotNull to enforce this at both the database and application levels.


69-77: Consider making Weekday enum a top-level class for reusability.

The Weekday enum is currently nested within OpeningHours. If other entities or classes might need to reference days of the week, consider extracting it to a top-level enum in the same package for better reusability.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b0618e and e51c6ec.

📒 Files selected for processing (1)
  • src/main/java/org/example/entities/OpeningHours.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/org/example/entities/OpeningHours.java (1)
src/main/java/org/example/entities/Restaurant.java (1)
  • Entity (9-92)
🔇 Additional comments (2)
src/main/java/org/example/entities/OpeningHours.java (2)

7-12: LGTM!

The entity declaration and auto-generated ID field configuration are correct and follow JPA best practices.


29-29: LGTM!

The no-argument constructor is required by JPA and correctly implemented.

Comment on lines +8 to +18
public class OpeningHours {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Enumerated(EnumType.ORDINAL)
private Weekday weekday;

private LocalTime openingTime;
private LocalTime closingTime;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Missing @ManyToOne relationship to Restaurant entity.

The OpeningHours entity is missing a bidirectional relationship to Restaurant. Looking at Restaurant.java, it defines a @OneToMany relationship, but there's no corresponding @ManyToOne in this entity. This causes several issues:

  1. The foreign key column is not properly defined in the OpeningHours table
  2. The @JoinColumn(name = "openingHoursId") in Restaurant.java is incorrect for a @OneToMany relationship (it would try to place the FK in the wrong table)
  3. Navigation from OpeningHours back to its Restaurant is impossible
🔎 Apply this diff to add the bidirectional relationship:

Add a @ManyToOne field after the id field:

     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id;
 
+    @ManyToOne
+    @JoinColumn(name = "restaurant_id")
+    private Restaurant restaurant;
+
     @Enumerated(EnumType.STRING)
     private Weekday weekday;

Update the constructor to accept the Restaurant parameter:

-    public OpeningHours(Weekday weekday, LocalTime openingTime, LocalTime closingTime) {
+    public OpeningHours(Restaurant restaurant, Weekday weekday, LocalTime openingTime, LocalTime closingTime) {
+        this.restaurant = restaurant;
         this.weekday = weekday;

Add getter and setter for the restaurant field:

public Restaurant getRestaurant() {
    return restaurant;
}

public void setRestaurant(Restaurant restaurant) {
    this.restaurant = restaurant;
}

Additionally, fix the @JoinColumn in Restaurant.java:

// In Restaurant.java, change from:
@OneToMany
@JoinColumn(name = "openingHoursId")
private List<OpeningHours> openingHours = new ArrayList<>();

// To:
@OneToMany(mappedBy = "restaurant")
private List<OpeningHours> openingHours = new ArrayList<>();

Based on the relationship structure observed in Restaurant.java and standard JPA bidirectional OneToMany/ManyToOne patterns.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/org/example/entities/OpeningHours.java around lines 8 to 18,
add a bidirectional ManyToOne relationship to Restaurant so the foreign key is
on the OpeningHours table: declare a private Restaurant restaurant field
annotated with @ManyToOne and @JoinColumn(name = "restaurant_id") placed after
the id field, update the constructors to accept and set the Restaurant
parameter, and add corresponding getRestaurant and setRestaurant methods; then
update src/main/java/org/example/entities/Restaurant.java to change the
OneToMany mapping from using @JoinColumn(name = "openingHoursId") to
@OneToMany(mappedBy = "restaurant") so the relationship is properly mapped.

Comment on lines +25 to +26
if(openingTime.isAfter(closingTime))
throw new RuntimeException("Opening time cannot be after closing time");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use IllegalArgumentException instead of generic RuntimeException.

The validation throws a generic RuntimeException, which makes it harder to handle specific validation failures. Use IllegalArgumentException for input validation errors as it's more semantically appropriate.

🔎 Apply this diff:
         if(openingTime.isAfter(closingTime))
-            throw new RuntimeException("Opening time cannot be after closing time");
+            throw new IllegalArgumentException("Opening time cannot be after closing time");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(openingTime.isAfter(closingTime))
throw new RuntimeException("Opening time cannot be after closing time");
if(openingTime.isAfter(closingTime))
throw new IllegalArgumentException("Opening time cannot be after closing time");
🤖 Prompt for AI Agents
In src/main/java/org/example/entities/OpeningHours.java around lines 25 to 26,
the code throws a generic RuntimeException when openingTime is after
closingTime; replace that with an IllegalArgumentException to more accurately
represent invalid input. Change the throw site to instantiate and throw an
IllegalArgumentException with the same or a slightly more descriptive message,
ensuring callers can catch validation failures specifically.

Comment on lines +47 to +49
public void setOpeningTime(LocalTime opening_time) {
this.openingTime = opening_time;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add validation to setters to maintain time constraints.

The constructor validates that openingTime is not after closingTime (line 25), but the setters setOpeningTime and setClosingTime lack this validation. This allows the invariant to be violated after object construction:

OpeningHours hours = new OpeningHours(Weekday.MONDAY, LocalTime.of(9, 0), LocalTime.of(17, 0)); // Valid
hours.setOpeningTime(LocalTime.of(18, 0)); // Now opening > closing, but no validation!
🔎 Suggested fix - extract validation and apply in setters:

First, extract the validation to a private method:

private void validateTimes(LocalTime opening, LocalTime closing) {
    if (opening != null && closing != null && opening.isAfter(closing)) {
        throw new IllegalArgumentException("Opening time cannot be after closing time");
    }
}

Then update the constructor:

     public OpeningHours(Weekday weekday, LocalTime openingTime, LocalTime closingTime) {
         this.weekday = weekday;
         this.openingTime = openingTime;
         this.closingTime = closingTime;
-        if(openingTime.isAfter(closingTime))
-            throw new RuntimeException("Opening time cannot be after closing time");
+        validateTimes(openingTime, closingTime);
     }

And add validation to both setters:

     public void setOpeningTime(LocalTime opening_time) {
+        validateTimes(opening_time, this.closingTime);
         this.openingTime = opening_time;
     }
     public void setClosingTime(LocalTime closing_time) {
+        validateTimes(this.openingTime, closing_time);
         this.closingTime = closing_time;
     }

Also applies to: 55-57

🤖 Prompt for AI Agents
In src/main/java/org/example/entities/OpeningHours.java around lines 47-49 and
55-57, the setters lack the same time-consistency check used in the constructor,
allowing openingTime to become after closingTime; extract a private
validateTimes(LocalTime opening, LocalTime closing) method that throws
IllegalArgumentException when both times are non-null and
opening.isAfter(closing), call validateTimes from the constructor and from
setOpeningTime and setClosingTime before assigning the fields, and ensure the
setters accept nulls but still enforce the invariant when both times are
present.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants