在使用 Spring JPA 在两个实体之间进行多对多映射的 table 中保存带有嵌入键的行时获取 ConstraintViolationException
Getting ConstraintViolationException while saving a row with embedded key in the table with many-to-many mapping between two entities using Spring JPA
在我们的 spring boot Restful WebService 中,我们有两个 master table,它们之间存在多对多关系。但是在交易 table 中,除了两个 table 的主键之外,我们还需要一个额外的字段 (current_time) 作为嵌入键的一部分。现在,我们创建了一个单独的 class 用于使用 @Embeddable 定义嵌入式主键。现在,在使用 Spring JPA 向事务 table 插入一个事务行时,我在相应的实体中手动设置主键并在相应的存储库上调用保存方法。但它给了我 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 + "]";
}
}
加入(事务)table 的实体:
@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;
嵌入式主键class如下:
@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;
}
来自服务 Class 的片段:
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);
这是因为 @JoinTable
不包括日期,它会跳过插入。如果您包括一个包含所有所需主键的列,它将按预期工作。
只有通过 @JoinTable
映射的列将在插入或更新期间包含(映射时默认为 true)
要么在 Project
class 中包含日期时间列,要么在没有 @JoinTable
的情况下使用关联。
我正在通过手机进行编辑。所以请忽略错别字。
在我们的 spring boot Restful WebService 中,我们有两个 master table,它们之间存在多对多关系。但是在交易 table 中,除了两个 table 的主键之外,我们还需要一个额外的字段 (current_time) 作为嵌入键的一部分。现在,我们创建了一个单独的 class 用于使用 @Embeddable 定义嵌入式主键。现在,在使用 Spring JPA 向事务 table 插入一个事务行时,我在相应的实体中手动设置主键并在相应的存储库上调用保存方法。但它给了我 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 + "]";
}
}
加入(事务)table 的实体:
@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;
嵌入式主键class如下:
@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;
}
来自服务 Class 的片段:
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);
这是因为 @JoinTable
不包括日期,它会跳过插入。如果您包括一个包含所有所需主键的列,它将按预期工作。
只有通过 @JoinTable
映射的列将在插入或更新期间包含(映射时默认为 true)
要么在 Project
class 中包含日期时间列,要么在没有 @JoinTable
的情况下使用关联。
我正在通过手机进行编辑。所以请忽略错别字。