SQLIntegrityConstraintViolationException при создании новой вставки в базу данных JPA - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть контроллер 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, все работает нормально.(по крайней мере, не исключение)

...