Java JTable binding via JPA - java

I have tried to search for proper answers, but nothing helped me so far. I am quite new to java GUI programming, actually, to java itself.. I have however managers to understand JPA, how to retrieve, insert and delete using JPA.
Now I want the data in my database to be shown in a JTable.
I currently have the following mySQL table(which i want to show in a JTable
games
Id PK int
Title
Publisher
Genre
ReleaseDate
As far as coding concerns, I have succesfully retrieved the data contained in the table using the following:
public List<Game> getGames(){
List<Game> games;
try{
TypedQuery<Game> selectGamesQuery = entityManager.createQuery("SELECT g FROM Game g", Game.class);
games = selectGamesQuery.getResultList();
} catch(Exception e) {
System.out.println(e);
}
return games;
}
This succesfully returns a list of games whom I can iterate trough.
Then, in my view I have the following
JScrollPane scrollPane = new JScrollPane();
contentPane.add(scrollPane, BorderLayout.CENTER);
tblGames = new JTable(new tblGamesModel());
tblGames.setShowVerticalLines(true);
tblGames.setShowHorizontalLines(true);
tblGames.setFillsViewportHeight(true);
scrollPane.setViewportView(tblGames);
Which ofcourse leads us to the table model,which is where I'm stuck.
public class tblGamesModel extends AbstractTableModel {
private GameRepository gameRepository;
private List<Game> games;
/**
*
*/
public tblGamesModel(){
gameRepository = new GameRepository();
games = gameRepository.getGames();
}
private static final long serialVersionUID = 1L;
#Override
public int getColumnCount() {
// TODO Auto-generated method stub
return 0;
}
#Override
public int getRowCount() {
// TODO Auto-generated method stub
return games.size();
}
#Override
public Object getValueAt(int arg0, int arg1) {
// TODO Auto-generated method stub
return null;
}
}
I know this is alot of code for a simple post, but I really don't know how else to show the current problem. Any good links would help, or advise on its own.
Thanks for taking the time to read the code and possibly help me out.
Remember, I am just a student programming, so I have a lot to learn about conventions etc aswell. So pointers are also welcome, as I am eager to learn from more experienced developers.

The simplest option is something like this:
#Override
public int getColumnCount() {
return 5;
}
...
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Game game = games.get(rowIndex);
switch (columnIndex) {
case 0:
return game.getId();
case 1:
return game.getTitle();
case 2:
return game.getPublisher();
case 3:
return game.getGenre();
case 4:
return game.getReleaseDate();
}
return null;
}
That can be prone to maintenance problems due to all the magic numbers - a solution would be to use an enumeration for the columns:
enum GameTableColumn {
ID, TITLE, PUBLISHER, GENRE, RELEASE_DATE;
}
And then get the enumeration instance for a column using GameTableColumn.values()[columnIndex].
A few style notes - tblGamesModel is a non-standard name for a Java class, class names always start with an upper case letter. A more Java name would be GamesTableModel. Hungarian notation prefixes (such as "tbl") are generally discouraged.
Also having a database fetch in a constructor is generally a bad idea. In a Swing application you want all fetches to be explicit so you can ensure they do not block the UI. Rather than getGames() I would suggest retrieveGames(). It may be best to construct the GamesRepository outside the table model and pass it in to the constructor. You could then perform the JPA query first in a different thread. This would prevent the UI thread from freezing while the database access is in progress.

