Reputation: 167
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
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
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
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