Как получить данные JTable для обновления из ResultSet
Я работаю над программой адресной книги (просто чтобы попрактиковаться в кодировании), и я наткнулся на небольшую загадку. Таблица изначально заполняется при запуске из набора результатов, который получается с помощью метода другого класса. Это метод, используемый для заполнения списка:
protected void populateContactList( int query )
{
try
{
ResultSetMetaData metaData;
contactListRS = contact.contactListQuery( query );
metaData = contactListRS.getMetaData();
int colCount = metaData.getColumnCount();
String[] colTitlesArray = new String[] {
"ContactID", "Last Name", "First Name", "Company" };
Vector< String > colTitles = new Vector< String >();
colTitles.addAll( Arrays.asList( colTitlesArray ) );
Vector< Vector< Object> > data = new Vector< Vector< Object > >();
while ( contactListRS.next() )
{
Vector< Object > rowVector = new Vector< Object >();
for ( int i = 1; i <= colCount; i++ )
{
rowVector.add( contactListRS.getObject( i ) );
}
data.add( rowVector );
}
contactTableModel.setDataVector( data, colTitles);
// hides col 0 (contactID) from display on jtable
// but retains data for retrieval from table model
contactDisplayTable.getColumnModel().getColumn( 0 )
.setIdentifier( "contactID" );
TableColumn contactIDCol = contactDisplayTable.
getColumn( "contactID" );
contactDisplayTable.getColumnModel().removeColumn( contactIDCol );
}
catch ( SQLException e )
{
System.err.println( e );
}
}
Этот метод работает правильно для начального отображения данных из ResultSet с начальным запросом при запуске, но после изменения ResultSet в результате поиска пользователя таблица очищается, а новые данные не отображаются. Этот метод используется для начального запроса:
protected ResultSet contactListQuery( int query )
{
try
{
if ( query == 0 )
{
listQuery = conn.prepareStatement( queryArr[ query ] );
queryRS = listQuery.executeQuery();
}
else if ( query == 1 )
{
queryRS = searchContacts();
queryRS.last();
}
}
catch (SQLException e)
{
e.printStackTrace();
}
return queryRS;
}
Этому методу передается int, указывающий вызывающий метод. Если это начальный запрос (или другой вызов, предназначенный для отображения полного списка контактов), ему передается 0, что приводит к полному списку запросов. В противном случае ему передается 1, и в этом случае он вызывает метод searchContacts. В любом случае он возвращает ResultSet, содержащий те же 4 элемента из БД, в метод populateContactList. Ниже приведен метод поиска контактов:
public ResultSet searchContacts() throws SQLException
{
String searchLN = addressBook.getSearchLN();
String searchFN = addressBook.getSearchFN();
String searchCO = addressBook.getSearchCO();
boolean checkLN = searchLN.isEmpty();
boolean checkFN = searchFN.isEmpty();
boolean checkCO = searchCO.isEmpty();
int rsLength;
try
{
if ( ( checkLN ) && ( checkFN ) && ( checkCO ) )
{
JOptionPane.showMessageDialog( addressBook.addressBookMainJF,
"All fields are empty.\nPlease enter search parameters.", "Empty Search", JOptionPane.ERROR_MESSAGE );
return contactListQuery( 0 );
}
else if ( !( checkLN ) && ( checkFN ) && ( checkCO ) )
{
listQuery = conn.prepareStatement( queryArr[ 1 ] );
listQuery.setString( 1, searchLN );
}
else if ( ( checkLN ) && !( checkFN ) && ( checkCO ) )
{
listQuery = conn.prepareStatement( queryArr[ 2 ] );
listQuery.setString( 1, searchFN );
}
else if ( !( checkLN ) && !( checkFN ) && ( checkCO ) )
{
listQuery = conn.prepareStatement( queryArr[ 3 ] );
listQuery.setString( 1, searchLN );
listQuery.setString( 2, searchFN );
}
else if ( ( checkLN ) && ( checkFN ) && !( checkCO ) )
{
listQuery = conn.prepareStatement( queryArr[ 4 ] );
listQuery.setString( 1, searchCO );
}
else if ( ( checkLN ) && !( checkFN ) && !( checkCO ) )
{
listQuery = conn.prepareStatement( queryArr[ 5 ] );
listQuery.setString( 1, searchFN );
listQuery.setString( 2, searchCO );
}
else if ( !( checkLN ) && ( checkFN ) && !( checkCO ) )
{
listQuery = conn.prepareStatement( queryArr[ 6 ] );
listQuery.setString( 1, searchLN );
listQuery.setString( 2, searchCO );
}
else if ( !( checkLN ) && !( checkFN ) && !( checkCO ) )
{
listQuery = conn.prepareStatement( queryArr[ 7 ] );
listQuery.setString( 1, searchLN );
listQuery.setString( 2, searchFN );
listQuery.setString( 3, searchCO );
}
else
{
JOptionPane.showMessageDialog( addressBook.addressBookMainJF,
"Error processing search.\nPlease try again.", "Search Error", JOptionPane.ERROR_MESSAGE );
}
searchRS = listQuery.executeQuery();
searchRS.last();
rsLength = searchRS.getRow();
if ( rsLength < 1 )
{
return contactListQuery( 0 );
}
}
catch ( SQLException e )
{
e.printStackTrace();
}
searchRS.first();
return searchRS;
}
Очевидно, этот метод определяет, какие поля содержат пользовательский ввод, заполняет пользовательский ввод в соответствующий запрос, выполняет запрос и возвращает ResultSet. В любом случае, в ResultSet включены те же 4 элемента, что и для запроса полного списка.
Я проверил, чтобы увидеть, содержит ли результирующий набор данные после запроса, и он всегда делает, если есть какие-либо совпадения. Я также проверил, чтобы ResultSet возвращался методу populateContactList, и это так. Я считаю, что проблема где-то в методе populateContactList, я просто не могу понять, в чем проблема. У меня есть одна теория, что, возможно, потребуется обновить таблицу с помощью contactTableModel.fireTableDataChanged(); которую я пробовал в различных точках метода populateContactList, но это не решило проблему. Возможно, есть что-то подобное, что сработает, о чем я не думал?
Я понимаю, что это многое нужно просмотреть, я просто хотел, чтобы каждый, кто хочет помочь, мог видеть весь задействованный код, а не догадываться, как он может выглядеть. Любая помощь, оказанная с этим, будет принята с благодарностью. Я заранее прошу прощения, если что-то из этого кажется дилетантским или если оно слишком затянуто. Просто пытаюсь быть тщательным и точным в этом вопросе.
1 ответ
Я понял это самостоятельно. Очевидно, последний бит перед блоком catch в методе searchContacts отбрасывал вещи. Я удалил этот бит:
searchRS.last();
rsLength = searchRS.getRow();
if ( rsLength < 1 )
{
return contactListQuery( 0 );
}
и теперь он работает правильно. Просто нужно найти другой способ обработки пустых результатов поиска RS, но я, вероятно, смогу решить эту проблему с помощью JOptionPane, чтобы уведомить пользователя о том, что результаты не найдены.