Pass loaded list to the model via constructor parameter or setter method. Then you can use following model structure:
public class TblGamesModel extends AbstractTableModel {
private static final String[] COLUMNS = {"id", "title",
...........
private static final int COL_ID = 0;
private static final int COL_TITLE = 1;
private List<Game> list; //list that is injected via constructor or setter method
public int getRowCount() {
return list.size();
}
public int getColumnCount() {
return COLUMNS.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
Game game = list.get(rowIndex);
switch (columnIndex) {
case COL_ID:
return game.getId();
........
}
}
public String getColumnName(int column) {
return COLUMNS[column];
}

Related

How to convert type Class<?> to int

I am trying to convert this data type to call out the method later on in another class to switch around layouts being made in other methods such as recipe1Layout(); by the index number of a class that has a field of a Class<?> Array.
Here is the getItem() method
public int getItem(){
int index = 0;
for(int i = 0; i < 100; i++) {
try{
index = recipe.getClass().getField("Classes").get(i);
} catch(Exception e){
}
}
return index;
}
Here is the Recipe Class
public class Recipes {
public Class<?>[] Classes = {
ChileConLecheActivity.class,
ArrozActivity.class,
EnchiladasActivity.class,
SopaActivity.class
};
}
The type of Class needs to be here because I have other uses for the recipe class.
For example, making a new instance of all classes to later on be called out to make adjustments to all the classes with one method.
The only thing I can think of is converting the type Class to an int so I can call out the method returning the index number I can do something like recipe.
index = Integer.parseInt(Classes[I].getName().toString());
But this is where I am asking for help I have no idea how to get rid of the error in the logcat.
The error shows up as
IndexOutOfArrayException
First off, stop using reflection. Use a public static array.
public class Recipes {
public static final Class<?>[] CLASSES = {
ChileConLecheActivity.class,
ArrozActivity.class,
EnchiladasActivity.class,
SopaActivity.class
};
}
Then, assuming your recipe instance has a field of what Class<Activity> it is assigned to, then, you would want something like this
public int getItem(){
int index = -1;
for(int i = 0 ; i < Recipe.CLASSES.length; i++) {
if (recipe.getActivityClass().equals(Recipe.CLASSES[i]) {
index = i;
break;
}
}
return index;
}
However, under certain situations, coupling one Activity class to any single Recipe instance, probably isn't a good idea.
I am trying to convert this data type to call out the method later on in another class to switch around layouts being made in other methods
if I understand what you are trying to do, you want a some mapping structure to some classes which have some pre-defined layouts.
Generally, this can be done with enums and OOP patterns
Have some base classes like this
public interface Layoutable {
int getLayout();
}
public enum Recipe {
ChileConLeche(R.layout.chile_con_leche),
Arroz(R.layout.arroz),
Enchiladas(R.layout.enchiladas),
Sopa(R.layout.sopa)
int layout;
Recipe(int layout) { this.layout = layout };
}
Ideally, you would want to use Fragments, but here is an example of an Activity structure
public abstract class RecipeActvity extends AppCompatActivity implements Layoutable {
protected Recipe recipe;
protected int getLayout() { return recipe.layout; }
}
public class ChileConLecheActivity extends RecipeActvity {
public ChileConLecheActivity() {
this.recipe = Recipe.ChileConLeche;
}
#Override
public void onCreate(...) {
setContentView(getLayout());
}
}
You can also combine this with a Map<Recipe, Class<RecipeActivity>>, from which you would use map.get(Recipe.ChileConCarne) to get the respective class element, for which you can startActivity() with

Why we extends AbstractTabelModel when set values into JTabel?

Im developing a app for ordeing system and i have to set data into JTabels.
And this code is successfully working.I wanted to know what the importance of and whats happen in this class?
Why we need to import AbstractTabelModel.class?
OrderTabelModel Class:-
public class OrderTableModel extends AbstractTableModel{
protected static final String[] COLUMN_NAMES={"Item","Qty","Amount"};
private List<Order> rows;
public OrderTableModel(List<Order> rows){
this.rows = new ArrayList<>(rows);
}
#Override
public int getRowCount() {
return rows.size();
}
#Override
public int getColumnCount() {
return COLUMN_NAMES.length;
}
#Override
public String getColumnName(int column) {
return COLUMN_NAMES[column];
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object value = null;
Order row = rows.get(rowIndex);
switch (columnIndex) {
case 0:
value = row.getItem();
break;
case 1:
value = row.getQty();
break;
case 2:
value = row.getAmount();
break;
}
return value;
}
}
this is other class
private void tblOrderListMouseClicked(java.awt.event.MouseEvent evt) {
int raw = tblOrderList.getSelectedRow();
Order or;
String item;
Double qty,amount,total;
ArrayList<Order> arrOrder = new ArrayList<Order>();
String selectedRaw = tblOrderList.getModel().getValueAt(raw, 0).toString();
System.out.println("order id : "+selectedRaw);
String sql = "select item,qty,amount from orderdetails where orderid='"+selectedRaw+"'";
con = new DBconnector().connect();
try {
Statement ps =con.createStatement();
ResultSet rs2 = ps.executeQuery(sql);
while(rs2.next()){
or = new Order();
or.setItem(rs2.getString("item"));
System.out.println("Item :" +rs2.getString("item"));
or.setQty(rs2.getDouble("qty"));
or.setAmount(rs2.getDouble("amount"));
arrOrder.add(or);
}
rs2.close();
ps.close();
OrderTableModel tblModel = new OrderTableModel(arrOrder);
tblOrderItems.setModel(tblModel);
} catch (Exception e) {
e.printStackTrace();
}
}
Can some one explain me the process of this please?
It is not always mandatory to extend the AbstractTableModel. You can simply extend the DefaultTableModel and only override the getValueAt() method if you have to.
But most of the time for simple usages it is not even needed to override the getValueAt() method either.
By using the DefaultTableModel, you have a limitation for the converting you data (imported from DB) to an object[][] or Vector types which may be a little boring.
But you asked what is the importance of using AbstractTabelModel?
In this case I can say when JTable is started to being rendered, it needs to determine the number of rows and number of the columns and also it needs to know which data should be renedered in each cell and so on. Based on this, JTable ask for this Information from the underlying TableModel. So it is needed for your TableModel(any child or implementation of TableModel) to have those methods which are used by JTable to retrieve the needed information.
Hope this would be helpful.
Good Luck.

JTable from AbstractTableModel not showing

Im using Window Builder plugin in eclipse to make all the visual components, and i add a JTable, and at first it was a simple JTable, and it show the data correctly. Since i need that the data of the JTable be non-editable, i create a model to use the method isCellEditable. my code is this.
public class MyTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private String[] columnNames;
private Object[][] data;
public MyTableModel(Object[][] sentdata, String[] cnames){
columnNames = cnames;
data = sentdata;
}
#Override
public int getColumnCount() {
// TODO Auto-generated method stub
return 0;
}
#Override
public int getRowCount() {
// TODO Auto-generated method stub
return 0;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
// TODO Auto-generated method stub
return null;
}
public boolean isCellEditable (int row, int column){
return false;
}
}//fin del modelo
and in the constructor of the class is this
String[] NombresdeColumnas = {"Nombre del Producto", "Cantidad en Inventario", "Precio Unitario"};
RegistroInventario inventariodatos = new RegistroInventario();
Object[][] data = inventariodatos.regresarInventario();
MyTableModel model1 = new MyTableModel(data, NombresdeColumnas);
Table_Inventario = new JTable(model1);
Table_Inventario.setGridColor(Color.gray);
JScrollPane scrollPane_1 = new JScrollPane();
scrollPane_1.setViewportView(Table_Inventario);
and it doesnt show anything, but when i was doing this:
Table_Inventario = new JTable(data, NombresdeColumnas);
it was working just fine, i don´t know if the error has todo with de Window Builder form eclipse or in the code cause im new doning JTables.
your issue is return 0; in
public int getColumnCount() {
and
public int getRowCount() {
use DefaultTableModel instead, sure if isn't there really important issue to use AbstractTableModel for Object[][] data or Vector of Vectors
usage of AbstractTableModel make me sence for model based on HashMap or java.util.List e.i.
Your AbstractTableModel does not contain any data.
You indicate it contains zero rows and zero columns by your implementation of the getColumnCount and getRowCount methods.
And even when you adjust those methods, you do not use the data passed in the constructor as you always return null in the getValueAt method.
I think you should start reading the 'How to create a TableModel' section from the table tutorial

Fill JTable in Java using Web Service recieving a List<Project>

Hello I have a school project where we created webmethods using web service with an ordinary .asmx file.
The programs I made in .Net C# have no problem with the return being a List<Project>.
However, I try to get the Java to work, and I tried Object[][] = wws.SelectAllProject() and so forth.
Here's the webmethod:
[WebMethod]//Ska vara collection
public List<Project> SelectAllProjects()
{
Controller contr = new Controller();
List<Project> project = contr.SelectAllProjects();
return project;
}
Here's the Project.cs file:
public class Project
{
public string pId { get; set; }
public string pName { get; set; }
public string pDescript { get; set; }
public Project()
{
this.pId = pId;
this.pName = pName;
this.pDescript = pDescript;
}
}
So in Java how shall I call the method?
I can call my other methods that are void which are ADD/Remove project...
public void SelectAllProjects () {
WebService webService = new WebService();
wws = webService.getWebServiceSoap12();
//Anropar webservice och får en Collection av Project
String[] columnNames = {"Project ID:", "Project Name:", "Project Description:"};
Object[][] = wws.selectAllProjects();
//Array[]test = wws.selectAllProjects();
}
Now I want to return something from this method (it should not be void) that which I can use to fill out a JTable in my view class (using MVC). The webmethod you see and returns a list of project. How shall I make this in Java? Tried googling, but I don't seem to find anything that is close to my project.
Thanks.
Compose your TableModel with a reference to your List<Project>, and use the model to construct your JTable. For example, your table might display two of the three project attribtes, and your row count would rely on the list's size().
#Override
public int getColumnCount() {
return 2;
}
#Override
public int getRowCount() {
return project.size();
}
For reference, this example extends AbstractTableModel and illustrates an implementation of getValueAt() that uses a Map<String, String>. See also How to Use Tables: Creating a Table Model.

Implementing ArrayLists to Table models

Hi I have an arraylist of a class I created called Pets which has the variables below
private String name;
private String species;
private int age;
I wanted to display this arraylist into a jTable and I did that succesfully by using defaultTableModel and calling setModel().
However I needed to add a sorting and filtering function for the Jtable. I took a look at the java tutorials were they were creating a subclass of AbstractTableModel in order to sort and filter. However they were using arrays to store the data. So I tried modifying the code to use an arraylist isntead but Im stuck with this method
public Object getValueAt(int row, int col) {
return data[row][col];
}
How do I get all the values from one object from th arraylist?
Any help will be greatly appreciated. Thanks in advance.
Does your ArrayList hold a row that is it's own type of object? If so, and if your ArrayList is a generic ArrayList<RowItem> then you could do something like:
#Override
public Object getValueAt(int row, int col) {
if (row > getRowCount()) {
// throw an exception
}
RowItem rowItem = rowItemList.get(row);
switch (col) {
case 0:
return rowItem.getName();
case 1:
return rowItem.getLastSpecies();
case 2:
return rowItem.getAge();
}
return null; // or throw an exception
}
You can try this:
public Object getValueAt(int row, int col) {
switch(col) {
case 0:
return ((Pets)data.get(row)).getName();
case 1:
return ((Pets)data.get(row)).getSpecies();
case 2:
return ((Pets)data.get(row)).getAge();
}
return null;
}

Categories