From b04913a30e131074747c51c5f049302cbb928300 Mon Sep 17 00:00:00 2001 From: opitzju <julian.opitz@stud.hs-hannover.de> Date: Tue, 30 Nov 2021 01:22:47 +0100 Subject: [PATCH] =?UTF-8?q?gr=C3=B6bste=20Fehler=20behoben?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/edu/hsh/dbs2/imdb/Starter.java | 8 +-- .../hsh/dbs2/imdb/entity/CharacterMapper.java | 4 +- .../java/edu/hsh/dbs2/imdb/entity/Genre.java | 5 +- .../java/edu/hsh/dbs2/imdb/entity/Mapper.java | 2 - .../java/edu/hsh/dbs2/imdb/entity/Movie.java | 4 +- .../hsh/dbs2/imdb/entity/MovieCharacter.java | 2 +- .../edu/hsh/dbs2/imdb/entity/MovieMapper.java | 12 +++- .../edu/hsh/dbs2/imdb/entity/MovieType.java | 2 - .../java/edu/hsh/dbs2/imdb/entity/Sex.java | 2 - .../edu/hsh/dbs2/imdb/logic/GenreManager.java | 2 +- .../java/edu/hsh/dbs2/imdb/logic/Manager.java | 6 +- .../edu/hsh/dbs2/imdb/logic/MovieManager.java | 31 +++++++---- .../hsh/dbs2/imdb/logic/PersonManager.java | 2 +- .../imdb/util/EntityManagerFactoryUtil.java | 6 +- .../imdb/util/NullTolerantMapCollector.java | 55 +++++++++++++++++++ .../java/edu/hsh/dbs2/imdb/util/Util.java | 14 +++++ .../META-INF/persistence.example.xml | 4 +- src/test/java/edu/hsh/dbs2/imdb/TestDB.java | 29 +++++++++- 18 files changed, 139 insertions(+), 51 deletions(-) create mode 100644 src/main/java/edu/hsh/dbs2/imdb/util/NullTolerantMapCollector.java diff --git a/src/main/java/edu/hsh/dbs2/imdb/Starter.java b/src/main/java/edu/hsh/dbs2/imdb/Starter.java index 620212b..be85108 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/Starter.java +++ b/src/main/java/edu/hsh/dbs2/imdb/Starter.java @@ -4,7 +4,6 @@ import edu.hsh.dbs2.imdb.gui.SearchMovieDialog; import edu.hsh.dbs2.imdb.gui.SearchMovieDialogCallback; import edu.hsh.dbs2.imdb.logic.ManagerFactory; import edu.hsh.dbs2.imdb.util.EntityManagerFactoryUtil; -import jakarta.persistence.Persistence; import javax.swing.*; @@ -17,12 +16,7 @@ public class Starter { public static void main(String[] args) throws Throwable { ManagerFactory.instance.setSessionFactory(EntityManagerFactoryUtil.createSessionFactory()); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - new Starter().run(); - } - }); + SwingUtilities.invokeLater(() -> new Starter().run()); } diff --git a/src/main/java/edu/hsh/dbs2/imdb/entity/CharacterMapper.java b/src/main/java/edu/hsh/dbs2/imdb/entity/CharacterMapper.java index da4e74f..0d61573 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/entity/CharacterMapper.java +++ b/src/main/java/edu/hsh/dbs2/imdb/entity/CharacterMapper.java @@ -34,11 +34,9 @@ public class CharacterMapper implements Mapper<MovieCharacter, CharacterDTO> { } public MovieCharacter unmapOn(CharacterDTO dto, MovieCharacter character) { - if (people == null || people.isEmpty()) - throw new IllegalStateException("CharacterMapper.unmapOn was called without first setting people."); character.setCharacter(dto.getCharacter()); character.setAlias(dto.getAlias()); - var person = people.stream().filter(p -> p.getName().equals(dto.getCharacter())).findAny().orElseThrow(); + var person = character.getCharacter() == null ? null : people.stream().filter(p -> p.getName().equals(dto.getPlayer())).findAny().orElseThrow(); character.setActor(person); return character; } diff --git a/src/main/java/edu/hsh/dbs2/imdb/entity/Genre.java b/src/main/java/edu/hsh/dbs2/imdb/entity/Genre.java index 06484c5..be287bd 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/entity/Genre.java +++ b/src/main/java/edu/hsh/dbs2/imdb/entity/Genre.java @@ -1,13 +1,10 @@ package edu.hsh.dbs2.imdb.entity; +import jakarta.persistence.*; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; -import jakarta.persistence.*; - -import java.util.Set; - @Getter @Setter @EqualsAndHashCode(onlyExplicitlyIncluded = true) diff --git a/src/main/java/edu/hsh/dbs2/imdb/entity/Mapper.java b/src/main/java/edu/hsh/dbs2/imdb/entity/Mapper.java index 9238684..d50aeac 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/entity/Mapper.java +++ b/src/main/java/edu/hsh/dbs2/imdb/entity/Mapper.java @@ -12,8 +12,6 @@ public interface Mapper<T, E> { return ts.stream().map(this::map).collect(Collectors.toSet()); } - - default Set<T> unmapAll(Collection<E> es) { return es.stream().map(this::unmap).collect(Collectors.toSet()); } diff --git a/src/main/java/edu/hsh/dbs2/imdb/entity/Movie.java b/src/main/java/edu/hsh/dbs2/imdb/entity/Movie.java index d3df27d..cdde9ad 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/entity/Movie.java +++ b/src/main/java/edu/hsh/dbs2/imdb/entity/Movie.java @@ -32,10 +32,10 @@ public class Movie { @Enumerated(EnumType.STRING) private MovieType type; - @OneToMany(cascade = CascadeType.ALL, mappedBy = "movie") + @OneToMany(cascade = CascadeType.ALL, mappedBy = "movie", fetch = FetchType.EAGER) private Set<MovieCharacter> characters; - @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) + @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE) @JoinTable(name = "MovieGenre", joinColumns = @JoinColumn(name = "MovieID"), inverseJoinColumns = @JoinColumn(name = "GenreID")) private Set<Genre> genres; diff --git a/src/main/java/edu/hsh/dbs2/imdb/entity/MovieCharacter.java b/src/main/java/edu/hsh/dbs2/imdb/entity/MovieCharacter.java index ee038e1..e86318f 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/entity/MovieCharacter.java +++ b/src/main/java/edu/hsh/dbs2/imdb/entity/MovieCharacter.java @@ -29,7 +29,7 @@ public class MovieCharacter { @Column(name = "Position") private Integer position; - @ManyToOne + @ManyToOne(cascade = CascadeType.MERGE) @JoinColumn(name = "Actor") private Person actor; diff --git a/src/main/java/edu/hsh/dbs2/imdb/entity/MovieMapper.java b/src/main/java/edu/hsh/dbs2/imdb/entity/MovieMapper.java index a06f4d4..2a57721 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/entity/MovieMapper.java +++ b/src/main/java/edu/hsh/dbs2/imdb/entity/MovieMapper.java @@ -2,7 +2,9 @@ package edu.hsh.dbs2.imdb.entity; import edu.hsh.dbs2.imdb.logic.dto.CharacterDTO; import edu.hsh.dbs2.imdb.logic.dto.MovieDTO; +import edu.hsh.dbs2.imdb.util.NullTolerantMapCollector; import edu.hsh.dbs2.imdb.util.Pair; +import edu.hsh.dbs2.imdb.util.Util; import lombok.Getter; import lombok.Setter; @@ -49,7 +51,7 @@ public class MovieMapper implements Mapper<Movie, MovieDTO> { } public Movie unmapOn(MovieDTO dto, Movie movie) { - if (genres == null || genres.isEmpty()) + if (genres == null && !Util.isNullOrEmpty(dto.getGenres())) throw new IllegalStateException("MovieMapper.unmapOn was called without first setting genres."); movie.setTitle(dto.getTitle()); movie.setYear(dto.getYear()); @@ -64,6 +66,7 @@ public class MovieMapper implements Mapper<Movie, MovieDTO> { public Movie deepUnmapOn(MovieDTO dto, Movie movie) { unmapOn(dto, movie); + charMapper.setMovie(movie); var mapping = mapMatchingDropDeleted(dto.getCharacters(), movie.getCharacters()); var newCharacters = mapping.entrySet().stream() .map(insertOrUpdate(charMapper::unmap, charMapper::unmapOn)) @@ -91,7 +94,7 @@ public class MovieMapper implements Mapper<Movie, MovieDTO> { private Map<CharacterDTO, MovieCharacter> mapMatchingDropDeleted(List<CharacterDTO> dtos, Set<MovieCharacter> characters) { return dtos.stream() .map(dto -> matchMCharToDto(dto, characters)) - .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); + .collect(NullTolerantMapCollector.getCharacterMapper()); } private Pair<CharacterDTO, MovieCharacter> matchMCharToDto(CharacterDTO dto, Set<MovieCharacter> characters) { @@ -100,4 +103,9 @@ public class MovieMapper implements Mapper<Movie, MovieDTO> { .findAny(); return new Pair<>(dto, matching.orElse(null)); } + + public void update(Set<Genre> genres, Set<Person> people) { + setGenres(genres); + charMapper.setPeople(people); + } } diff --git a/src/main/java/edu/hsh/dbs2/imdb/entity/MovieType.java b/src/main/java/edu/hsh/dbs2/imdb/entity/MovieType.java index 01c540c..040cbd6 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/entity/MovieType.java +++ b/src/main/java/edu/hsh/dbs2/imdb/entity/MovieType.java @@ -1,7 +1,5 @@ package edu.hsh.dbs2.imdb.entity; -import java.util.Arrays; - public enum MovieType { V, T, C, G; diff --git a/src/main/java/edu/hsh/dbs2/imdb/entity/Sex.java b/src/main/java/edu/hsh/dbs2/imdb/entity/Sex.java index 3345f32..fb2661f 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/entity/Sex.java +++ b/src/main/java/edu/hsh/dbs2/imdb/entity/Sex.java @@ -1,7 +1,5 @@ package edu.hsh.dbs2.imdb.entity; -import java.util.Arrays; - public enum Sex { f, m; diff --git a/src/main/java/edu/hsh/dbs2/imdb/logic/GenreManager.java b/src/main/java/edu/hsh/dbs2/imdb/logic/GenreManager.java index 865ffae..77cf45e 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/logic/GenreManager.java +++ b/src/main/java/edu/hsh/dbs2/imdb/logic/GenreManager.java @@ -24,7 +24,7 @@ public class GenreManager extends Manager { } Stream<Genre> getGenreImpl() { - return query(Genre.class, (cb, cq) -> cq.select(cq.from(Genre.class))); + return query(Genre.class, (cb, cq) -> cq.select(cq.from(Genre.class))).stream(); } } diff --git a/src/main/java/edu/hsh/dbs2/imdb/logic/Manager.java b/src/main/java/edu/hsh/dbs2/imdb/logic/Manager.java index 691412a..ef70bec 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/logic/Manager.java +++ b/src/main/java/edu/hsh/dbs2/imdb/logic/Manager.java @@ -5,8 +5,8 @@ import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import lombok.Cleanup; +import java.util.List; import java.util.function.BiConsumer; -import java.util.stream.Stream; public class Manager { protected final EntityManagerFactory sessionFactory; @@ -15,11 +15,11 @@ public class Manager { this.sessionFactory = sessionFactory; } - protected <T> Stream<T> query(Class<T> type, BiConsumer<CriteriaBuilder, CriteriaQuery<T>> function) { + protected <T> List<T> query(Class<T> type, BiConsumer<CriteriaBuilder, CriteriaQuery<T>> function) { @Cleanup var entityManager = sessionFactory.createEntityManager(); var cb = entityManager.getCriteriaBuilder(); var cq = cb.createQuery(type); function.accept(cb, cq); - return entityManager.createQuery(cq).getResultStream(); + return entityManager.createQuery(cq).getResultList(); } } diff --git a/src/main/java/edu/hsh/dbs2/imdb/logic/MovieManager.java b/src/main/java/edu/hsh/dbs2/imdb/logic/MovieManager.java index 6303cec..4d6d13b 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/logic/MovieManager.java +++ b/src/main/java/edu/hsh/dbs2/imdb/logic/MovieManager.java @@ -1,12 +1,14 @@ package edu.hsh.dbs2.imdb.logic; -import edu.hsh.dbs2.imdb.entity.*; -import edu.hsh.dbs2.imdb.logic.dto.CharacterDTO; +import edu.hsh.dbs2.imdb.entity.Movie; +import edu.hsh.dbs2.imdb.entity.MovieMapper; import edu.hsh.dbs2.imdb.logic.dto.MovieDTO; +import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import lombok.Cleanup; -import java.util.*; +import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; public class MovieManager extends Manager { @@ -35,7 +37,7 @@ public class MovieManager extends Manager { if (search != null && search.length() > 0) cq.where(cb.like(cb.upper(root.get("title")), "%" + search.toUpperCase() + "%")); }); - return movies.map(mapper::map).collect(Collectors.toList()); + return movies.stream().map(mapper::map).collect(Collectors.toList()); } /** @@ -48,7 +50,7 @@ public class MovieManager extends Manager { * @throws Exception */ public void insertUpdateMovie(final MovieDTO movieDTO) throws Exception { - var movie = findMovieById(movieDTO.getId()); + Optional<Movie> movie = movieDTO.getId() == null ? Optional.empty() : findMovieById(movieDTO.getId()); updateMapper(); if (movie.isPresent()) update(movie.get(), movieDTO); @@ -59,25 +61,31 @@ public class MovieManager extends Manager { private void updateMapper() { var genres = genreManager.getGenreImpl().collect(Collectors.toSet()); var people = personManager.getPeopleImpl(null).collect(Collectors.toSet()); - mapper.setGenres(genres); - mapper.getCharMapper().setPeople(people); + mapper.update(genres, people); } private void insert(MovieDTO dto) throws Exception { - var entityManager = sessionFactory.createEntityManager(); - var movie = mapper.unmap(dto); + @Cleanup var entityManager = sessionFactory.createEntityManager(); entityManager.getTransaction().begin(); + var movie = mapper.unmap(dto); entityManager.persist(movie); entityManager.getTransaction().commit(); } private void update(Movie movie, MovieDTO dto) { - var entityManager = sessionFactory.createEntityManager(); + @Cleanup var entityManager = sessionFactory.createEntityManager(); entityManager.getTransaction().begin(); + movie = mergeIfDetached(movie, entityManager); mapper.deepUnmapOn(dto, movie); entityManager.getTransaction().commit(); } + private Movie mergeIfDetached(Movie movie, EntityManager entityManager) { + if (!entityManager.contains(movie)) + return entityManager.merge(movie); + return movie; + } + /** * Loescht einen Film aus der Datenbank. Es werden auch alle abhaengigen Objekte geloescht, * d.h. alle Charaktere und alle Genre-Zuordnungen. @@ -94,6 +102,7 @@ public class MovieManager extends Manager { return; @Cleanup var entityManager = sessionFactory.createEntityManager(); entityManager.getTransaction().begin(); + movie = mergeIfDetached(movie, entityManager); entityManager.remove(movie); entityManager.getTransaction().commit(); } @@ -113,7 +122,7 @@ public class MovieManager extends Manager { return query(Movie.class, (cb, cq) -> { var root = cq.from(Movie.class); cq.select(root).where(cb.equal(root.get("id"), id)); - }).findAny(); + }).stream().findAny(); } } diff --git a/src/main/java/edu/hsh/dbs2/imdb/logic/PersonManager.java b/src/main/java/edu/hsh/dbs2/imdb/logic/PersonManager.java index 175904f..ca2f0c8 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/logic/PersonManager.java +++ b/src/main/java/edu/hsh/dbs2/imdb/logic/PersonManager.java @@ -30,6 +30,6 @@ public class PersonManager extends Manager { cq.select(root); if (text != null && text.length() > 0) cq.where(cb.like(root.get("name"), "%" + text + "%")); - }); + }).stream(); } } diff --git a/src/main/java/edu/hsh/dbs2/imdb/util/EntityManagerFactoryUtil.java b/src/main/java/edu/hsh/dbs2/imdb/util/EntityManagerFactoryUtil.java index ec2e914..66846d9 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/util/EntityManagerFactoryUtil.java +++ b/src/main/java/edu/hsh/dbs2/imdb/util/EntityManagerFactoryUtil.java @@ -1,17 +1,13 @@ package edu.hsh.dbs2.imdb.util; -import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; -import java.sql.Connection; -import java.sql.DriverManager; - public class EntityManagerFactoryUtil { public static EntityManagerFactory createSessionFactory() { try { - return Persistence.createEntityManagerFactory("edu.hsh.dbs2.imdb"); + return Persistence.createEntityManagerFactory("edu.hsh.dbs2.imdb", Util.getTestDataProperty()); } catch (Exception e) { System.err.println("Error while connecting to database"); e.printStackTrace(); diff --git a/src/main/java/edu/hsh/dbs2/imdb/util/NullTolerantMapCollector.java b/src/main/java/edu/hsh/dbs2/imdb/util/NullTolerantMapCollector.java new file mode 100644 index 0000000..29e2f80 --- /dev/null +++ b/src/main/java/edu/hsh/dbs2/imdb/util/NullTolerantMapCollector.java @@ -0,0 +1,55 @@ +package edu.hsh.dbs2.imdb.util; + +import edu.hsh.dbs2.imdb.entity.MovieCharacter; +import edu.hsh.dbs2.imdb.logic.dto.CharacterDTO; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collector; + +public class NullTolerantMapCollector<T, E> implements Collector<Pair<T, E>, Map<T, E>, Map<T, E>> { + + public static Collector<Pair<CharacterDTO, MovieCharacter>, Map<CharacterDTO, MovieCharacter>, Map<CharacterDTO, MovieCharacter>> getCharacterMapper() { + return new NullTolerantMapCollector<>(); + } + + @Override + public Supplier<Map<T, E>> supplier() { + return HashMap::new; + } + + @Override + public BiConsumer<Map<T, E>, Pair<T, E>> accumulator() { + return NullTolerantMapCollector::put; + } + + private static <T,E> void put(Map<T, E> map, Pair<T, E> pair) { + map.put(pair.key, pair.value); + } + + @Override + public BinaryOperator<Map<T, E>> combiner() { + return NullTolerantMapCollector::combine; + } + + private static <T, E> Map<T, E> combine(Map<T, E> map1, Map<T, E> map2) { + map1.putAll(map2); + return map1; + } + + @Override + public Function<Map<T, E>, Map<T, E>> finisher() { + return Function.identity(); + } + + @Override + public Set<Characteristics> characteristics() { + return Collections.singleton(Characteristics.IDENTITY_FINISH); + } +} diff --git a/src/main/java/edu/hsh/dbs2/imdb/util/Util.java b/src/main/java/edu/hsh/dbs2/imdb/util/Util.java index 4c87c54..655637e 100644 --- a/src/main/java/edu/hsh/dbs2/imdb/util/Util.java +++ b/src/main/java/edu/hsh/dbs2/imdb/util/Util.java @@ -1,6 +1,20 @@ package edu.hsh.dbs2.imdb.util; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + public class Util { private Util() {} + public static <T> boolean isNullOrEmpty(Collection<T> coll) { + return coll == null || coll.isEmpty(); + } + + public static Map<String, String> getTestDataProperty() { + var properties = new HashMap<String, String>(); + properties.put("jakarta.persistence.sql-load-script-source", "src/main/resources/TestData.sql"); + return properties; + } + } diff --git a/src/main/resources/META-INF/persistence.example.xml b/src/main/resources/META-INF/persistence.example.xml index ff1b4b1..3f3181d 100644 --- a/src/main/resources/META-INF/persistence.example.xml +++ b/src/main/resources/META-INF/persistence.example.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <persistence xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"> - <persistence-unit name="edu.hsh.dbs2.imdb"> + <persistence-unit name="edu.hsh.dbs2.imdb" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <properties> <property name="jakarta.persistence.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/> @@ -14,7 +14,7 @@ <property name="jakarta.persistence.schema-generation.create-script-source" value="src/main/resources/Schema.sql"/> <property name="jakarta.persistence.schema-generation.drop-script-source" value="src/main/resources/DropSchema.sql"/> <property name="hibernate.check_nullability" value="true"/> - <property name="hibernate.jdbc.use_getGeneratedKeys" value="true"/> + <property name="hibernate.hbm2ddl.auto" value="validate"/> </properties> </persistence-unit> </persistence> \ No newline at end of file diff --git a/src/test/java/edu/hsh/dbs2/imdb/TestDB.java b/src/test/java/edu/hsh/dbs2/imdb/TestDB.java index 6a7b4db..44e59d0 100644 --- a/src/test/java/edu/hsh/dbs2/imdb/TestDB.java +++ b/src/test/java/edu/hsh/dbs2/imdb/TestDB.java @@ -1,6 +1,7 @@ package edu.hsh.dbs2.imdb; import edu.hsh.dbs2.imdb.entity.*; +import edu.hsh.dbs2.imdb.util.Util; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; import jakarta.persistence.PersistenceException; @@ -19,9 +20,7 @@ public class TestDB { @BeforeClass public static void setUp() { - var properties = new HashMap<String, String>(); - properties.put("jakarta.persistence.sql-load-script-source", "src/main/resources/TestData.sql"); - sessionFactory = Persistence.createEntityManagerFactory("edu.hsh.dbs2.imdb", properties); + sessionFactory = Persistence.createEntityManagerFactory("edu.hsh.dbs2.imdb", Util.getTestDataProperty()); } @AfterClass @@ -73,4 +72,28 @@ public class TestDB { assertEquals("Bob", character.get().getActor().getName()); assertEquals(Sex.m, character.get().getActor().getSex()); } + + @Test + public void testInsertDeleteMovie() { + @Cleanup var em = sessionFactory.createEntityManager(); + var movie = new Movie(); + movie.setTitle("The Matrix"); + movie.setType(MovieType.C); + movie.setYear(1998); + em.getTransaction().begin(); + em.persist(movie); + em.flush(); + em.getTransaction().commit(); + var cb = em.getCriteriaBuilder(); + var cq = cb.createQuery(Movie.class); + var root = cq.from(Movie.class); + cq.select(root).where(cb.equal(root.get("id"), movie.getId())); + var sameMovie = em.createQuery(cq).getSingleResult(); + assertEquals(movie.getTitle(), sameMovie.getTitle()); + assertEquals(movie.getType(), sameMovie.getType()); + assertEquals(movie.getYear(), sameMovie.getYear()); + em.getTransaction().begin(); + em.remove(sameMovie); + em.getTransaction().commit(); + } } -- GitLab