ardayigit
ardayigit

Reputation: 167

how to create a JTable with POJOs with a single table model

I’m trying to create a GUI to display the content of a database. I’m using a JTable for that. I want a constructor that takes a list of POJOs and eventually column titles. I want also my JTable to be able to return the selected POJO (for example when I doubleclick on a row). Do I really need to create a table model for each POJO or is there a better way?

I’ve made some searchs on similar topics, but I didn’t find any answer that uses a single table model for all POJOs and none of them has a method that returns a POJO.

Here is the description of my database tables and POJOs:

Database tables:

POJOs:

Upvotes: 0

Views: 1410

Answers (3)

ardayigit
ardayigit

Reputation: 167

Here is as example of solution using reflection and 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(); 
    }
}

Upvotes: 1

camickr
camickr

Reputation: 324128

Check out Row Table Model. It provide general support for TableModel methods. You will need to implement a couple of methods for the specific fields of your POJO.

Or you can use the Bean Table Model. It uses reflection on your POJO to create the TableModel. It extends the RowTableModel.

Upvotes: 2

lance-java
lance-java

Reputation: 27994

I'm guessing someone has already created a generic TableModel backed by bean getters and setters. Try googling ReflectionTableModel or BeanTableModel.

Failing that it would be quite simple to roll your own TableModel using the reflection api

Upvotes: 2

Related Questions