У меня следующая проблема.У меня есть 2 сущности, Кино и Актер.
Отношение
В фильме есть несколько актеров, но актер может быть в нескольких фильмах.Теперь проблема возникает, когда я пытаюсь добавить 2 фильма, у которых есть общий актер.
Допустим, я добавляю Deadpool, а после этого я добавляю Deadpool 2. Когда я добавляю второйфильм Я получаю следующую ошибку:
Оператор был прерван, поскольку он вызвал бы дублирование значения ключа в ограничении уникального или первичного ключа
Теперь это допустимо, потому чтоjpa вставляет актера в базу данных, которая уже существует.Я не знаю, как я могу решить эту проблему, я получаю идентификаторы из TheMovieDatabase и не хочу, чтобы в моей базе данных были дубликаты Актеров.
MOVIE:
@Entity(name = "Movie")
public class Movie {
//instance variables
@Positive
@Id
private long tmdbId;
...
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "movie_actor",
joinColumns = @JoinColumn(name = "movie_tmdbid"),
inverseJoinColumns = @JoinColumn(name = "actor_id")
)
private Set<Actor> actors = new HashSet<>();
...
Актер:
@Entity(name = "Actor")
public class Actor {
@Id
private long id;
...
@ManyToMany(mappedBy = "actors")
private Set<Movie> movies = new HashSet<>();
Метод добавления Jpa
public void addMovie(Movie movie) {
try {
//open connection
openConnection();
//check
if (movie == null) {
throw new DatabaseException("You cannot add an empty movie");
}
//contains only looks in the current persistence context
if (entityManager.find(Movie.class,movie.getTmdbId()) != null) {
throw new MovieAlreadyExistsException("This movie already exists!");
}
//begin transaction
entityManager.getTransaction().begin();
//add movie & commit
entityManager.persist(movie);
entityManager.getTransaction().commit();
}catch (MovieAlreadyExistsException error){
throw new MovieAlreadyExistsException(error.getMessage(),error);
} catch (Exception error) {
throw new DatabaseException(error.getMessage(), error);
} finally {
closeConnection();
}
}
Метод, который устанавливает актеров: Это займет актеров из TheMovieDatabase, а addMovie - это актера из jpa за фасадом.
//add a movie
@PostMapping(value = "/add")
public String saveMovie(@ModelAttribute("movie") @Valid Movie movie, BindingResult result) {
...
try{
//set actors
Set<Actor> actors = new HashSet<>(mediaService.getMovieActors(movie.getTmdbId()));
movie.setActors(actors);
//add movie with actors
movieService.addMovie(movie);
StackTrace:
Внутреннее исключение: org.apache.derby.shared.common.error.DerbySQLIntegrityConstraintViolationException: оператор был прерван, так как он вызвал бы дублирование значения ключа в ограничении уникального или первичного ключа или уникальном индексе, определенном как «SQL180530224955890», определенном в «ACTOR».Код ошибки: 20000 Вызов: INSERT INTO ACTOR (ID, MOVIECHARACTER, NAME, PROFILEPICTURE) VALUES (?,?,?,?) Bind => [4 параметра привязаны] Запрос: InsertObjectQuery (model.movie.actor.Actor@d681)] с основной причиной ОШИБКА 23505: Оператор был прерван, так как он вызвал бы дублирование значения ключа в ограничении уникального или первичного ключа или уникальном индексе, идентифицированном как «SQL180530224955890», определенном в «ACTOR».в org.apache.derby.client.am.ClientStatement.completeExecute (неизвестный источник) в org.apache.derby.client.net.NetStatementReply.parseEXCSQLSTTreply (неизвестный источник) в org.apache.derby.client.net.NetStatementRepte.read(Неизвестный источник) в org.apache.derby.client.net.StatementReply.readExecute (Неизвестный источник) в org.apache.derby.client.net.NetPreparedStatement.readExecute_ (Неизвестный источник) в org.apache.derby.client.am.ClientPreparedStatement.readExecute (Неизвестный источник) в org.apache.derby.client.am.ClientPreparedStatement.flowExecute (Неизвестный источник) в org.apache.derby.client.am.ClientPreparedStatement.executeUpdateX или неизвестный источник (неизвестный источник).client.am.ClientPreparedStatement.executeUpdate (Неизвестный источник) по адресу org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect (DatabaseAccessor.java:895) по адресу org.eclipse.persistence.internal.databaseorcessecuJava: 967) в org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall (DatabaseAccessor.java:637) в org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall (DatabaseAccessor.java:564) в org.eclipse.persistence.internal.sessions.AbstractSession.allicExSession.Java: 2093) в org.eclipse.persistence.sessions.server.ClientSession.executeCall (ClientSession.java:309) в org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall (DatasourceCallQueryMeecism.j).persistence.internal.queries.DatasourceCallQueryMechanism.executeCall (DatasourceCallQueryMechanism.java:256) при org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject (DatasourceCallQueryMechanism.java:405) при org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject (StatementQueryMechanism.java:165) в org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject (StatementQueryMechanism.java:180)в org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite (DatabaseQueryMechanism.java:502) в org.eclipse.persistence.queries.InsertObjectQuery.executeCommit (InsertObjectQuery.javasertOip.yery.lip.uery.uipse.user.user.user.user.user.user.user или.executeCommitWithChangeSet (InsertObjectQuery.java:90) при org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet (DatabaseQueryMechanism.java:314) при org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery (WriteObjectQuery.java:58) вorg.eclipse.persistence.queries.DatabaseQuery.execute (DatabaseQuery.java:911) по адресу org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork (DatabaseQuery.java:810) по адресу org.eclipse.persistence.quvel.OodeQuifyUquifyObjectLevelModifyQuery.java:108) в org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork (ObjectLevelModifyQuery.java:85) в org.eclipse.persistence.internal.Sessions.UnitOfWorkImpl.internalExecuteQuery (UnitOfWorkImpl.java:2979) в org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery (AbstractSession.java:1892) в org.eclipse.persistence.internal.SessionJava: 1874) в org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery (AbstractSession.java:1824) в org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet (CommitManecip или or CommitManager.java).persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet (CommitManager.java:194) в org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet (CommitManager.jsessgAl.in.writeAllObjectsWithChangeSet (AbstractSession.java:4384) в org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase (UnitOfWorkImpl.java:1491) в org.eclipse.persistence.internal.sessions.UnitWorkImpl.commitToDatabaseWithChangeSet (UnitOfWorkImpl.java:1581) в org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork (RepeatableWriteUnitOfWork.java:278) в org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume (UnitOfWorkImpl.java:1218) в org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit (EntityTransactionImpl.java:134) в model.db.types.MovieDatabaseJpa.addMovie (MovieDatabaseJpa.java:66) в модели. MovieService.java: 19) at web.controller.MovieController.saveMovie (MovieController.java:72) в sun.reflect.NativeMethodAccessorImpl.invoke0 (родной метод) в sun.reflect.NativeMethodAccessorImpl.invoke (собственный).отражения.в орг.сpringframework.web.method.support.InvocableHandlerMethod.invokeForRequest (InvocableHandlerMethod.java:136) в org.springframework.web.servlet.mvc.method.annotation.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod (RequestMappingHandlerAdapter.java:870) в org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdaping.servlet.mvc.method.AbstractHandlerMethodAdapter.handle (AbstractHandlerMethodAdapter.java:87) в org.springframework.web.servlet.DispatcherServlet.doDispatch (DispatcherServlet.java:991)по адресу org.springframework.web.servlet.DispatcherServlet.doService (DispatcherServlet.java:925) по адресу org.springframework.web.servlet.FrameworkServlet.processRequest (FrameworkServlet.java:978) at org.sprervwork(FrameworkServlet.java:881)
Может кто-нибудь указать мне правильное направление?Спасибо!