2016-08-09 1 views
0

J'essaie de créer une interface graphique pour afficher le contenu d'une base de données. J'utilise un JTable pour ça. Je veux un constructeur qui prend une liste de POJO et éventuellement des titres de colonnes. Je veux aussi que mon JTable puisse retourner le POJO sélectionné (par exemple quand je double-clique sur une ligne). Ai-je vraiment besoin de créer un modèle de table pour chaque POJO ou existe-t-il un meilleur moyen?comment créer un JTable avec POJOs avec un seul modèle de table

J'ai fait des recherches sur des sujets similaires, mais je n'ai trouvé aucune réponse qui utilise un modèle de table unique pour tous les POJO et aucun d'entre eux n'a une méthode qui renvoie un POJO.

Voici la description de mes tables de base de données et POJO:

tables de base de données:

  • étudiants (id, nom, prénom, date de naissance, grade_id, PhoneNumber)
  • grades (id, qualité)
  • auteurs (id, nom, prénom, nationality_id)
  • nationalités (id, nationalité)
  • livres (id, titre, author_id, student_id)

POJO:

  • année (int id, grade String)
  • Student (id int, prenom String, String nom, grade année)
  • Auteur (int id, prenom String, String nom, la nationalité de la nationalité)
  • nationalité (id int, nationalité String)
  • livre (id int, String titre, Autho r auteur, étudiant)
+0

Voulez-vous dire que vous voulez stocker différents POJO est dans un JTable? – Kayaman

+0

Non, mais je veux avoir par exemple un JTable générique pour chaque POJO donc je n'aurai pas besoin de créer une classe pour chacun d'entre eux. – ardayigit

+0

Pour être honnête, il vaut mieux écrire cinq classes qui étendent AbstractTableModel. Il suffit de remplacer quatre ou cinq méthodes dans chacune d'elles, et elles ne sont pas très longues. – VGR

Répondre

0

Voici un exemple de solution utilisant la réflexion et les annotations.

public class Worker { 

    @Updatable(false) 
    @Order(1) 
    @ColumnName("ID") 
    private int id; 

    @Updatable(true) 
    @Order(2) 
    @ColumnName("FIRST NAME") 
    private String firstName; 

    @Updatable(true) 
    @Order(3) 
    @ColumnName("LAST NAME") 
    private String lastName; 

    public Worker() { 
    } 

    public Worker(int id, String firstName, String lastName) { 
     this.id = id; 
     this.firstName = firstName; 
     this.lastName = lastName; 
    } 

    @Order(1) 
    public int getId() { 
     return id; 
    } 

    @Order(1) 
    public void setId(int id) { 
     this.id = id; 
    } 

    @Order(2) 
    public String getFirstName() { 
     return firstName; 
    } 

    @Order(2) 
    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 

    @Order(3) 
    public String getLastName() { 
     return lastName; 
    } 

    @Order(3) 
    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 
} 

-

@Retention(RetentionPolicy.RUNTIME) 
public @interface Order { 
    int value(); 
} 

-

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface ColumnName { 
    String value(); 
} 

-

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface Updatable { 
    boolean value(); 
} 

-

public class ComparatorReflection<T extends AccessibleObject & Member> implements Comparator<T>{ 

    @Override 
    public int compare(T o1, T o2) { 
     Order or1 = o1.getAnnotation(Order.class); 
     Order or2 = o2.getAnnotation(Order.class); 
     if (or1 != null && or2 != null && or1.value() - or2.value() != 0) { 
      return or1.value() - or2.value(); 
     } 
     return o1.getName().compareTo(o2.getName()); 
    } 

} 

-

public class ModelDAO extends AbstractTableModel { 

    private List<?> data; 

    public ModelDAO(List data) { 
     this.data = data; 
    } 

    @Override 
    public int getRowCount() { 
     return this.data.size(); 
    } 

    @Override 
    public int getColumnCount() { 
     return data.get(0).getClass().getDeclaredFields().length; 
    } 

    @Override 
    public Object getValueAt(int rowIndex, int columnIndex) { 
     try { 
      Method[] methods = data.get(rowIndex).getClass().getDeclaredMethods(); 
      Arrays.sort(methods, new ComparatorReflection<Method>()); 
      return methods[2*columnIndex].invoke(data.get(rowIndex), null); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    @Override 
    public Class<?> getColumnClass(int columnIndex) { 
     Field[] fields = data.get(0).getClass().getDeclaredFields(); 
     Arrays.sort(fields, new ComparatorReflection<Field>()); 
     return fields[columnIndex].getType(); 
    } 

    @Override 
    public String getColumnName(int column) { 
     Field[] fields = data.get(0).getClass().getDeclaredFields(); 
     Arrays.sort(fields, new ComparatorReflection<Field>()); 
     return fields[column].getAnnotation(ColumnName.class).value(); 
    } 

    @Override 
    public boolean isCellEditable(int rowIndex, int columnIndex) { 
     Field[] fields = data.get(rowIndex).getClass().getDeclaredFields(); 
     Arrays.sort(fields, new ComparatorReflection<Field>()); 
     return fields[columnIndex].getAnnotation(Updatable.class).value(); 
    } 
} 
2

Je suppose que quelqu'un a déjà créé un TableModel générique soutenu par des getters et setters bean. Essayez googling ReflectionTableModel ou BeanTableModel.

A défaut, il serait assez simple de rouler votre propre TableModel en utilisant la reflection api

+0

Merci beaucoup! L'idée d'utiliser la réflexion m'a beaucoup aidé! – ardayigit

2

Check out Row Table Model. Il fournit un support général pour les méthodes TableModel. Vous devrez implémenter quelques méthodes pour les champs spécifiques de votre POJO. Vous pouvez également utiliser Bean Table Model. Il utilise la réflexion sur votre POJO pour créer le TableModel. Il étend le RowTableModel.