Sort Behavior of Table View in JavaFX - java

I intend to write an JFX-Application that displays data from database tables that contain up to 1M entries. Unfortunately, the standard API makes it difficult to support lazy loading. Reading the whole table is not an option (even though it performs well up to 100K entries).
Paging can be accomplished using a custom list class provided as model to the TableView. However, I also need to control the sorting behaviour of the TableView, since in my case, this would be left to the dbms.
An ugly solution is to make the columns unsortable, and add a Click-Event listener to the Column-Header. Apart from the coding, this also makes it impossible to display the current sort order in the usual way.
It is possible to listen to a change to columnSortOrder, but the standard sorting mechanism is still applied. What I would like to be able to do is display the standard ascending/descending icon in the column header while having full control of the sort behaviour of the TableView.
[Edit: In short, I want to implement lazy loading. I want a TableView that behaves exactly like normal TableView but does not sort the list when the user clicks on a column header. However, the sort order should still be displayed in the column header label.]
Is that somehow possible to achieve?
Many thanks for your answers in advance!

For reference:
This has been added to JavaFX-8. One can use TableView.setSortPolicy(...) to customize sorting.

Related

Nattable loose selection just after loading data

I'm using Nattable for almost all my tables in my application. Now an user reported an issue regarding the selection in Nattable.
When my application loads data the data is shown, when the user select an item just after the data loading, it will remove the selection. When the user wait a few seconds and does the selection again it holds.
Is this a known behavior of Nattable? For me it looks like the data is still loading when the first selection took place. The data load is 11K items with multiple cell labelers.
Without seeing the details it is hard to tell. Actually I wonder how something is rendered while the data is still loaded. But I suppose you have some interesting lazy loading mechanism to make the table accessible fast.
From my experience the behavior you describe happens because of a StructuralChangeEvent. Once the data is completely loaded such an event is fired to update all layers accordingly. A structural change is used to completely clear, that also implies the selection when using the default SelectionModel. The selection in that model is stored by row index. But as a structural change means this could have been changed, the selection is removed to avoid that something is shown selected that was not selected before.
Either you use an extended selection model like the RowSelectionModel or the PreserveSelectionModel or you double check when the StructuralChangeEvent is fired and if you can deal with that. But I suppose an alternative selection model should be more interesting with regards to your data loading mechanism.

Dynamically create search criteria and results using Java and sql database

I am currently working with a Java based web application (JSF) backed by Hibernate that has a variety of different search pages for different areas.
A search page contains a search fields section, which a user can customize the search fields that they are interested in. There are a range of different search field types that can be added (exact text, starts with, contains, multi-select list boxes, comma separated values, and many more). Search fields are not required to be filled in and are ignored, where as some other search fields require a different search field to have a value for this search field to work.
We currently use a custom search object per area that is specific to that area and has hard coded getter and setter search fields.
public interface Search {
SearchFieldType getSearchPropertyOne();
void setSearchPropertyOne(SearchFieldType searchPropertyOne);
AnotherSearchFieldType getSearchPropertyTwo();
void setSearchPropertyTwo(AnotherSearchFieldType searchPropertyTwo);
...
}
In this example, SearchFieldType and AnotherSearchFieldType represent different search types like a TextSearchField or a NumericSearchField which has a search type (Starts with, Contains, etc.) or (Greater Than, Equals, Less Than, etc.) respectively and a search value that they can enter or leave empty (to ignore the search field).
We use this search object to prepare a Criteria object
The search results section is a table that can also be customized by the user to contain only columns of the result object that they are interested in. Most columns can be ordered ascending or descending.
We back our results in a Result object per result which also hard codes the columns that can be displayed. This table is backed by hibernate annotations, but we are trying to use flat data instead of allowing other hibernate backed objects to minimize lazy joining data.
#Entity(table = "result_view")
public interface Result {
#Column(name = "result_field_one")
Long getResultFieldOne();
void setResultFieldOne(Long resultFieldOne);
#Column(name = "result_field_two")
String getResultFieldTwo();
void setResultFieldTwo(String resultFieldTwo);
...
}
The search page is backed by a view in our database which handles the joining to all the tables needed for every possible outcome. This view has gotten pretty massive and we take a huge performance hit for every search, even when a user only really wants to search on one field and display a few columns because we have upwards of thirty search field options and thirty different columns they can display and this is all backed by the one view.
On top of this, users request new search fields and columns all the time that they would like added to the page. We end up having to alter the search and result objects as well as the backing view to make these changes.
We are trying to look into this matter and find alternatives to this. One approach mentioned was to create different views that we dynamically choose based on the fields searched on or displayed in the results table. The different views might join different columns and we pick and choose which view we need for any given search.
I'm trying to think about the problem a different way. I think it might be better to not use a view and instead dynamically join tables we need based on what search fields and result columns are requested. I also feel that the search and result objects should not contain hard coded getters/setters and should instead be a collection of search fields and a collection (or map) of result columns. I have yet to completely flesh out my idea.
Would hibernate still be a valid solution to this issue? I wouldn't want to have to create a Result object used in a hibernate criteria since they result columns can be different. Both search fields and/or result columns might require joining tables.
Is there a framework I could use that might help solve the problem? I've been trying to look for something, and the closest thing I have found is SqlBuilder.
Has anyone else solved a similar problem dynamically?
I would prefer not to reinvent the wheel if a solution already exists.
I apologize that this ended up as a wall of text. This is my first stackoverflow post, and I wanted to make sure I thoroughly defined my problem.
Thanks in advance for your answers!
I don't fully understand the problem. But JPA Criteria API seems very flexible, which can be used to build query based on user-submitted filtering conditions.

