JavaFx TableView CRUD for large database tables - java

I'm looking for sample apps or documentation for displaying a large table in JavaFx TableView , without loading the entire table into memory beforehand. CRUD capabilities would be nice, too, though I can write this myself if necessary.
All the examples I have found pre-load data into a an observable list (in memory, I assume), which I can't do for, say, 5 million records!
I have worked in Java Swing with table models that get their data from JDBC ResultSets, is there something similar I can do for JavaFx TableView? I also added my own sort and column layout persistence in Swing, and am looking to do something similar in JavaFx.
This may be a "beginner" question, or it's possible that I missed something simple while scouring through the JavaFx info.

Each TableView must has a model class. you can easily set your model class to table view.
For example you have class Student with (id,name,avg)
define an ObservableList of Student just like
ObservableList<Student> stdList = FXCollections.observableArrayList();
then set the list to the table view by
tableView.setDate(stdList);
and Now you can do anything you imagine (CRUD) on the list.

Related

In populating an ObservableList, do I have to load ALL the records from my database?

So I'm porting my Swing Java database application to Java FX (still a beginner here, I recently just learned the basics of FXML and the MVC pattern, so please bear with me).
I intend to load the data from my existing database to the "students" ObservableList so I can show it on a TableView, but on my original Swing code, I have a search TextField, and when the user clicks on a button or presses Enter, the program:
Executes an SQLite command that searches for specific records, and retrieves the RecordSet.
Creates a DefaultTableModel based on the RecordSet contents
And throws that TableModel to the JTable.
However, Java FX is a completely different beast (or at least it seems so to me--don't get me wrong, I love Java FX :D ) so I'm not sure what to do.
So, my question is, do I have to load ALL the students in the database, then use some Java code to filter out students that don't fit the search criteria (and display all students when the search text is blank), or do I still use SQLite in filtering and retrieving records (which means I need to clear the list then add students every time a search is performed, and maybe it will also mess up with the bindings? Maybe there will be a speed penalty on this method also? Besides that, it will also reset the currently selected record because I clear the list--basically, bad UI design and will negatively impact the usability)
Depending on the right approach, there is also a follow-up question (sorry, I really can't find the answer to these even after Googling):
If I get ALL students from database and implement a search feature in Java, won't it use up more RAM than it should, because I am storing ALL the database data in RAM, instead of just the ones searched for? I mean, sure, even my lowly laptop has 4GB RAM, but the feeling of using more memory than I should makes me feel somewhat guilty LOL
If I choose to just update the contents of the ObservableList every time a new search has been performed, will it mess up with the bindings? Do I have to set up bindings again? How do I clear the contents of the ObservableList before adding the new contents?
I also have the idea of just setting the selected table item to the first record that matches the search string but I think it will be difficult to use, since only one record can be highlighted per search. Even if we highlight multiple rows, it'd be difficult to browse all selected items.
Please give me the proper way, not the "easy" way. This is my first time implementing a pattern (MVC or am I actually doing MVP, I don't know) and I realized how unmaintainable and ugly my previous programs are because I used my own style. This is a relatively big project that I need to support and improve for several years so having clean code and doing stuff the right way should help in maintaining the functionality of this program.
Thank you very much in advance for your help, and I hope I don't come off as a "dumb person who can't even Google" in asking these questions. Please bear with me here.
Basic design tradeoffs
You can, of course, do this either of the ways you describe. The basic tradeoffs are:
If you load everything from the database, and filter the table in Java, you use more memory (though not as much as you might think, as explained below)
If you filter from the database and reload every time the user changes the filter, there will be a bigger latency (delay) in displaying the data, as a new query will be executed on the database, with (usually) network communication between the database and the application being the biggest bottleneck (though there are others).
Database access and concurrency
In general, you should perform database queries on a background thread (see Using threads to make database requests); if you are frequently making database queries (i.e. filtering via the database), this gets complex and involves frequently disabling controls in the UI while a background task is running.
TableView design and memory management
The JavaFX TableView is a virtualized control. This means that the visual components (cells) are created only for visible elements (plus, perhaps, a small amount of caching). These cells are then reused as the user scrolls around, displaying different "items" as required. The visual components are typically quite memory-consumptive (they have hundreds of properties - colors, font properties, dimensions, layout properties, etc etc - most of which have CSS representations), so limiting the number created saves a lot of memory, and the memory consumption of the visible part of the table view is essentially constant, no matter how many items are in the table's backing list.
General memory consumption computations
The items observable list that forms the table's backing list contains only the data: it is not hard to ballpark-estimate the amount of memory consumed by a list of a given size. Strings use 2 bytes per character, plus a small fixed overhead, doubles use 8 bytes, ints use 4 bytes, etc. If you wrap the fields in JavaFX properties (which is recommended), there will be a few bytes overhead for each; each object has an overhead of ~16 bytes, and references themselves typically use up to 8 bytes. So a typical Student object that stores a few string fields will usually consume of the order of a few hundred bytes in memory. (Of course, if each has an image associated with it, for example, it could be a lot more.) Thus if you load, say 100,000 students from a database, you would use up of the order of 10-100MB of RAM, which is pretty manageable on most personal computer systems.
Rough general guidelines
So normally, for the kind of application you describe, I would recommend loading what's in your database and filtering it in memory. In my usual field of work (genomics), where we sometimes need 10s or 100s of millions of entities, this can't be done. (If your database contains, say, all registered students in public schools in the USA, you may run into similar issues.)
As a general rule of thumb, though, for a "normal" object (i.e. one that doesn't have large data objects such as images associated with it), your table size will be prohibitively large for the user to comfortably manage (even with filtering) before you seriously stretch the memory capacity of the user's machine.
Filtering a table in Java (all objects in memory)
Filtering in code is pretty straightforward. In brief, you load everything into an ObservableList, and wrap the ObservableList in a FilteredList. A FilteredList wraps a source list and a Predicate, which returns true is an item should pass the filter (be included) or false if it is excluded.
So the code snippets you would use might look like:
ObservableList<Student> allStudents = loadStudentsFromDatabase();
FilteredList<Student> filteredStudents = new FilteredList<>(allStudents);
studentTable.setItems(filteredStudents);
And then you can modify the predicate based on a text field with code like:
filterTextField.textProperty().addListener((obs, oldText, newText) -> {
if (newText.isEmpty()) {
// no filtering:
filteredStudents.setPredicate(student -> true);
} else {
filteredStudents.setPredicate(student ->
// whatever logic you need:
student.getFirstName().contains(newText) || student.getLastName().contains(newText));
}
});
This tutorial has a more thorough treatment of filtering (and sorting) tables.
Comments on implementing "filtering via queries"
If you don't want to load everything from the database, then you skip the filtered list entirely. Querying the database will almost certainly not work fast enough to filter (using a new database query) as the user types, so you would need an "Update" button (or action listener on the text field) which recomputed the new filtered data. You would probably need to do this in a background thread too. You would not need to set new cellValueFactorys (or cellFactorys) on the table's columns, or reload the columns; you would just call studentTable.setItems(newListOfStudents); when the database query finished.

How made dataTable in rowExpansion section in another dataTable with common model

I have complex dataTable witch paganation, dynamic columns, lazyloading, sotring , filtering, multi selection. Now I have to use this table and model in another context. All rows in table now must have "subtable" with the same colums, multiselection woring in outer table context without pagination, sorting, fitering. I schould use dataTable(row Expansion(inner dataTable))?
The actual question is not clear. And I must warn you about heavy table structures in primefaces, they tend to not function as intended. It's generally a good approach to simplify the structure (on JSF/PF elements level).
For example, instead of using tables inside tables you could use JSTL for the outer iteration. There are also SubTable (http://www.primefaces.org/showcase/ui/data/datatable/subTable.xhtml) and TreeTable (http://www.primefaces.org/showcase/ui/data/treetable/basic.xhtml) elements available. You could also adapt DataGrid or DataList elements for your purposes...

JTable data persistence advice

I am seeking advice in persisting my JTable data in an elegant manner. So far my research has indicated I can iterate through the many columns and rows and extract the data for saving (seems convoluted) or that I can save the table and related data as an Object in an Object file.
I would love to hear some advice from those more versed in this area as I am quite new to JTables and their workings. Are there many other solutions available that may be a better choice?
It depends on what you want to do with the persisted data. If you only want to persist it so that you can display it again later, look at serializing (Java Serializable or Java Externalizable) it to a data-stream that you put somewhere. Later you can read it back (deserialize) and display it again.
If you want to put it in a database where the information is useable for other purposes, then you probably want to implement some object which models your data to keep it clear and simple. Then you can present this in a Swing Jtable by adapting your model to a table model. This still means you need to write the adaptation/transformation logic but it shouldn't be onerous and you get the most usable result. The TableModel is simply a way of looking at your data that a JTable is able to understand. Look at Adaptor patterns to get one idea about the mapping.
Hope that helps.

Visualise relationships between CSV file and custom datastructure

I'm working on an application where I need to map fields in one CSV file to fields in a data structure defined by the application. I'd thought of different ways of doing this, but the method that I like the best is the one where I would have a graphical user interface where the user could just drag columns from an entity representing the CSV file to an entity representing the internal data structure. This way, it would be all drag and drop.
Does anyone know of a Java library I can use to achieve something like this?
UPDATE
I'd like to point out that I am looking for components which can help me with the visualisation. I do know that I can't find any ready made components which will take care of the entire mapping and data transformations for me. It's a matter of trying to track down swing components which can help me visualise relationships between entities and their fields (CSV file being an entity and internal data structure being another entity).
Consider using JList or JTable containing a checkbox column, either of which would leverage the existing DnD support for those components. A common interface uses two parallel lists flanking a column of controls. For example,
(source: java2s.com)

Java: Retrieving data from Database and load in JTable

I know how to retrieve data (just text in a table) from a database in Java and how to show it in the console. But I want to load it in a JTable.
Is there a good (modern) way (tutorial), without using Vectors?
Check out this tutorial: How to Use Tables
Seems your question is similar with these two questions:
How to fill data in a JTable with database?
Displaying data from database in JTable
Check out GlazedLists it comes with ready made TableModels that are based on modern collection interfaces.
http://www.glazedlists.com/
If you don't want to use an extra library. You can easily implement your own javax.swing.table.TableModel. I like to implement TableModel and java.util.List so I'm working with just a simple List, and hooking up any List easily.

Categories

Resources