title: Java DefaultTableModel gather data from multiple tables
body: <p>I have a data relation</p>
  
  <pre><code>Person-Attends-Course
  
  Person
  -------
  id: integer primary key
  name: string
  prename: string
  age: integer
  
  Course
  -------
  courseName: string primary key
  hours: integer
  
  Attends
  --------
  id: integer primary key references Person
  courseName: string primary key references Course
  </code></pre>
  
  <p>I need to have a data validation. After a long search on the Internet, I decided to implement it by extending DefaultTableModel. So far I created the code below and I have some questions:</p>
  
  <p><strong>Class Person</strong></p>
  
  <pre><code>class Person{
    private String name, prename,id;
    private int age;
  
    public Person(){}
  
    public String getName(){return this.name;}
    public String getPrename(){return this.prename;}
    public int getAge(){return this.age;}
    public String getId(){return this.id;}
  
    public void setName(String name){
      try{
          if(name.equals(""))
              JOptionPane.showMessageDialog(null, "Must insert name");
          else
              this.name = name;
      }
      catch(NullPointerException e){
          this.name = "";
      }
  }
  
    public void setPrename(String prename){
      if(prename.equals(""))
          JOptionPane.showMessageDialog(null, "Must insert prename");
      else
          this.prename = prename;
    }
  
    public void setAge(int age){
      try{
          if(age &lt;0 || age &gt;=100)
              JOptionPane.showMessageDialog(null, "Must insert valid age");
          else
              this.age = age;
      }
      catch(Exception e){
          this.age = 0;
      }
    }
  
    public void setId(String id){
      this.id = id;
    }
  }
  </code></pre>
  
  <p><strong>Class PersonTM</strong></p>
  
  <pre><code>class PersonTM extends DefaultTableModel{
    private final List&lt;Person&gt; personlist;
    private final String[] columnNames = {"id", "name", "prename","age"};
    private final Class[] columnClass = {String.class, String.class, String.class, Integer.class};
  
    public PersonTM(){this.personlist = new ArrayList&lt;&gt;();}
  
  @Override
  public Class&lt;?&gt; getColumnClass(int columnIndex){
      return columnClass[columnIndex];
  }
  
  @Override
  public String getColumnName(int column){
      return columnNames[column];
  }
  
  public String[] getColumnNames(){return this.columnNames;}
  
  @Override
  public int getColumnCount() {
      return columnNames.length;
  }
  
  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
      Person row = personlist.get(rowIndex);
      switch(columnIndex){
          case 0:
              return row.getId();
          case 1:
              return row.getName();
          case 2:
              return row.getPrename();
          case 3:
              return row.getAge();
          default:
              return null;
      }
  }
  
  @Override
  public void setValueAt(Object obj, int rowIndex, int columnIndex){
      Person row = personlist.get(rowIndex);
      switch(columnIndex){
          case 0:
              row.setId((String)obj);
              break;
          case 1:
              row.setName((String)obj);
              break;
          case 2:
              row.setPrename((String)obj);
              break;
          case 3:
              row.setAge((Integer)obj);
              break;
      }
    }
  }
  </code></pre>
  
  <p><strong>Class Course</strong></p>
  
  <pre><code>class Courses{
    private String courseName;
    private int hours;
  
    public Courses(){}
  
    public String getCourseName(){return this.courseName;}
    public int getHours() {return this.hours;}
  
    public void setCourseName(String courseName){
      if(courseName.equals(""))
          JOptionPane.showMessageDialog(null, "Must insert courseName");
      else
          this.courseName = courseName;
    }
  
    public void setHours(int hours){
      if(hours &lt;=0 || hours &gt;=50)
          JOptionPane.showMessageDialog(null, "Must insert valid hours");
      else
          this.hours = hours;
    }
  }
  </code></pre>
  
  <p><strong>Class CourseTM</strong></p>
  
  <pre><code>class CoursesTM extends DefaultTableModel{
    private final List&lt;Courses&gt; courseslist;
    private final String[] columnNames = {"course name","hours"};
    private final Class[] columnClass = {String.class,Integer.class};
  
    public CoursesTM(){this.courseslist = new ArrayList&lt;&gt;();}
  
    @Override
    public Class&lt;?&gt; getColumnClass(int columnIndex){
      return columnClass[columnIndex];
    }
  
    @Override
    public String getColumnName(int column){
      return columnNames[column];
    }
  
    public String[] getColumnNames(){return this.columnNames;}
  
    @Override
    public int getColumnCount() {
      return columnNames.length;
    }
  
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
      Courses row = courseslist.get(rowIndex);
      switch(columnIndex){
          case 0:
              return row.getCourseName();
          case 1:
              return row.getHours();
          default:
              return null;
      }
    }
  
    @Override
    public void setValueAt(Object obj, int rowIndex, int columnIndex){
      Courses row = courseslist.get(rowIndex);
      switch(columnIndex){
          case 0:
              row.setCourseName((String)obj);
              break;
          case 1:
              row.setHours((Integer)obj);
              break;
      }
    }
  }
  </code></pre>
  
  <p><strong>Class Attends</strong></p>
  
  <pre><code>//here I am a little confused
  
  class Attends{
    private final Person p;
    private final Course c;
  
    public Attends(Person p,Course c){
      this.p = p;
      this.c = c;
    }
  
    public Person getPerson(){return this.p;}
    public Course getCourse(){return this.c;}
  }
  </code></pre>
  
  <p><strong>Class AttendsTM</strong></p>
  
  <pre><code>class AttendsTM extends DefaultTableModel{
    private final PersonTM p;
    private final CoursesTM c;
    private final Map&lt;Person,List&lt;Course&gt;&gt; attendslist;
    private String[] columnNames;
    private final Class[] columnClass = {Person.class,Courses.class};
  
    public AttendsTM(Map&lt;Person,List&lt;Courses&gt;&gt; attendslist){
      this.attendslist = attendslist;
      this.p = new PersonTM();
      this.c = new CoursesTM();
    }
  
    public void setColumnNames(){
      for (int i = 0; i &lt; p.getColumnCount(); i++)
          columnNames[i] = p.getColumnName(i);
      for (int i = p.getColumnCount(); i &lt; c.getColumnCount(); i++)
          columnNames[i] = c.getColumnName(i);
    }
  }
  </code></pre>
  
  <p><strong>Class Viewer</strong></p>
  
  <pre><code>class viewer extends JFrame{
    private final JScrollPane scrollPane;
    private final AttendsTM model;
    private final JTable table;
  
    public viewer(){
      //collect data from db
      Person p1 = new Person();
      p1.setId("00001");
      p1.setName("John");
      p1.setPrename("Johnson");
      p1.setAge(30);
  
      Person p2 = new Person();
      p2.setId("00002");
      p2.setName("Jack");
      p2.setPrename("Jackson");
      p2.setAge(30);
  
      Courses c1 = new Courses();
      c1.setCourseName("History of art");
      c1.setHours(25);
  
      Courses c2 = new Courses();
      c2.setCourseName("Music");
      c2.setHours(15);
  
      List&lt;Courses&gt; coursesList = new ArrayList&lt;&gt;();
      coursesList.add(c1);
      coursesList.add(c2);
  
      Map&lt;Person,List&lt;Courses&gt;&gt; attendsMap = new LinkedHashMap&lt;&gt;();
      attendsMap.put(p1, coursesList);
      attendsMap.put(p2, coursesList);
  
      model = new AttendsTM(attendsMap);
      table = new JTable(model);
      //add a blank row at the end of Jtable
      model.addRow(new Object[model.getColumnCount()]);
      table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
      table.setCellSelectionEnabled(true);
      table.setColumnSelectionAllowed(false);
      table.setRowSelectionAllowed(true);
      //resize columns and use horizontal scroll bar to view data
      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
      //disable column dragging
      table.getTableHeader().setReorderingAllowed(false);
      scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
  }
  
    public void initializeUI(){
      add(scrollPane);
      setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      setSize(300,300);
      setVisible(true);
    }
  }
  </code></pre>
  
  <p><strong>Class TableModelExample</strong></p>
  
  <pre><code>public class TableModelExample {
    public static void main(String[] af){
      Runnable runnable = new Runnable(){
          @Override
          public void run() {
              new viewer().initializeUI();
          }
      };
      EventQueue.invokeLater(runnable);
    }
  }
  </code></pre>
  
  <p>So my questions are:</p>
  
  <ol>
  <li><p>How am I supposesd to appear a JTable with all columns from Person and Courses? Should I do this through Attends and how?</p></li>
  <li><p>How am I gathering data from Person and Course in AttendsTM? Am I doing it right?</p></li>
  </ol>
  
  <p>Any suggestion would be very wellcome. Thank you in advance.</p>