Display a dynamically changing arrayList of objects with 4 string fields

I would assume that I should use a jTable. I tried this, but I can't for the life of me figure out how to append, insert and delete rows without a ton of overrides and complicated code. I find it hard to believe that Oracle doesn't have an easier way to do it.
Here's the premise. I have a few arrayLists. Each contain n amount of items and I want to be able to add these items' properties in the form of strings to the jtable and once i surpass a certain number of rows, I want the jTable to scroll.
So that's the reason I need to be able to add and remove rows.
As discussed in How to Use Tables: Creating a Table Model, DefaultTableModel has convenient methods to add, insert and remove rows. Simply update your model using any of these methods and your view will be updated accordingly.
Addendum: There's an example here.
Take a look at GlazedLists. It makes working with dynamically changing data and sowing it in JTables/JLists/JTrees, etc, very simple.

How to enable GUI behaviors for sorting a JTable when SQL does the sorting?

How do I enable JTable icons and behaviors for sorting table rows by a column, without letting it use a comparison predicate to do the sorting? That is to say, how do I tell the table headers to show the arrow for ascending/descending sort order in the column being used, and get it to call appropriate methods when sort order/column change?
I am trying to create an (editable, filterable, sortable) JTable backed by an SQL query or view. The rows may not fit in memory, and may not map cleanly to java objects, so I want to do all sorting/filtering within SQL. I have already written the code for changing a query to accommodate sorting by column, filtering by values, and visible columns.
To use this, I am planning to write a JTableModel based on a ResultSet with TYPE_SCROLL_SENSITIVE, and CONCUR_UPDATABLE, so changes to the DB get propagated to the ResultSet. I will periodically (several times a second) force a refresh of the visible JTable from the ResultSet, so changes to the database become visible to the user. User changes to the table will be passed to the updateable ResultSet after validation.
I've looked a little bit at how sorting is done normally, but most implementations seems to rely on the JTable creating a javax.swing.RowSorter with a Comparator predicate, or on maintaining a sorted list of rows that fires events when changed. So, my questions:
ORM frameworks are NOT an answer to this question, because the data do not map well to entity objects. Also, the DBMS I am using is H2.
EDIT: Sortable JTable libraries based on applying Comparators or sorting predicates to row objects are also unsuitable, unfortunately. I do not believe I will be able to hold all objects in memory in order to perform sorting. This problem prevents me from using the SwingX JXTables, GlazedLists, or similar libraries. I wish I could, but I can't. Period.
** I will be dealing with many thousand rows, potentially millions, with numerous columns. Yes, I really DO need to use SQL to do the sorting and filtering.**
Questions: (in descending importance)
How do I show indicators for which column is used to sort rows?
How do I get the JTable to fire appropriate events when the column headers are LEFT-clicked to change sort order?
Is there an easier way to force the JTable to update when the database changes?
Is there a library that would make all this considerably easier (connecting DB queries or views and JTables)?
Am I going to run into horrible, horrible problems when I design the system like this?
I have never used it myself but JIDE Data Grids provides a DatabaseTableModel that provides filtering and sorting support using SQL WHERE and ORDER BY.
In answer to 1 and 2, check out SwingX, which already includes a table class with built-in sorting (and filtering). You may be able to adapt this.
Am I going to run into horrible, horrible problems when I design the system like this?
From experience, yes. I worked on a project almost exactly the same as this, where someone had designed a JTable that supposedly 'magically' bound to a database table. This coupled display logic and database access together in one big horrible mess, which we replaced entirely with reflection-driven table models and separate record CRUD operations.
You say that ORM is not the answer...
If the format of the data doesn't change, then it's worth considering anyway. Your 'entity' classes need not represent real-world entities.
If (as I suspect) your entity format changes, it might be worth considering:
A flexible map-based Record class which stores records as key-value pairs;
Dynamically-built table models for your display logic, built by querying record keys, plugged into SwingX tables to get sort and filter for free;
A similarly-designed Repository class which encapsulates your database access separately from the table itself, responsible for loading and saving Records. This acts as an adapter between your updateable ResultSet and the view (although I'd check whether using a ResultSet this way is going to require an open database connection whilst data is visible...).
This separation into 'a table that displays and sorts records' and 'a repository that manages the data' means:
You can reuse the table for non-database-bound data;
You can display database-bound records in things other than tables;
You won't go mad trying to build and test the thing :)
You should be able to subclass javax.swing.RowSorter in order to create a row sorter that does the sorting in the database. From the API docs:
"RowSorter implementations typically don't have a one-to-one mapping with the underlying model, but they can. For example, if a database does the sorting, toggleSortOrder might call through to the database (on a background thread), and override the mapping methods to return the argument that is passed in."
http://docs.oracle.com/javase/6/docs/api/javax/swing/RowSorter.html
Leaving aside the database stuff there's a class called SortableTable that's a part of JIDE Grids. It displays the sorting with a little ^ or v in the table header, and supports sorting by more than 1 column (1v, 2v, etc.).

Efficient way to implement paged SQL result table in a Java desktop application

I need to build a table from SQL select result set. I want to add some paging functionality to the table because the result set can be very large. There was many discussions how to do the paging at the SQL level. But how to implement the paging at the GUI level? I have two ideas:
Do the paging in a web UI style - for example google search result paging;
"Excel style" - the scroll pane where the table resides expands as user scrolls down.
The second one looks nicer but complex to implement. When to do SQL select for a next chunk of data so that a user haven't wait for it. There should be some "read ahead" logic? What will happen if user scrolls quite quickly? What to do with rows that aren't visible any more to have constant memory usage?
Maybe there is already such a table component or good examples? Or maybe this good looking table functionality is unworthy of efforts to implement it?
You could do everything directly into your TableModel, there is no need to change something in the UI(well you migh show something in the UI - a status - but you don't need to change how JTable renders itself).
Just implement a JDBCTableModel which will have :
count the results and return this value as getRowCount().
have a background thread which brings page X(row X to row X + page_size) in memory
if the view(JTable) asks for a row which is not there(page not loaded) show a message "Loading data..." somewhere in left or rigth top corner and return empty cells.
Paging doesn't makes sense for a Swing application, it was invented before the current fancy AJAX libraries could implement table scrolling(see http://www.ext-livegrid.com/).
The people who have built paging tables for AJAX libraries have obviously thought about this a lot, so you may be able to learn from them if you can't find something already built. Since you are using Java, note that you can find paging tables written in Java for GWT. See these SO threads:
GWT paging widget
Best pageable table implementation in GWT
The ideas (and much of the code) for your implemenation may be found in the open source projects mentioned.

Categories