Spring JPA中的java ManyTone关联不更新相关实体
我在使用多对一关联在DB中插入JPA实体时遇到问题
我正在使用:
- 弹簧靴2.1.4。释放
- Ecliselink 2.7.4。RC2(org.eclipse.persistence.jpa)
- spring引导启动器数据jpa
我使用的是Spring的存储库,其中只有一个save方法,没有insert、merge或update方法
我使用一个实体DbWatchlist
,它与另一个实体DbWatchlistProvider
有多对一的关联
如果我创建一个新的DBWatchlist
,其中DbWatchlistProvider
的字段已填充,那么一切都可以正常工作。另外,如果我更改了一个现有的DbWatchlist
,并且在这里更改了DbWatchlistProvider
的字段,并执行了“保存所有内容”操作
但是,如果我试图用现有的DbWatchlistProvider
创建一个新的DbWatchlist
,JPA总是尝试为DbWatchlistProvider
插入一个新记录
在插入实体DbWatchlist
之前,我试图从数据库中读取DbWatchlistProvider
,然后进行保存,但这里也进行了插入。这将导致一个例外:
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
# 1 楼答案
我也有同样的问题,最近发现了根本原因
在我的例子中,问题是我有两个
@Entity
类引用相同的@Table(name = X)
当发生这种情况时,必须同时更新这两个实体,否则会出现错误,如图所示
解决方案(在我的例子中)是使用DTO投影,而不是为一个表使用重复的实体
简单的修复,但错误会导致方式比清晰更混乱
不知道你是否有同样的问题,但你确实有同样的错误
嗯