Получение ConstraintViolationException при сохранении строки со встроенным ключом в таблице с сопоставлением «многие-ко-многим» между двумя объектами с использованием Spring JPA

В нашей весенней загрузке Restful WebService у нас есть две главные таблицы с отношениями «многие ко многим» между ними. Но в таблице транзакций нам нужно одно дополнительное поле (current_time) как часть встроенного ключа, кроме первичных ключей двух таблиц. Теперь мы создали отдельный класс для определения встроенного первичного ключа с помощью @Embeddable. Теперь, вставляя одну строку транзакции в таблицу транзакций с помощью Spring JPA, я вручную устанавливаю первичные ключи в соответствующей сущности и вызываю метод сохранения в соответствующем репозитории. Но он дает мне ConstraintViolationException, поскольку current_time имеет нулевое значение, даже если я установил его вручную. Любая помощь будет высоко оценен.

Первая сущность выглядит следующим образом:

@Entity
@Table(name = "project")
public class Project {
    @Id
    @GenericGenerator(name = "projectid", strategy = "com.sample.upload.entity.ProjectIDGenerator")
    @GeneratedValue(generator = "projectid")
    @Column(name = "projectid")
    private String projectID;
    @Column(name = "project_name")
    private String projectName;
    @Column(name = "project_descr")
    private String projectDesc;
    @Column(name = "project_input_path")
    private String projectPath;
    @Column(name = "project_creation_time")
    private Calendar projectCreationTime;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "project_migration", joinColumns = @JoinColumn(name = "projectid", referencedColumnName = "projectid"), inverseJoinColumns = @JoinColumn(name = "migratorid", referencedColumnName = "migratorid"))
    private List<Migrator> migrators;

    @Column(name = "account_name")
    private String accountName;
    @Column(name = "account_group")
    private String accountGroup;

    public String getProjectID() {
        return projectID;
    }

    public void setProjectID(String projectID) {
        this.projectID = projectID;
    }

    public String getAccountName() {
        return accountName;
    }

    public void setAccountName(String accountName) {
        this.accountName = accountName;
    }

    public String getAccountGroup() {
        return accountGroup;
    }

    public void setAccountGroup(String accountGroup) {
        this.accountGroup = accountGroup;
    }

    public String getProjectName() {
        return projectName;
    }

    public void setProjectName(String projectName) {
        this.projectName = projectName;
    }

    public String getProjectDesc() {
        return projectDesc;
    }

    public void setProjectDesc(String projectDesc) {
        this.projectDesc = projectDesc;
    }

    public String getProjectPath() {
        return projectPath;
    }

    public void setProjectPath(String projectPath) {
        this.projectPath = projectPath;
    }

    public Calendar getProjectCreationTime() {
        return projectCreationTime;
    }

    public void setProjectCreationTime(Calendar projectCreationTime) {
        this.projectCreationTime = projectCreationTime;
    }

    public List<Migrator> getMigrators() {
        return migrators;
    }

    public void setMigrators(List<Migrator> migrators) {
        this.migrators = migrators;
    }

}

Вторая сущность:

@Entity
@GenericGenerator(name = "generatorName", strategy = "increment")
@Table(name = "migrator")
public class Migrator {

    @Id
    @GeneratedValue(generator = "generatorName")
    @Column(name = "migratorid")
    private String migratorId;
    @Column(name = "src_tech_name")
    private String srcTechName;
    @Column(name = "dest_tech_name")
    private String destTechName;
    @Column(name = "migrator_name")
    private String migratorName;
    @Column(name = "migrator_type")
    private String migratorType;

    public String getMigratorId() {
        return migratorId;
    }

    public void setMigratorId(String migratorId) {
        this.migratorId = migratorId;
    }

    public String getSrcTechName() {
        return srcTechName;
    }

    public void setSrcTechName(String srcTechName) {
        this.srcTechName = srcTechName;
    }

    public String getDestTechName() {
        return destTechName;
    }

    public void setDestTechName(String destTechName) {
        this.destTechName = destTechName;
    }

    public String getMigratorName() {
        return migratorName;
    }

    public void setMigratorName(String migratorName) {
        this.migratorName = migratorName;
    }

    public String getMigratorType() {
        return migratorType;
    }

    public void setMigratorType(String migratorType) {
        this.migratorType = migratorType;
    }

