Code for Module:
@Data
@NoArgsConstructor
@ToString
@Entity(name = "modules")
@Table(name = "modules")
public class Module {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "module_id")
private int moduleId;
@Column(name = "module_name")
private String moduleName;
@Column(name = "module_code")
private String moduleCode;
@Column(name = "moderator_lecturer")
private String moderatorLecturerId;
@Column(name = "secondary_lecturer")
private String secondaryLecturerId;
@OneToMany(mappedBy = "foreignModuleId", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Assessment> assessments;
public void addAssessment(Assessment assessment) {
assessments.add(assessment);
}
}
Code for Assignment
@Data
@NoArgsConstructor
@ToString
@Entity(name = "assessments")
@Table(name = "assessments")
public class Assessment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "assessment_id")
private int assessmentId;
@Enumerated(EnumType.STRING)
@Column(name = "assessment_type")
private AssessmentType assessmentType;
@Column(name = "assessment_weight")
private int assessmentWeight;
@Column(name = "assessment_weeks")
private String weeks;
@Column(name = "assessment_upload_date")
private LocalDate uploadDate;
@Column(name = "assessment_deadline_date")
private LocalDate deadlineDate;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "assessment_belongsTo_module", referencedColumnName = "module_id")
private Module foreignModuleId;
}
A Module can have many Assessments hence why I chose these annotations. I firstly extract those data from an excel file and combine them in a list (that is passed later on as an argument called "modules"). The list is of the form: Module(moduleId=0, moduleName=Programming Principles and Algorithms , moduleCode= CCS1110, moderatorLecturerId=Dr Stamatopoulou, secondaryLecturerId= Dr Efremidis, assessments=[Assessment(assessmentId=0, assessmentType=ASSESSED_LAB, assessmentWeight=35, weeks=00001000000000000, uploadDate=null, deadlineDate=null, foreignModuleId=null), Assessment(assessmentId=0, assessmentType=ASSESSED_LAB, assessmentWeight=65, weeks=00000000000000001, uploadDate=null, deadlineDate=null, foreignModuleId=null)]) Module(moduleId=0, moduleName=Programming Methodology and Design, moduleCode= CCS1115, moderatorLecturerId=Dr Stamatopoulou, secondaryLecturerId= Dr Efremidis, assessments=[Assessment(assessmentId=0, assessmentType=PROJECT, assessmentWeight=35, weeks=00000000000000100, uploadDate=null, deadlineDate=null, foreignModuleId=null), Assessment(assessmentId=0, assessmentType=ASSESSED_LAB, assessmentWeight=65, weeks=00000000000000001, uploadDate=null, deadlineDate=null, foreignModuleId=null)])
Then I upload the list on the database:
@NoArgsConstructor
@Data
public class AppDAOImpl implements AppDAO{
private SessionFactory factory;
public void upload(List<com.project.model.Module> modules) {
Session currentSession = factory.getCurrentSession();
try {
currentSession.beginTransaction();
for(Module module : modules) {
currentSession.save(module);
}
currentSession.getTransaction().commit();
}
finally {
currentSession.close();
factory.close();
}
}
}
When I execute Hibernate create queries of form: Hibernate: insert into modules (moderator_lecturer, module_code, module_name, secondary_lecturer) values (?, ?, ?, ?) Hibernate: insert into assessments (assessment_type, assessment_weight, assessment_deadline_date, assessment_belongsTo_module, assessment_upload_date, assessment_weeks) values (?, ?, ?, ?, ?, ?) Hibernate: insert into assessments (assessment_type, assessment_weight, assessment_deadline_date, assessment_belongsTo_module, assessment_upload_date, assessment_weeks) values (?, ?, ?, ?, ?, ?)
But in the database on the table for Assessments, the field assessment_belongsTo_module is null.
I have tried a lot of things and cannot fix the problem. I have also read similar threads and still nothing. Maybe there is a problem in the way I have created the fields on each table in the db (e.g. the foreign key)?
CodePudding user response:
- Do not use the name Module for a class, say MModule. It is confused with the java.lang.Module.
- Create JpaRepository MModuleRepository. Then in a controller, write simply something like
for(MModule module :modules){
moduleRepository.save(module);
}
CodePudding user response:
The problem that was causing this was related to the fact that I did not initialize the attribute "foreignModuleId" in the Assessment class. So when I extract the data from my excel at some point I have the lines:
assessment.setForeignModuleId(module); // I add the module in which the assessment belongs.
module.addAssessment(assessment); // I then add that assessment to the @OneToMany assessments List
I also fixed a stackOverFlow exception that was caused whenever I did operations like retrieving those data from the db, by including this in the Assessment class:
@ToString.Exclude
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "assessment_belongsTo_module", referencedColumnName = "module_id")
private Module foreignModuleId = new Module();
It is very important because Lombok's toString causes a recursive call which then results in the previously mentioned exception.