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

В нашей весенней загрузке 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);

1 Ответ

0 голосов
/ 07 мая 2018

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

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

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

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

...