    @Override
    public String toString() {
        return "Technology [migratorId = " + migratorId + ", srcTechName = " + srcTechName + ", destTechName = "
                + destTechName + ", migratorName = " + migratorName + ", migratorType = " + migratorType + "]";
    }

}

Сущность таблицы соединения (транзакции):

@Entity
@Table(name = "project_migration")
public class ProjectMigration {

    @EmbeddedId
    private ProjectMigrationID migrationId;

    @Column(name  = "migration_finish_time")
    private Calendar migrationFinishTime;
    @Column(name  = "time_in_millis_for_migration")
    private long timeInMillisForMigration;
    @Column(name  = "migration_status")
    private String migrationStatus;
    @Column(name  = "migrated_codebase_path")
    private String migratedCodeBasePath;

Встроенный класс первичного ключа выглядит следующим образом:

@Embeddable
public class ProjectMigrationID implements Serializable {

    private static final long serialVersionUID = -3623993529011381924L;

    @Column(name = "projectid")
    private String projectId;
    @Column(name = "migratorid")
    private String migratorId;
    @Column(name = "migration_start_time")
    private Calendar migrationStartTime;



    public ProjectMigrationID() {

    }

    public ProjectMigrationID(String projectId, String migratorId, Calendar migrationStartTime) {

        this.projectId = projectId;
        this.migratorId = migratorId;
        this.migrationStartTime = migrationStartTime;
    }

Фрагмент из класса обслуживания:

for (String migratorId : data.getMigratorIds()) {

            Migrator migrator = migratorRepository.findByMigratorId(migratorId);
            migrators.add(migrator);
        }


        if (projectId != null) {
            project = projectRepository.findByProjectID(projectId);
            System.out.println(project==null);
            project.setMigrators(migrators);
            System.out.println("I am here");
            if (project != null) {
                //project.setMigrationStatus("In Progress");

                ProjectMigrationID pmId = new ProjectMigrationID();
                pmId.setProjectId(project.getProjectID());
                pmId.setMigratorId(project.getMigrators().get(0).getMigratorId());
                pmId.setMigrationStartTime(new GregorianCalendar());
                ProjectMigration pm = new ProjectMigration();
                pm.setMigrationId(pmId);
                pm.setMigrationStatus("Pending");
                projectMigrationRepository.save(pm);
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
0
290
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это из-за @JoinTable, где дата не указана, и он пропускает вставку. Если вы добавите столбец со всеми необходимыми первичными ключами, он будет работать должным образом.

Только столбцы, сопоставленные через @JoinTable, будут включены во время вставки или обновления (по умолчанию при сопоставлении используется значение true)

Либо включите столбец даты и времени в класс Project, либо используйте ассоциацию без @JoinTable.

Редактирую через мобильный. Поэтому, пожалуйста, не обращайте внимания на опечатки, если они есть.

Привет @Karthik, Спасибо за ответ. Из-за бизнес-требований я не могу добавить столбец даты ни в одну из сущностей (Project & Migrator). Пожалуйста, дайте мне знать, как еще можно связать эти две таблицы в одну таблицу транзакций.

ABHISHEK SRIVASTAVA 07.05.2018 13:46

Тогда мы не сможем использовать @JoinTable. Создайте объект для таблицы отображения PROJECT_MIGRATION. и сохраните экземпляры, используя таблицу сопоставления для сущностей Project и Mapping. Мы не можем скрыть правду от JPA / Hibernate, если хотим, чтобы он вел себя хорошо: стр. Либо укажите все первичные ключи, либо разбейте сущности и сохраните их обычным способом.

Karthik R 07.05.2018 13:52

Хорошо. Итак, насколько я понимаю из ваших утверждений, я не должен использовать @JoinTable, если я не хочу включать поле current_time в свои классы сущностей. Я нашел одно закрытое решение (хотя оно не использует третий столбец в качестве первичного ключа) ... Могу ли я следовать [ссылка] codejava.net/frameworks/hibernate/… и по-прежнему использовать @JoinTable?

ABHISHEK SRIVASTAVA 07.05.2018 14:06

Да. Как я уже сказал, статьи сохраняются с помощью таблицы сопоставления. В этом случае дополнительный первичный ключ будет сохранен как обычный объект. Кажется, это соответствует моему второму комментарию :) Пожалуйста, отметьте ответ как решенный, если вы нашли способ пройти. :)

Karthik R 07.05.2018 14:19

Другие вопросы по теме