У меня проблема с вставкой объектов JPA в БД с использованием связи "многие к одному".
Я использую:
- Spring Boot 2.1.4.RELEASE
- Ecliselink 2.7.4.RC2 (org.eclipse.persistence.jpa)
- весна-загрузка-стартер-данные JPA
Я использую репозиторий Spring, где у меня есть только метод сохранения, но нет методов вставки, слияния или обновления.
Я использую сущность DbWatchlist
, которая имеет многозначную связь с другой сущностью DbWatchlistProvider
.
Если я создаю новый DBWatchlist
с заполненными полями DbWatchlistProvider
, все работает нормально. Также, если я изменяю существующий DbWatchlist
, а также здесь поля для DbWatchlistProvider
и делаю сохранение, все работает.
Но если я пытаюсь создать новый DbWatchlist
с существующим DbWatchlistProvider
, JPA всегда пытается ВСТАВИТЬ новую запись для DbWatchlistProvider
.
Я пытался прочитать DbWatchlistProvider
из базы данных, прежде чем вставить в сущность DbWatchlist
и после этого сделать сохранение, но здесь также делается INSERT. Это приводит к исключению:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.4.v20190115-ad5b7c6b2a): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: unique constraint or index violation; SYS_PK_10144 table: WATCHLISTPROVIDER
Error Code: -104
Call: INSERT INTO WatchlistProvider (Key, Description, Id) VALUES (?, ?, ?)
bind => [3 parameters bound]
Мой код:
@Entity
@Table(name = TableName.WATCHLIST, uniqueConstraints = {
@UniqueConstraint(columnNames = {ColumnName.PROVIDER_KEY, ColumnName.ID})})
@UuidGenerator(name = KEY_GENERATOR)
public class DbWatchlist {
@Id
@Column(name = ColumnName.KEY, nullable = false)
@GeneratedValue(generator = KEY_GENERATOR)
public String key;
@ManyToOne(optional = false, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = ColumnName.PROVIDER_KEY, nullable = false, updatable = false)
public DbWatchlistProvider watchlistProvider;
@Column(name = ColumnName.ID, nullable = false)
public String id;
@Column(name = ColumnName.DESCRIPTION)
public String description;
@Column(name = ColumnName.LATEST_VERSION)
public String latestVersion;
}
@Entity
@Table(name = TableName.PROVIDER, uniqueConstraints = {
@UniqueConstraint(columnNames = {ColumnName.ID})})
@UuidGenerator(name = KEY_GENERATOR)
public class DbWatchlistProvider {
@Id
@Column(name = ColumnName.KEY, nullable = false)
@GeneratedValue(generator = KEY_GENERATOR)
public String key;
@Column(name = ColumnName.ID, nullable = false)
public String id;
@Column(name = ColumnName.DESCRIPTION)
public String description;
}
@Repository
public interface WatchlistRepository extends CrudRepository<DbWatchlist, String> {
boolean existsByWatchlistProviderAndId(DbWatchlistProvider provider, String id);
}
В своем тесте я попробовал следующее:
DbWatchlistProvider provider = new DbWatchlistProvider();
provider.id = "PROV";
provider.description = "description for provider";
DbWatchlist newRow = new DbWatchlist();
newRow.id = "ID1";
newRow.description = "description";
newRow.watchlistProvider = provider;
DbWatchlist createdRow = repository.save(newRow);
createdRow.description = "update";
createdRow.watchlistProvider.description = "also updated";
createdRow = repository.save(createdRow);
DbWatchlist createdRow2 = new DbWatchlist();
createdRow2.watchlistProvider = createdRow.watchlistProvider;
createdRow2.id = "test";
createdRow2.description = "description";
//This save is not working, but the createdRow2.watchlistProvider.key is filled
repository.save(createdRow2);
До последнего сохранения все работает без ошибок и, как и ожидалось.
Кто-нибудь знает, в чем проблема и почему DbWatchlistProvider
пытается вставить, а не обновить?
Исключение составляет:
Caused by: javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.4.v20190115-ad5b7c6b2a): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: unique constraint or index violation; SYS_PK_10144 table: WATCHLISTPROVIDER
Error Code: -104
Call: INSERT INTO WatchlistProvider (Key, Description, Id) VALUES (?, ?, ?)
bind => [3 parameters bound]
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.4.v20190115-ad5b7c6b2a): org.eclipse.persistence.exceptions.DatabaseException
Query: InsertObjectQuery
Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: unique constraint or index violation; SYS_PK_10144 table: WATCHLISTPROVIDER
Caused by: org.hsqldb.HsqlException: integrity constraint violation: unique constraint or index violation; SYS_PK_10144 table: WATCHLISTPROVIDER