Home > ammentos, ddpole, development, java, mission, opensource > Showing query results within a JTable

Showing query results within a JTable

One of the most boring and error prone operations to do while writing desktop applications with database access is to show query results into a JTable. Here’s a simple EntityTableModel that can be used every time you need to need to do so, if you are using Ammentos.

import it.biobytes.ammentos.*;
import it.biobytes.ammentos.event.*;
import it.biobytes.ammentos.query.*;
import javax.swing.table.*;
import java.util.*;

public class EntityTableModel<T> extends AbstractTableModel
  implements PersistenceListener
{
  private Class<T> m_class;
  private List<T> m_entities;
  private Query m_query;
  private Field[] m_columns;
  private boolean m_editable;

  /** Creates a new instance of EntityTableModel */
  public EntityTableModel( Class<T> c, Query qry ) throws PersistenceException
  {
    m_query = qry;
    m_class = c;
    m_columns = Ammentos.getMetadata( c ).getVisibleFields();
    refresh();
  }

  /**
   * Creates a new instance of EntityTableModel based on a list of entities
   */
  public EntityTableModel( Class<T> c, List<T> entities ) throws PersistenceException
  {
    m_class = c;
    m_columns = Ammentos.getMetadata( c ).getVisibleFields();
    m_entities = entities;
  }

  /**
   * Returns the value for the cell at <code>columnIndex</code> and
   * <code>rowIndex</code>.
   *
   * @param    rowIndex    the row whose value is to be queried
   * @param    columnIndex     the column whose value is to be queried
   * @return    the value Object at the specified cell
   */
  public Object getValueAt(int rowIndex, int columnIndex)
  {
    Field f = m_columns[ columnIndex ];
    Object obj = m_entities.get( rowIndex );
    return f.get( obj );
  }

  /**
   * Returns the number of rows in the model. A
   * <code>JTable</code> uses this method to determine how many rows it
   * should display.  This method should be quick, as it
   * is called frequently during rendering.
   *
   * @return the number of rows in the model
   * @see #getColumnCount
   */
  public int getRowCount()
  {
    return m_entities.size();
  }

  /**
   * Returns the number of columns in the model. A
   * <code>JTable</code> uses this method to determine how many columns it
   * should create and display by default.
   *
   * @return the number of columns in the model
   * @see #getRowCount
   */
  public int getColumnCount()
  {
    return m_columns.length;
  }

  public void refresh() throws PersistenceException
  {
    if ( m_query != null )
    {
      m_entities = Ammentos.loadUpdatable( m_class, m_query );
    }
    fireTableDataChanged();
  }

  /**
   *  Returns a default name for the column using spreadsheet conventions:
   *  A, B, C, ... Z, AA, AB, etc.  If <code>column</code> cannot be found,
   *  returns an empty string.
   *
   * @param column  the column being queried
   * @return a string containing the default name of <code>column</code>
   */
  public String getColumnName(int column)
  {
    return m_columns[ column ].getDescription();
  }

  public Field getColumnField( int column )
  {
    return m_columns[ column ];
  }

  public void objectSaved( PersistenceEvent e )
  {
    System.out.println( "Object saved!" );
    if ( ( e.getObject() != null ) && m_class.isInstance( e.getObject() ) )
    try { refresh(); }catch( Exception ex )
    {
      System.out.println( "Exception: " + ex.getMessage() );
      ex.printStackTrace();
    }
  }

  public void objectDeleted( PersistenceEvent e )
  {
    System.out.println( "Object deleted!" );
    if ( ( e.getObject() != null ) && m_class.isInstance( e.getObject() ) )
    try { refresh(); }catch( Exception ex )
    {
      System.out.println( "Exception: " + ex.getMessage() );
      ex.printStackTrace();
    }
  }

  public void setColumnVisible( String fieldName, boolean visible )
  {
    try
    {
      Field field = Ammentos.getMetadata( m_class ).getField( fieldName );
      if ( field != null )
      {
        field.setVisible( visible );
      }
    }
    catch( PersistenceException e )
    {
    }
  }

  public T getEntityAt( int row )
  {
    return m_entities.get( row );
  }

  public void setQuery( Query qry )
  {
    m_query = qry;
  }

  public Query getQuery()
  {
    return m_query;
  }  

  public boolean isCellEditable(int rowIndex, int columnIndex)
  {
    if ( !m_editable ) return false;
    Field field = getColumnField( columnIndex );
    return ( field.getType() != FieldTypeEnum.ENTITY.getFieldType() );
  }

  public void setValueAt(Object aValue, int rowIndex, int columnIndex)
  {
    Field field = getColumnField( columnIndex );
    T obj = getEntityAt( rowIndex );

    try
    {
      field.set( obj, /*field.parseValue( ( String )aValue )*/ aValue );
      //Ammentos.save( obj );
    }
    catch( Exception e )
    {
      System.out.println( "Error saving entity: " + e.getMessage() );
      e.printStackTrace();
    }
  }

  public boolean isEditable() {
    return m_editable;
  }

  public void setEditable(boolean editable) {
    m_editable = editable;
  }

}

Now loading and displaying queries is straight:

myTable.setModel(new EntityTableModel<MyPersistentEntity>);

Notice that EntityTableModel implements PersistenceListener. That means that you can register it:

Ammentos.addPersistenceListener(myEntityTableModel(MyPersistentEntity.class, new Query()));

This way, any time one Entity of the type contained in the JTable is saved or deleted, your JTable will automatically refresh it content! Do you think it’s nice?

Next time we will talk about ordering issues.

  1. NathyWhetly
    February 10, 2009 at 4:10 am

    Hi, cool site, good writing 😉

  2. August 23, 2009 at 11:23 am

    nhZqj1 ytlwkwbnpdxg, [url=http://dgfdmaiaowfp.com/]dgfdmaiaowfp[/url], [link=http://fydymxcnqakt.com/]fydymxcnqakt[/link], http://mgkomlmhucis.com/

  3. January 11, 2013 at 8:30 am

    Hello sir,how can I display a single entity gotten from the getSingleresult(); to show up in a Jtable? Thanks a lot

  1. No trackbacks yet.

Leave a comment