0

I have gone through multiple questions on this subject and here are a few that I have taken:Hibernate Access Exception. Wikibooks and Another ManyToMany extra column on Hibernate

Now, here are my questions:

  1. When doing the MayToOne mapping, do we need to follow the innerclass syntax on the OneToMany end? Say on the Wikibooks link, why does this link not use the innerclass reference on the OneToMany end? Observe that this uses the IdClass and not the Embeddable approach. Is that the difference? Any pointers on the Embeddable approach?

  2. When persisting, what is the exact sequence? First create the PK, then set the member variables in the outer class, then persist the mapping class instance?

  3. When zeroing in on the exact collection implementation, what are the bases of the choice? For example, I know that when we need to avoid duplicates, HashSet implementation is the option. Second, choosing an ArrayList vs a LinkedList is a choice that will be imposed by the additional domain requirements. What other criteria do I need to consider?

  4. When composing the Pk class, what I know is that the member variables are of the corresponding basic datatypes and not the Entity classes. For example, on this link, the PK class directly uses the Student and TeachingClass. And this has solution-answer that works for Hibernate. (Does this follow the Specification? Cannot infer after reading the JSR).

I am on EclipseLink 2.6. Can anybody help me with a single source of truth?

Thanks in advance

EDIT 1: Here is the example sourceCode with questions. And thanks for the comment. It actually made me ask more questions (mentioned inline).

@Entity
@Table(name="Student")
public class Student{
    @Id
    @Column(name="roll_number")
    private String rollNumber;

    private String firstName;
    private String lastName;

    //Which one is right? The immediate line or the one after?
    @OneToMany(mappedBy="student")
    @OneToMany(mappedBy="StudentSubjectPK.studentRollNumber")
    Collection<StudentSubjectMap> subjecttsForThisStudent;

    //Now, when I drill down to the actual Collection implementation to select, 
    //what are the criteria(twomentioned already. Anymore??)
public Collection<StudentSubjectMap> getSubjectsForThisStudent(){
      if(subjectsForThisStudent==null) !CollectionImplementation! subjectsForThisStudent = new !CollectionImplementation!();
      return subjectsForThisStudent;
}
    ....
}

@Entity
@Table(name="Subject")
public class Subject{
    @Id
    @Column(name="subject_name")
    private String subject;

    private String teacherName;
    private boolean isElective;
    private boolean isGraded;

    //Which one is right? The immediate line or the one after?
    @OneToMany(mappedBy="subject")
    @OneToMany(mappedBy="StudentSubjectPK.subjectName")
    Collection<StudentSubjectMap> studentsEnrolledInThisSubject
    ....
}

@Entity
public class StudentSubjectMap{

    @EmbeddedId
    private StudentSubjectMapPk pk;

    //Should the mapping be here or inside the StudentSubjectPK class?
    @ManyToOne(targetEntity="Student.class")
    //Is the PrimaryKeyJoinColumn annotation column in the next line redundant?
    @PrimaryKeyJoinColumn(name="roll_number",referencedColumn="roll_number")
    private Student student;

    @ManyToOne(targetEntity="Subject.class")
    @PrimaryKeyJoinColumn(name="subject_name",referencedColumn="subject_name")
    private Subject subject;

    //Do I need the setters and getters for the student and subject fields above?

    private float finalGrade;
    private float attendancePercentage;

    @Embeddable
    public static class StudentSubjectMapPK{
        @Column(name="roll_number")
        private String studentRollNumber;
        @Column(name="subject_name")
        private String subjectName;
    //Are getters and setters necessary here? Why?
    }
}
Venkata Rahul S
  • 304
  • 2
  • 10
  • You have 0 code example, and are not using correct terminology, so it's very hard to understand correct terminology. There is no outer or inner class in a OneToMany association. And you can't persist a table. – JB Nizet Jun 25 '17 at 06:59
  • Looking subjective opinions aren't great stackoverflow questions as they will get closed. Start with what you are trying to do: just adding an extra field to a ManyToMany mapping? Depending on the version of JPA you are using, there are quite a few examples that don't need to be overly complex, and JPA 2+ has derived IDs making it easier to avoid PrimaryKeyJoinColumn complexities. https://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/DerivedIdentifiers – Chris Jun 26 '17 at 14:44
  • I tried the approach with an inner PK class. The tables get created without error. But the persistence complains of not finding a parent key. The SQL with the binded values is not present in the logs, indicating that something is wrong in the sequence of persistence. That is where I started looking for more detailed information. Also, I thought using the PrimaryKeyJoinColumn is mandatory when the child entity has the referred column as a part of its primarykey. Has this requirement been done away with in 2.0? – Venkata Rahul S Jun 26 '17 at 15:41

1 Answers1

0

For some of the questions I had, here is the algorithm (essentially a sequence of JPA steps)

  1. Create an instance of the StudentSubjectMap class
  2. Fill all the fields in the instance
  3. Create an addSubjectToStudent class in which you create an instance of the StudentSubjectMapPK class.
  4. Assign the primary key values to the StudentSubjectMapPK instance
  5. Create OneToMany relations in both the Student class and the Subject class. Ensure that the cascade flag for the maps in either of these classes is set to CascadeType.PERSIST
  6. Create Getters and setters on all fields of the map (I did not verify whether their absence creates any exception)
  7. The join column must be mentioned as a PrimaryKeyJoinColumn. It need not be marked transient. However the column name of the physical table must be the same (value of the attribute columnName for the @PrimaryKeyJoinColumn annotation and the @Column(name="") on the StudentSubjectMapPK.subject and the StudentSubjectMap.subject members
  8. I tried quoting the OuterClass$InnerClass.memberVariableName structure but JPA complained that it was not able to find the mappedBy column in the targetEntity. Essentially, on the @OneToMany attribute in the Student class, the mappedBy attribute should have a value student and not StudentSubjectMapPK.student.

I will post the exact working code with the Student and Subject classes in a couple of days and also try and answer a couple of other questions that bogged me down in a subsequent comment.

Venkata Rahul S
  • 304
  • 2
  • 10