Избегайте генерации идентификатора в составном ключе с использованием MapsId - PullRequest
0 голосов
/ 19 июня 2019

Я пытаюсь создать объединенную таблицу с дополнительным столбцом.Как избежать создания составного идентификатора, если один из дочерних объектов не был сохранен ранее во время сохранения сущности объединяемой таблицы?Я использую @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, но в итоге получается исключение, потому что одна из строк не должна быть нулевой.В этом случае описание не обнуляется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...