У меня есть приложение, созданное с использованием JHipster 6.x. Я могу успешно создать ветку, если @Version не добавлен для колонки версий. Я не могу понять отношения между оптимистической блокировкой и отношениями ManyToOne. Я тоже пробовал разные каскадные варианты, но все тщетно.
Класс одной стороны:
@Entity
@Table(name = "institute")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@org.springframework.data.elasticsearch.annotations.Document(indexName = "institute")
public class Institute extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@org.springframework.data.elasticsearch.annotations.Field(type = FieldType.Keyword)
private Long id;
@NotNull
@Size(min = 1, max = 15)
@Column(name = "code", length = 15, nullable = false)
private String code;
@NotNull
@Size(min = 3, max = 100)
@Column(name = "name", length = 100, nullable = false)
private String name;
@Version
@Column(name = "version")
private Integer version;
@OneToMany(mappedBy = "institute")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Branch> branches = new HashSet<>();
...
Класс многих сторон:
@Entity
@Table(name = "branch")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@org.springframework.data.elasticsearch.annotations.Document(indexName = "branch")
public class Branch extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@org.springframework.data.elasticsearch.annotations.Field(type = FieldType.Keyword)
private Long id;
@NotNull
@Size(min = 1, max = 15)
@Column(name = "code", length = 15, nullable = false)
private String code;
@NotNull
@Size(min = 3, max = 100)
@Column(name = "name", length = 100, nullable = false)
private String name;
@Version
@Column(name = "version")
private Integer version;
@ManyToOne(optional = false)
@NotNull
@JsonIgnoreProperties("branches")
private Institute institute;
...
Код контроллера
@PostMapping("/branches")
public ResponseEntity<BranchDTO> createBranch(@Valid @RequestBody BranchDTO branchDTO) throws URISyntaxException {
log.debug("REST request to save Branch : {}", branchDTO);
if (branchDTO.getId() != null) {
throw new BadRequestAlertException("A new branch cannot already have an ID", ENTITY_NAME, "idexists");
}
BranchDTO result = branchService.save(branchDTO);
return ResponseEntity.created(new URI("/api/branches/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(applicationName, false, ENTITY_NAME, result.getId().toString()))
.body(result);
}
Сервисный код
public BranchDTO save(BranchDTO branchDTO) {
log.debug("Request to save Branch : {}", branchDTO);
Branch branch = branchMapper.toEntity(branchDTO);
branch = branchRepository.save(branch);
BranchDTO result = branchMapper.toDto(branch);
branchSearchRepository.save(branch);
return result;
}
Mapper (StructMap)
@Mapper(componentModel = "spring", uses = {InstituteMapper.class})
public interface BranchMapper extends EntityMapper<BranchDTO, Branch> {
@Mapping(source = "institute.id", target = "instituteId")
@Mapping(source = "institute.name", target = "instituteName")
BranchDTO toDto(Branch branch);
@Mapping(source = "instituteId", target = "institute")
@Mapping(target = "classGroups", ignore = true)
@Mapping(target = "removeClassGroup", ignore = true)
Branch toEntity(BranchDTO branchDTO);
default Branch fromId(Long id) {
if (id == null) {
return null;
}
Branch branch = new Branch();
branch.setId(id);
return branch;
}
}
Хранилище - JPA CrudRepository
@SuppressWarnings("unused")
@Repository
public interface BranchRepository extends JpaRepository<Branch, Long>, JpaSpecificationExecutor<Branch> {
}
Исключение:
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : c.v.e.domain.Branch.institute -> c.v.e.domain.Institute; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : c.v.e.domain.Branch.institute -> c.v.e.domain.Institute