CBit
CBit

Reputation: 63

How to implement a Many-to-Many POJO structure?

I have many Students each one may have many Subjects and each Subject may have many Students as well. Now I want to implement a POJO structure:allStudentList and allSubjectList are just for query all elements of each type.
Is this structure a properly designed?
Are there better alternatives?
Here is my approach:

//THE Student class 
public class Student {

    //List with all students.
    private static ArrayList<Student> allStudentList = new ArrayList<>();
    //Student fields
    private String id;
    private String name;
    //The subjects of Student
    private ArrayList<Subject> subjectsList = new ArrayList<>();

    public Student(String id, String subject) {
        this.id = id;
        this.name = subject;
        allStudentList.add(this);
    }

    public boolean addSubject(Subject subject) {
        subject.getStudentList().add(this);
        return subjectsList.add(subject);
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    ArrayList<Subject> getSubjectsList() {
        return subjectsList;
    }

    public void setSubjectsList(ArrayList<Subject> subjectsList) {
        this.subjectsList = subjectsList;
    }

    public static Student[] getStudents() {
        return allStudentList.toArray(new Student[allStudentList.size()]);
    }

    @Override
    public String toString() {
        String s = "";
        for (Subject subject : subjectsList) {
            s += "\n  " + subject.getId() +" " +subject.getName();
        }
        return "Student{" + "id=" + id + ", name=" + name + ", subjectsList=" + s + '}';
    }
//THE Subject class 
public class Subject {

    //List with all students.
    private static ArrayList<Subject> allSubjectList = new ArrayList<>();
    private String id;
    private String name;
    private ArrayList<Student> studentList = new ArrayList<>();


    public Subject(String id, String name) {
        this.id = id;
        this.name = name;
        allSubjectList.add(this);

    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    ArrayList<Student> getStudentList() {
        return studentList;
    }
    public boolean addStudent(Student student) {
        student.getSubjectsList().add(this);
        return studentList.add(student);
    }

    public static Subject[] getStudents() {
        return  allSubjectList.toArray(new Subject [allSubjectList.size()]);
    }

    @Override
    public String toString() {
        String s ="";
        for (Student student : studentList) {
           s +="\n  "+student.getId() +" "+student.getName();
        }
        return "Subject{" + "id=" + id + ", nombre=" + name + ", studentList=" +s  + '}';
    }
//The test class:
public class TestMany2Many {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Student student0 = new Student("ST000", "Morty");
        Student student1 = new Student("ST001", "Rick");
        Subject subject0 = new Subject("SU000", "Physics");
        Subject subject1 = new Subject("SU001", "Math");
        student0.addSubject(subject0);
        student0.addSubject(subject1);
        student1.addSubject(subject0);
        Student[] st = Student.getStudents();
        Subject[] su = Subject.getStudents();
        for (Subject subject : su) {
            System.out.println("subject = " + subject);
        }
        for (Student student : st) {
            System.out.println("student = " + student);
        }


    }

}

Upvotes: 1

Views: 99

Answers (1)

Michael McKay
Michael McKay

Reputation: 670

It seems that your Student class also contains the list of all students. Yet you are instantiating it multiple times which will create multiple lists. It might help to think of it as a list and add an "s" to the end of the name "Students". Then instantiate it once and add the students to it. Something like

Subjects subjectList = new Subjects();
Students studentList = new Students();
subjectList.setStudents(studentList);

studentList.addStudent(student1ID, student1Name);
studentList.addStudent(student2ID, student2Name);
studentList.getStudent(studentID).addSubject(subjectID);

or, for that last line

studentList.addSubject(student1ID, subjectID);

The subjectID would have to exist in the equivalent Subjects class.

To keep track of the many-to-many relationships, its best to keep the data in one place if you can. Otherwise, you will have essentially two copies of the same list. So rather than keep the list of students within the subjects object, the subjects object can query the students object to get the list of students taking any particular subject.

public List<Student> getEnrolledStudents(String subjectID)
{
    Students studentList = getStudentList();
    return studentList.getStudentsEnrolledInSubject(subjectID);
}

Search for bi-directional lists as a possible solution.

The students object would be able to find directly the subjects any student is taking.

If you must put the data in both, you need to ensure its synced somehow so a delete of a student will delete the associated records in the subjects and vice versa. This gets messy quickly and is likely the point of the exercise.

Good luck!

Upvotes: 1

Related Questions