Я пытаюсь создать объединенную таблицу с дополнительным столбцом.Как избежать создания составного идентификатора, если один из дочерних объектов не был сохранен ранее во время сохранения сущности объединяемой таблицы?Я использую @MapsId для получения частей идентификаторов от сущностей для составного ключа.
Когда я пытаюсь сохранить AssetRepositoryEntity с указанным непостоянным репозиторием (без сгенерированного RepositoryId), я ожидаю, что исключение или сбой каким-то образомдругим способом.Но вместо этого Hibernate пытается сгенерировать Id для непостоянного репозитория
Это родительский объект:
@Entity
@Table(name = "ASSET_REPO_MAP")
public class AssetRepoMapEntity implements Serializable {
@EmbeddedId
private AssetRepositoryId primaryKey;
@ManyToOne(cascade = CascadeType.REMOVE)
@MapsId("repositoryId")
private RepositoryEntity repositoryEntity;
@ManyToOne
@MapsId("assetId")
private AssetEntity assetEntity;
@Column(name = "STATUS", nullable = false)
private Status status = Status.NEW;
public AssetRepoMapEntity(){}
public AssetRepoMapEntity(RepositoryEntity repositoryEntity, AssetEntity assetEntity){
this.repositoryEntity = repositoryEntity;
this.assetEntity = assetEntity;
this.primaryKey = new AssetRepositoryId(repositoryEntity.getId(),assetEntity.getAssetId());
}
................................................................
................................................................
Он имеет составной ключ AssetRepository:
@Embeddable
public class AssetRepositoryId implements Serializable{
@Column(name="repository_id")
private String repositoryId;
@Column(name="asset_id")
private String assetId;
private AssetRepositoryId(){
}
public AssetRepositoryId(String repositoryId, String assetId){
this.repositoryId = repositoryId;
this.assetId = assetId;
}
..................................................................
..................................................................
И дочерний объект RepositoryEntity:
@Entity(name = "repositoryEntity-v2")
@Table(name = "REPOSITORIES")
@DynamicInsert
@DynamicUpdate
public class RepositoryEntity implements Serializable {
private static final long serialVersionUID = 3440851562367009351L;
@Id
@Column(name = "REPOSITORY_ID", nullable = false)
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
private String repository_id;
@Column(name = "description", length = 512, nullable = false)
private String description;
.....................................................................
.....................................................................
@Column(name = "status", length = 64)
@Enumerated(EnumType.STRING)
private Status status = Status.ACTIVE;
@OneToMany(mappedBy = "repositoryEntity", orphanRemoval = true)
private Set<AssetRepoMapEntity> assetRepositoryList = new HashSet<AssetRepoMapEntity>();
....................................................................
....................................................................
@ MapsId обеспечивает RepositoryEntity.repository_id для AssetRepositoryId.repositoryId, насколько я понял.Также стоит упомянуть, что я использую JpaRepository для сохранения AssetRepoMapEntity:
@Repository(value = "assetRepoMapRepository-v2")
public interface AssetRepoMapRepository extends JpaRepository<AssetRepoMapEntity, AssetRepositoryId> {
}
Я пытаюсь сохранить AssetRepoMapEntity:
@RunWith(SpringRunner.class)
@TestConfiguration
public class AssetRepoMapTest {
@Autowired
private AssetRepository assetRepository;
@Autowired
private RepoRepository repoRepository;
@Autowired
private AssetRepoMapRepository assetRepoMapRepository;
RepositoryEntity repositoryEntity;
AssetEntity assetEntity;
@Before
public void setUp() {
repositoryEntity = new RepositoryEntity();
repositoryEntity.setName("repository1");
repositoryEntity.setDescription("repository1 description");
repositoryEntity.setPath("/repository1/path");
repositoryEntity.setStatus(RepositoryEntity.Status.ACTIVE);
assetEntity = new AssetEntity();
assetEntity.setKey("....");
assetEntity.setType(.....);
}
@Test
public void insertAssetItemWithNotExistingRepository() {
assetRepository.save(assetEntity1);
AssetRepoMapEntity assetJoinRepositoryEntity = new AssetRepoMapEntity(this.repositoryEntity1,assetEntity1);
assetRepoMapRepository.save(assetJoinRepositoryEntity);
Optional<AssetRepoMapEntity> result = assetRepoMapRepository.findById(assetJoinRepositoryEntity.getPrimaryKey());
}
}
Ожидаемый результат:
Исключение: RepositoryEntity был создан, но не был сохранен (в переходном состоянии), а его repository_id должен быть нулевым
Фактический результат: Hibernate пытается вставить следующую запись в базу данных, чтобы узаконить сохранение «AssetRepoMapEntity»:
FE=> Parse(stmt=null,query="insert into repositories (status, repository_id) values ($1, $2)",oids={1043,1043})
o.postgresql.core.v3.QueryExecutorImpl : FE=> Bind(stmt=null,portal=null,$1=<'ACTIVE'>,type=VARCHAR,$2=<'3e3e31a2-9ba1-4863-843a-7b07ba30cf2b'>,type=VARCHAR)
1) Отдает ранее созданную сущность со всеми заполненными полями
2) Создает новую сущность только с созданным полем свойства repository_id (все остальные свойства пусты)
3) Попытка вставить сгенерированный raw, но в итоге получается исключение, потому что одна из строк не должна быть нулевой.В этом случае описание не обнуляется.