1

我在使用多对一关联在数据库中插入 JPA 实体时遇到问题。

我在用着:

  • Spring Boot 2.1.4.RELEASE
  • Ecliselink 2.7.4.RC2 (org.eclipse.persistence.jpa)
  • spring-boot-starter-数据-jpa

我正在使用 Spring 的存储库,其中只有一个保存方法,没有插入、合并或更新方法。

我使用DbWatchlist与另一个实体具有多对一关联的实体DbWatchlistProvider

如果我创建一个新DBWatchlist的填充字段,DbWatchlistProvider一切正常。此外,如果我更改现有的DbWatchlist以及此处的字段DbWatchlistProvider并进行保存,则一切正常。

但是,如果我尝试DbWatchlist使用现有DbWatchlistProviderJPA 创建一个新的,总是会尝试为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
4

1 回答 1

0

I've been having the same issue, and recently found out the base cause.

In my case, the problem was that I had two @Entity classes referencing the same @Table(name = X)

When you have such a thing happening, you have to update both entities at the same time, or else you get errors like you're seeing here.

The solution (in my case) is to use a DTO Projection instead of having a duplicate entity for the one table.

Simple fix, but the error causes way more confusion than clarity.

No idea if you've got the same problem or not, but you do have the same error.

HTH!

于 2020-11-16T22:21:44.630 回答