Skip to content
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
73 changes: 73 additions & 0 deletions src/main/java/Director.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import jakarta.persistence.*;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Entity
public class Director {

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

@OneToMany(mappedBy = "director")
private Set<Film> films = new HashSet<>();

private String name;
private String country;
private int birthYear;
@Column(nullable = true)
private Integer yearOfDeath;

public Set<Film> getFilms() {
return films;
}

public void setFilms(Set<Film> films) {
this.films = films;
}

public Integer getYearOfDeath() {
return yearOfDeath;
}

public void setYearOfDeath(Integer yearOfDeath) {
this.yearOfDeath = yearOfDeath;
}

public int getBirthYear() {
return birthYear;
}

public void setBirthYear(int birthYear) {
this.birthYear = birthYear;
}

public String getCountry() {
return country;
}

public void setCountry(String country) {
this.country = country;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public void setId(Long id) {
this.id = id;
}

public Long getId() {
return id;
}

}


61 changes: 61 additions & 0 deletions src/main/java/Film.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import jakarta.persistence.*;

import java.util.List;

@Entity
public class Film {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String title;
@ManyToOne
@JoinColumn(name = "director_id")
private Director director;

public Director getDirector() {
return director;
}

public void setDirector(Director director) {
this.director = director;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public void setId(Long id) {
this.id = id;
}

public Long getId() {
return id;
}

//Lägg till en ny film
public static void addFilm(EntityManager em, String title, Director director) {
Film film = new Film();
film.setTitle(title);
film.setDirector(director);
em.persist(film);
System.out.println("Film tillagd: " + title);
}
Comment on lines +41 to +47
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 null validation and consider extracting to a repository class.

The method lacks null checks for parameters, which could lead to NullPointerException or constraint violations. Additionally, mixing data access logic with entity classes violates separation of concerns—consider moving CRUD operations to a dedicated repository or DAO class.

✅ Proposed fix with validation
 public static void addFilm(EntityManager em, String title, Director director) {
+    if (em == null) {
+        throw new IllegalArgumentException("EntityManager cannot be null");
+    }
+    if (title == null || title.trim().isEmpty()) {
+        throw new IllegalArgumentException("Title cannot be null or empty");
+    }
+    if (director == null) {
+        throw new IllegalArgumentException("Director cannot be null");
+    }
     Film film = new Film();
     film.setTitle(title);
     film.setDirector(director);
     em.persist(film);
     System.out.println("Film tillagd: " + title);
 }
📝 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 static void addFilm(EntityManager em, String title, Director director) {
Film film = new Film();
film.setTitle(title);
film.setDirector(director);
em.persist(film);
System.out.println("Film tillagd: " + title);
}
public static void addFilm(EntityManager em, String title, Director director) {
if (em == null) {
throw new IllegalArgumentException("EntityManager cannot be null");
}
if (title == null || title.trim().isEmpty()) {
throw new IllegalArgumentException("Title cannot be null or empty");
}
if (director == null) {
throw new IllegalArgumentException("Director cannot be null");
}
Film film = new Film();
film.setTitle(title);
film.setDirector(director);
em.persist(film);
System.out.println("Film tillagd: " + title);
}
🤖 Prompt for AI Agents
In @src/main/java/Film.java around lines 41 - 47, The static addFilm method on
Film mixes persistence with the entity and lacks null/empty validation; validate
inputs (check em, title non-null/non-empty, director non-null) and fail fast
(throw IllegalArgumentException) before creating/persisting the Film, and then
move this persistence logic out of the Film entity into a dedicated
repository/DAO (e.g., FilmRepository.addFilm or FilmDao.create) that owns the
EntityManager usage; keep the Film class as a plain entity and have the new
repository handle instantiation, validation, em.persist, and any logging.

//Hämta alla filmer
public static List<Film> getAllFilms(EntityManager em) {
return em.createQuery("FROM Film", Film.class).getResultList();
}
Comment on lines +49 to +51
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 null validation for EntityManager.

The method should validate that the EntityManager parameter is not null to prevent NullPointerException.

✅ Proposed fix
 public static List<Film> getAllFilms(EntityManager em) {
+    if (em == null) {
+        throw new IllegalArgumentException("EntityManager cannot be null");
+    }
     return em.createQuery("FROM Film", Film.class).getResultList();
 }
🤖 Prompt for AI Agents
In @src/main/java/Film.java around lines 49 - 51, getAllFilms should validate
the EntityManager parameter to avoid a NullPointerException; at the start of the
method (in getAllFilms(EntityManager em) of class Film) add a null check for em
and throw an IllegalArgumentException (or another appropriate runtime exception)
with a clear message like "EntityManager must not be null" if it is null,
otherwise proceed to call em.createQuery(...).


//Hämta filmer regisserade av en viss regissör
public static List<Film> getFilmsByDirector(EntityManager em, Director director) {
return em.createQuery("FROM Film f WHERE f.director = :director", Film.class)
.setParameter("director", director)
.getResultList();
}
Comment on lines +54 to +58
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 null validation for parameters.

Both EntityManager and Director parameters should be validated to prevent NullPointerException.

✅ Proposed fix
 public static List<Film> getFilmsByDirector(EntityManager em, Director director) {
+    if (em == null) {
+        throw new IllegalArgumentException("EntityManager cannot be null");
+    }
+    if (director == null) {
+        throw new IllegalArgumentException("Director cannot be null");
+    }
     return em.createQuery("FROM Film f WHERE f.director = :director", Film.class)
         .setParameter("director", director)
         .getResultList();
 }
📝 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 static List<Film> getFilmsByDirector(EntityManager em, Director director) {
return em.createQuery("FROM Film f WHERE f.director = :director", Film.class)
.setParameter("director", director)
.getResultList();
}
public static List<Film> getFilmsByDirector(EntityManager em, Director director) {
if (em == null) {
throw new IllegalArgumentException("EntityManager cannot be null");
}
if (director == null) {
throw new IllegalArgumentException("Director cannot be null");
}
return em.createQuery("FROM Film f WHERE f.director = :director", Film.class)
.setParameter("director", director)
.getResultList();
}
🤖 Prompt for AI Agents
In @src/main/java/Film.java around lines 54 - 58, In getFilmsByDirector validate
inputs at the top: check that EntityManager em and Director director are not
null and if either is null throw an IllegalArgumentException (with a clear
message like "em must not be null" or "director must not be null") before using
them; keep the rest of the method unchanged so the query uses the validated
parameters.



}
63 changes: 63 additions & 0 deletions src/main/java/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import jakarta.persistence.Entity;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;
import jakarta.persistence.PersistenceConfiguration;
import org.hibernate.jpa.HibernatePersistenceConfiguration;

import java.util.List;

public class Main {
public static void main(String[] args) {


final PersistenceConfiguration cfg = new HibernatePersistenceConfiguration("emf")
.jdbcUrl("jdbc:mysql://localhost:3306/film_database")
.jdbcUsername("root")
.jdbcPassword("root")
Comment on lines +14 to +16
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 hardcoded database credentials.

Hardcoded credentials pose a security risk and make the application less flexible. Consider using environment variables, a configuration file, or a secrets management system.

🔒 Proposed fix using environment variables
-            .jdbcUrl("jdbc:mysql://localhost:3306/film_database")
-            .jdbcUsername("root")
-            .jdbcPassword("root")
+            .jdbcUrl(System.getenv().getOrDefault("DB_URL", "jdbc:mysql://localhost:3306/film_database"))
+            .jdbcUsername(System.getenv().getOrDefault("DB_USER", "root"))
+            .jdbcPassword(System.getenv().getOrDefault("DB_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
.jdbcUrl("jdbc:mysql://localhost:3306/film_database")
.jdbcUsername("root")
.jdbcPassword("root")
.jdbcUrl(System.getenv().getOrDefault("DB_URL", "jdbc:mysql://localhost:3306/film_database"))
.jdbcUsername(System.getenv().getOrDefault("DB_USER", "root"))
.jdbcPassword(System.getenv().getOrDefault("DB_PASSWORD", ""))
🤖 Prompt for AI Agents
In @src/main/java/Main.java around lines 14 - 16, The code in Main.java
currently hardcodes DB settings via jdbcUrl, jdbcUsername, and jdbcPassword;
replace these literal values with configuration via environment variables or a
config provider: read System.getenv("DB_JDBC_URL"),
System.getenv("DB_USERNAME"), and System.getenv("DB_PASSWORD") (or use your
existing config loader) and pass those values into the
.jdbcUrl/.jdbcUsername/.jdbcPassword calls, validating that required variables
exist and failing fast with a clear error if they are missing; remove the
hardcoded "jdbc:mysql://localhost:3306/film_database", "root", and "root"
literals and provide sensible defaults only when appropriate and documented.

.property("hibernate.hbm2ddl.auto", "update")
.property("hibernate.show_sql", "true")
.property("hibernate.format_sql", "true")
.property("hibernate.highlight_sql", "true")
.managedClasses(Film.class, Director.class);
try (EntityManagerFactory emf = cfg.createEntityManagerFactory()) {
emf.runInTransaction(em -> {
//Skapa regissör för test
Director director = new Director();
director.setName("Christopher Bolan");
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

Fix typo in director name.

"Christopher Bolan" should likely be "Christopher Nolan".

✏️ Proposed fix
-                    director.setName("Christopher Bolan");
+                    director.setName("Christopher Nolan");
📝 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
director.setName("Christopher Bolan");
director.setName("Christopher Nolan");
🤖 Prompt for AI Agents
In @src/main/java/Main.java at line 26, The director name has a typo: update the
string passed to director.setName from "Christopher Bolan" to the correct
"Christopher Nolan" by editing the call to director.setName in the code where
the director variable is set.

director.setCountry("United States");
director.setBirthYear(1970);
em.persist(director);

//Testa att lägga till filmer
Film.addFilm(em, "The Dirk Knight", director);
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

Fix typo in film title.

"The Dirk Knight" should likely be "The Dark Knight".

✏️ Proposed fix
-                    Film.addFilm(em, "The Dirk Knight", director);
+                    Film.addFilm(em, "The Dark Knight", director);
📝 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
Film.addFilm(em, "The Dirk Knight", director);
Film.addFilm(em, "The Dark Knight", director);
🤖 Prompt for AI Agents
In @src/main/java/Main.java at line 32, Replace the incorrect film title passed
to Film.addFilm: change the string "The Dirk Knight" to "The Dark Knight" in the
Film.addFilm(em, "The Dirk Knight", director) call (and any other occurrences of
the same typo) so the movie title is spelled correctly when creating the Film
record.

Film.addFilm(em, "Inception", director);

//Testa att hämta alla filmer
System.out.println("\nAlla filmer:");
List<Film> films = Film.getAllFilms(em);
films.forEach(film -> System.out.println(film.getTitle()));

//Testa att hämta filmer av en viss regissör
System.out.println("\nAlla filmer av regissör:");
List<Film> filmsByDirector = Film.getFilmsByDirector(em, director);
filmsByDirector.forEach(film -> System.out.println(film.getTitle()));

//If no Films in database, add some
// if (em.createQuery("select count(o) from Film o", Long.class)
// .getSingleResult() == 0) {
// Film film1 = new Film();
// em.persist(film1);
// em.flush();
// Film film2 = new Film();
// em.persist(film2);
// }
// System.out.println("==== Using select query, N + 1 ====");
// em.createQuery("from Film", Film.class)
// .getResultList().forEach(System.out::println);

});

}

}
}