У меня есть контроллер ProjectContoller
, который должен получить ProjectDto
и сохранить его в своей базе данных.
Я получил для этого следующий код:
@Autowired
ProjectService projectService;
@PostMapping(value = ControllerConstants.CREATE_NEW_PROJECT)
public ResponseEntity createProject(@RequestBody ProjectDto project) {
this.logger.info("Creating Project " + project.toString());
this.projectService.saveProject(project);
return ResponseEntity.ok(HttpStatus.OK);
}
MyProjectService
для этого:
@Autowired
private EntityManager entityManager;
@Autowired
private ProjectConverter projectConverter;
@Override
public void saveProject(ProjectDto projectDto) {
ProjectEntity entity = this.projectConverter.convertDtoToEntityWithDefaultFactory(projectDto);
}
Автосоединение ProjectConverter
:
@Autowired
private FactoryEntityService factoryService;
@Autowired
private ProjectRoleEntityService projectRoleService;
@Autowired
private UserRepository userRepository;
@Autowired
private EntityManager entityManager;
@Transactional
public ProjectEntity convertDtoToEntityWithDefaultFactory(ProjectDto projectDto) {
FactoryEntity defaultFactory = this.factoryService.getOrCreateFactoryEntity(projectDto.getProjectArea());
ProjectEntity projectEntity = new ProjectEntity(projectDto.getProjectNumber(), projectDto.getProjectName(),
defaultFactory, ProjectState.ACTIVE);
UserEntity userEntity = this.userRepository.findUserByShorthand(projectDto.getManagerShorthand()).get();
ProjectRoleEntity projectRole = this.projectRoleService.getManagerProjectRoleEntity();
UserProjectRoleAssignment assignment = new UserProjectRoleAssignment(projectRole, projectEntity, userEntity);
projectEntity.addAssignment(assignment);
userEntity.addAssignment(assignment);
projectRole.addAssignment(assignment);
if (this.entityManager.contains(projectEntity)) {
this.entityManager.merge(projectEntity);
} else {
this.entityManager.persist(projectEntity);
}
this.entityManager.persist(assignment);
this.entityManager.flush();
return projectEntity;
}
ProjectEntity:
@Entity
@Table(name = "PV_PROJECT")
public class ProjectEntity {
@Id
@Column(name = "NUMBER")
private String projectNumber;
@Column(name = "NAME", nullable = false)
private String projectName;
@Column(name = "CREATED", nullable = false)
private LocalDateTime createdDate = LocalDateTime.now();
@Column(name = "LASTUPDATE", nullable = false)
private LocalDateTime lastupdated = LocalDateTime.now();;
@Enumerated(EnumType.STRING)
@Column(name = "STATE", nullable = false)
private ProjectState state;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "FACTORY_ID")
private FactoryEntity factory;
@OneToMany(mappedBy="id.project", cascade= {CascadeType.ALL})
private Set<UserProjectRoleAssignment> assignments = new HashSet<UserProjectRoleAssignment>();
//Getter, Setter, Constructor...
}
И Фабрика:
@Entity
@Table(name = "PV_FACTORY")
public class FactoryEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@Column(name = "NAME", nullable = false, unique = true)
private String name;
@OneToMany(
mappedBy = "factory",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<ProjectEntity> projects = new ArrayList<ProjectEntity>();
@OneToMany(
mappedBy = "factory",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<UserEntity> users = new ArrayList<UserEntity>();
}
Итак, при вызове этого контроллера-API я получаю следующий вывод: (Отладка Hibernate включена)
2018-12-19 01:20:34.018 TRACE 21400 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [INTEGER] - [1]
2018-12-19 01:20:34.022 TRACE 21400 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [INTEGER] - [1]
2018-12-19 01:20:34.026 DEBUG 21400 --- [nio-8080-exec-3] org.hibernate.SQL : SELECT * FROM PV_PROJECTROLE p WHERE p.name = ?
Hibernate: SELECT * FROM PV_PROJECTROLE p WHERE p.name = ?
2018-12-19 01:20:34.026 TRACE 21400 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [Project Manager]
2018-12-19 01:20:34.030 DEBUG 21400 --- [nio-8080-exec-3] org.hibernate.SQL : insert into pv_projectrole (name) values (?)
Hibernate: insert into pv_projectrole (name) values (?)
2018-12-19 01:20:34.034 TRACE 21400 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [Project Manager]
2018-12-19 01:20:34.038 DEBUG 21400 --- [nio-8080-exec-3] org.hibernate.SQL : insert into pv_factory (name) values (?)
Hibernate: insert into pv_factory (name) values (?)
2018-12-19 01:20:34.038 TRACE 21400 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [SD]
2018-12-19 01:20:34.042 DEBUG 21400 --- [nio-8080-exec-3] org.hibernate.SQL : insert into pv_project (created, factory_id, lastupdate, name, state, number) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into pv_project (created, factory_id, lastupdate, name, state, number) values (?, ?, ?, ?, ?, ?)
2018-12-19 01:20:34.046 TRACE 21400 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [TIMESTAMP] - [2018-12-19T01:20:33.958]
2018-12-19 01:20:34.050 TRACE 21400 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [INTEGER] - [2]
2018-12-19 01:20:34.050 TRACE 21400 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [TIMESTAMP] - [2018-12-19T01:20:33.958]
2018-12-19 01:20:34.050 TRACE 21400 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [VARCHAR] - [Name]
2018-12-19 01:20:34.050 TRACE 21400 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [6] as [VARCHAR] - [Number]
2018-12-19 01:20:34.054 WARN 21400 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1452, SQLState: 23000
2018-12-19 01:20:34.054 ERROR 21400 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : Cannot add or update a child row: a foreign key constraint fails (`pvdev`.`pv_project`, CONSTRAINT `pv_project_ibfk_1` FOREIGN KEY (`FACTORY_ID`) REFERENCES `pv_projectfactory` (`id`))
2018-12-19 01:20:34.142 ERROR 21400 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`pvdev`.`pv_project`, CONSTRAINT `pv_project_ibfk_1` FOREIGN KEY (`FACTORY_ID`) REFERENCES `pv_projectfactory` (`id`))
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-java-8.0.13.jar!/:8.0.13]
Кажется, у меня возникла проблема с вновь созданной записью - когда я гарантирую, что естьзапись в моей базе данных перед вызовом метода контроллера createProject
, все работает нормально.(по крайней мере, не исключение)