Currently I got the following problem:
I load the TableModel data from a H2 database like so:
public static DefaultTableModel loadTableModel(ResultSet rs)
throws SQLException {
// names of columns
Vector<String> columnNames = new Vector<String>();
int columnCount = Definitions.COLUMN_NAMES.length;
for (String string : Definitions.COLUMN_NAMES) {
columnNames.add(string);
}
// data of table
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
while (rs.next()) {
Vector<Object> vector = new Vector<Object>();
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
if (rs.getObject(columnIndex).getClass() == Integer.class) {
if ((int) rs.getObject(columnIndex) == 0) {
vector.add(null);
} else {
vector.add(rs.getObject(columnIndex));
}
} else {
vector.add(rs.getObject(columnIndex));
}
}
data.add(vector);
}
return new DefaultTableModel(data, columnNames);
}
By doing so I pass over the data from my database and columnNames to the constructor of the DefaulTableModel. The problem is, that not all my columns contain the same data type (seemingly the default type seems to be String), so I need to set the data type for all columns directly while creating the DefaultTableModel. How can this be don? I did not find a method to change the column class later on.
If I create my own "TableModelClass" that extends DefaultTableModel, how do I need to create a constructor that works something like this:
TableModelClass(data, columnNames, columnType)
columnType should be a vector containing the Class types like
String.class, Boolean.class etc.
ResultSetMetaData md = rs.getMetaData();
probably is info You expected. Call only once while openning, metadata is ok when zero rows is in query result too.
BTW I usually
build kind of "table metadata" like human readable column captions (Polish language).
be aware at null in some rows (You are ok)
I use traditionally Map< String,OBject > but vector is good to.
copy & paste from my real code, this sample is from web (Wicket) but data modelling is the same.
protected Map<String, Object> move_fields() {
Map<String, Object> rec = new HashMap<String, Object>();
// MathContext mc = new MathContext(2);
for (int i = 0; i < columns; i++) {
String key;
try {
key = md.getColumnName(i + 1).toLowerCase();
int type = md.getColumnType(i + 1);
Object o;
switch (type) {
case java.sql.Types.DOUBLE:
case java.sql.Types.DECIMAL:
case java.sql.Types.FLOAT:
case java.sql.Types.NUMERIC:
BigDecimal bd = rs.getBigDecimal(i + 1);
if (bd != null) {
// bd = bd.round(mc);
bd = bd.setScale(2, RoundingMode.HALF_EVEN);
}
o = bd;
break;
default:
o = rs.getObject(i + 1);
break;
}
rec.put(key, o);
} catch (SQLException e) {
e.printStackTrace();
}
}
for (Entry<String, DynamicField> v : virtuals.entrySet()) {
v.getValue().prepare(rs, record, _my_has_next);
Object o = v.getValue().getValue(rs, record, _my_has_next);
rec.put(v.getValue().getNameInTemplate(), o);
}
for (Entry<String, String> f: rest.entrySet()) {
String kolumna = f.getKey();
String prawo = f.getValue();
if(prawa.contains(prawo)){
int c=1;
}
else{
record.put(kolumna, "");
}
}
return rec;
}
Related
So I need to populate a JTable using data from
List<Object[]> results = query.getResultList();
I'm using NetBeans. I have tried many different things that haven't seemed to work for me.
This is my code:
public void login()
{
Query queryPK = CryptoCurrencyPUEntityManager.createNativeQuery("SELECT t.email, t.user_id FROM usertbl t");
Query queryFK = CryptoCurrencyPUEntityManager.createNativeQuery("SELECT t.curreny, t.amount FROM CURRENCY t WHERE user_fk=?1 ");
List<Object[]> results = queryPK.getResultList();
for(int i = 0; i < results.size(); i++)
{
if(results.get(i)[0].equals(loginEmail))
{
int fk = (int)(results.get(i)[1]);
System.out.println(fk);
queryFK.setParameter(1, fk);
List<Object[]> currencyTBLresluts = queryFK.getResultList();
Currency cur = new Currency();
String[] currTBLheadings = {"Currency","Amount"};
// This is where I would put the data into the table
// Not sure how I am meant to do that
// jTableCurr.setModel(); maybe?
}
}
}
This is an one of many example that you could use it:
//declaring columns
String col[] ={"Currency", "Amount"};
//TableModel
DefaultTableModel tableModel = new DefaultTableModel (col,0);
//Your awesome table with tableModel *injected*
JTable table = new JTable(tableModel);
public void login() {
Query queryPK = CryptoCurrencyPUEntityManager.createNativeQuery("SELECT t.email, t.user_id FROM usertbl t");
Query queryFK = CryptoCurrencyPUEntityManager.createNativeQuery("SELECT t.curreny, t.amount FROM CURRENCY t WHERE user_fk=?1 ");
List<Object[]> results = queryPK.getResultList();
for(int i = 0; i < results.size(); i++) {
if(results.get(i)[0].equals(loginEmail)) {
int fk = (int)(results.get(i)[1]);
System.out.println(fk);
queryFK.setParameter(1, fk);
List<Object[]> currencyTBLresluts = queryFK.getResultList();
if(currencyTBLresluts != null && !currencyTBLresluts.isEmpty()){
Object[] array = currencyTBLresluts.toArray(new Object[currencyTBLresluts.size()]);
((DefaultTableModel)table.getModel()).addRow(array);
}
}
}
}
I came right after looking though the api
public void whenUserLogsIn(){
Query queryPK = CryptoCurrencyPUEntityManager.createNativeQuery("SELECT t.email, t.user_id FROM usertbl t");
Query queryFK = CryptoCurrencyPUEntityManager.createNativeQuery("SELECT t.curreny, t.amount FROM CURRENCY t WHERE user_fk=?");
List<Object[]> results = queryPK.getResultList();
for(int i = 0; i < results.size(); i++)
{
Object[] userArr = results.get(i);
if(userArr[0].equals(loginEmail))
{
int userID = (int)(userArr[1]);
System.out.println(userID);
queryFK.setParameter(1, userID);
List<Object[]> currencyTBLresluts = queryFK.getResultList();
System.out.println("No of currency "+ currencyTBLresluts.size());
String[] currTBLheadings = {"Currency","Amount"};
DefaultTableModel model = new DefaultTableModel(currTBLheadings, currencyTBLresluts.size());
for (Object[] currencyTBLreslut : currencyTBLresluts)
{
model.addRow(currencyTBLreslut);
System.out.println(currencyTBLreslut[0]);
}
jTableCurr.setModel(model);
}
}
}
How can I get the value of HashTable inside the arrayList?
I have the following code:
public ArrayList resultSetToArrayList(ResultSet rs) {
ArrayList list = new ArrayList();
try {
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
int rowcount = 0;
while (rs.next()) {
Hashtable row = new Hashtable();
for (int i = 1; i <= columns; ++i) {
row.put(md.getColumnName(i), rs.getString(i));
}
list.add(rowcount, row);
rowcount++;
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
You appear to be using raw types and Hashtable instead of a HashMap. I think you're asking for something like
public List<Map<String, String>> resultSetToArrayList(ResultSet rs) {
List<Map<String, String>> list = new ArrayList<>();
try {
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
while (rs.next()) {
Map<String, String> row = new HashMap<>();
for (int i = 1; i <= columns; ++i) {
row.put(md.getColumnName(i), rs.getString(i));
}
list.add(row);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
As for getting the values back out of a Map, you might iterate the Map.keySet() like
for (String key : map.keySet()) {
System.out.printf("%s = %s%n", key, map.get(key));
}
This is a last resort. I'm studying development of Information Systems and even my teachers can't solve this... this is a nut for you to crack!!
This is the problem: My jTable in GUI gives me this:
This is what Microsoft Management Studio shows me:
As you can tell the jTable (GUI) has got 2 main problems:
The columnname "Name" does not contain any information. And it should? Why isn't it showing?
Since as you can tell, the table contains several columns, too many to even show. I therefore want to "add a restriction" that changes so that the jTable only shows the first 6 columns.
This is the code for the "creation of the table", in the DataAccessLayer:
private TableModel getResultSetAsDefaultTableModel(ResultSet rs) {
try {
String[] columnHeadings = new String[0];
Object[][] dataArray = new Object[0][0];
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
String columnName = md.getColumnName(i);
columnHeadings = Arrays.copyOf(columnHeadings, columnHeadings.length + 1);
columnHeadings[i - 1] = columnName;
}
int r = 0;
while (rs.next()) {
Object[] row = new Object[columnCount];
for (int i = 1; i <= columnCount; i++) {
row[i - 1] = rs.getObject(i);
}
dataArray = Arrays.copyOf(dataArray, dataArray.length + 1);
dataArray[r] = row;
r++;
}
DefaultTableModel dtm = new DefaultTableModel(dataArray, columnHeadings) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
return dtm;
} catch (SQLException ex) {
Logger.getLogger(Dataaccesslayer.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
If you want me to show you the path of the code (frame, controller) just say so and I'll post it.
I would be so thankful if anyone can solve this...
Regards,
Christian
I think it is because in your for loop it should say i = 0; and not i = 1; since the first information (the name) is at index 0 right ?
In your case it could be enough to just leave the for-loop as it is and change this line to:row[i - 1] = rs.getObject(i-1);
To hide or show columns you could call setMin setMax and setPreferredWidth on your TableColumn.
Change your method like next, I think it helps you:
private TableModel getResultSetAsDefaultTableModel(ResultSet rs) {
try {
List<String> columnHeadings = new ArrayList<String>();
Object[][] dataArray = new Object[0][0];
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
columnHeadings.add(md.getColumnName(i));
}
int r = 0;
while (rs.next()) {
Object[] row = new Object[columnCount];
for (int i = 1; i <= columnCount; i++) {
row[i-1] = rs.getObject(i);
}
dataArray = Arrays.copyOf(dataArray, dataArray.length + 1);
dataArray[r] = row;
r++;
}
DefaultTableModel dtm = new DefaultTableModel(dataArray,columnHeadings.toArray(new Object[columnHeadings.size()])) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
return dtm;
} catch (SQLException ex) {
Logger.getLogger(Dataaccesslayer.class.getName()).log(Level.SEVERE,null, ex);
}
return null;
}
For showing not all columns use dtm.setColumnCount(2);. Here 2 is column count to show.
This is the code for the "creation" of the table I have in my DataAccessLayer.
private TableModel getResultSetAsDefaultTableModel(ResultSet rs) {
try {
String[] columnHeadings = new String[0];
Object[][] dataArray = new Object[0][0];
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
String columnName = md.getColumnName(i);
columnHeadings = Arrays.copyOf(columnHeadings, columnHeadings.length + 1);
columnHeadings[i - 1] = columnName;
}
int r = 0;
while (rs.next()) {
Object[] row = new Object[columnCount];
for (int i = 1; i <= columnCount; i++) {
row[i - 1] = rs.getObject(i);
}
dataArray = Arrays.copyOf(dataArray, dataArray.length + 1);
dataArray[r] = row;
r++;
}
DefaultTableModel dtm = new DefaultTableModel(dataArray, columnHeadings) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
return dtm;
} catch (SQLException ex) {
Logger.getLogger(Dataaccesslayer.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
**This results in some complications, since one of my tables has 50 different columns and therefore you can't read the columnnames or what is in the cell.
The problem is that the table's values are determined by the metadata...
I want to limit the columns that are showed to a specific number (5) for all tables.
How do I do it?**
Kind regards,
Chris
you can remove tables if you want to...
int amountColumns = table.getColumnModel().getColumnCount(); //count columns
TableColumn c6 = table.getColumnModel().getColumn(6); //identif a random column
table.getColumnModel().removeColumn(c6); //remove this column
i hope that helped...
I would not remove them but change their size to 0.
int amountColumns = table.getColumnModel().getColumnCount(); //count columns
TableColumn c6 = table.getColumnModel().getColumn(6); //identif a random column
table.getColumnModel().setMin(0);
table.getColumnModel().setMax(0);
table.getColumnModel().setPreferredWidth(0);
Like i answered you in your other thread...
I am using the following to add retrieved values to the class. all values will be added to attributes of the class but I am using compisition ( have an object of class in the class) and it does not show anything on output.
class employee
{
....
private Address address = new Address();
.....
}
...
Employee emp = new Employee();
try {
ps = con.prepareStatement("select * from employee,address "
+ "WHERE employee.username = ? AND "
+ "employee.ADD_ID = address.ID");
ps.setString(1, username);
ResultSet r = ps.executeQuery();
if (r.next()) {
BeanProcessor bp = new BeanProcessor();
emp = bp.toBean(r,Employee.class);
System.out.println("blockkkk:"+emp.getAddress().getBlock());
//output of above line is blockkkk:null
}
con.close();
ps.close();
} catch (SQLException e) {
System.err.println(e.getMessage());
}
return emp;
Address class is as following:
public class Address {
.....
private String block;
....
public String getBlock() {
return block;
}
public void setBlock(String block) {
this.block = block;
}
....
}
The BeanProcessor.toBean works like this:
Convert a ResultSet row into a JavaBean. This implementation uses reflection and BeanInfo classes to match column names to bean property names. Properties are matched to columns based on several factors:
The class has a writable property with the same name as a column. The name comparison is case insensitive.
The column type can be converted to the property's set method parameter type with a ResultSet.get* method. If the conversion fails (ie. the property was an int and the column was a Timestamp) an SQLException is thrown.
Primitive bean properties are set to their defaults when SQL NULL is returned from the ResultSet. Numeric fields are set to 0 and booleans are set to false. Object bean properties are set to null when SQL NULL is returned. This is the same behavior as the ResultSet get* methods.
May be the address is not a writable property. Pls do check it.
public static Object copyFromResultSet(Class clazz, ResultSet resultSet)
{
ArrayList objectArrayList = new ArrayList(1);
try
{
Object object = clazz.newInstance();
objectArrayList.add(object);
copyFromResultSet(objectArrayList, resultSet);
}
catch (Exception e)
{
e.printStackTrace();
}
return objectArrayList.get(0);
}
then:
public static void copyFromResultSet(ArrayList<Object> objectArrayList, ResultSet resultSet)
{
ArrayList arrayList = null;
try
{
if (objectArrayList != null)
{
int objectArrayList_len = objectArrayList.size();
int objectArrayList_index = 0;
java.beans.BeanInfo toBeanInfo[] = new java.beans.BeanInfo[objectArrayList_len];
Vector<Method> objectMethodVector[] = new Vector[objectArrayList_len];
Vector<Type> objectTypeVector[] = new Vector[objectArrayList_len];
int totalMethod[] = new int[objectArrayList_len];
int[][] indexes = new int[objectArrayList_len][];
for (objectArrayList_index = 0; objectArrayList_index < objectArrayList_len; objectArrayList_index++)
{
toBeanInfo[objectArrayList_index] = java.beans.Introspector.getBeanInfo(objectArrayList.get(objectArrayList_index).getClass());
}
if (objectArrayList_len > 0 && resultSet != null)
{
Method method = null;
Type type[] = null;
int cols = 0;
String colName = null;
for (objectArrayList_index = 0; objectArrayList_index < objectArrayList_len; objectArrayList_index++)
{
//toBeanInfo[objectArrayList_index]=java.beans.Introspector.getBeanInfo(objectArrayList.get(objectArrayList_index).getClass());
java.beans.PropertyDescriptor toPropertyDescriptor[] = toBeanInfo[objectArrayList_index].getPropertyDescriptors();
int toPropertyDescriptor_length = toPropertyDescriptor.length;
method = null;
type = null;
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
cols = resultSetMetaData.getColumnCount();
colName = null;
Vector<Method> methodVector = new Vector(cols);
Vector<Type> typeVector = new Vector(cols);
indexes[objectArrayList_index] = new int[cols];
totalMethod[objectArrayList_index] = -1;
for (int i = 1; i <= cols; i++)
{
colName = resultSetMetaData.getColumnName(i);
for (int j = 0; j < toPropertyDescriptor_length; j++)
{
if (toPropertyDescriptor[j].getName().equalsIgnoreCase(colName))
{
totalMethod[objectArrayList_index]++;
method = toPropertyDescriptor[j].getWriteMethod();
type = method.getGenericParameterTypes();
methodVector.add(method);
typeVector.add(type[0]);
indexes[objectArrayList_index][totalMethod[objectArrayList_index]] = i;
break;
}
}
}
objectMethodVector[objectArrayList_index] = (methodVector);
objectTypeVector[objectArrayList_index] = (typeVector);
}
if (resultSet.next())
{
arrayList = new ArrayList();
for (objectArrayList_index = 0; objectArrayList_index < objectArrayList_len; objectArrayList_index++)
{
for (int i = 0; i <= totalMethod[objectArrayList_index]; i++)
{
//System.out.println(objectMethodVector[objectArrayList_index].get(i));
objectMethodVector[objectArrayList_index].get(i).invoke(objectArrayList.get(objectArrayList_index), getObject(indexes[objectArrayList_index][i], objectTypeVector[objectArrayList_index].get(i), resultSet));
}
arrayList.add(objectArrayList.get(objectArrayList_index));
}
}
while (resultSet.next())
{
for (objectArrayList_index = 0; objectArrayList_index < objectArrayList_len; objectArrayList_index++)
{
for (int i = 0; i <= totalMethod[objectArrayList_index]; i++)
{
objectMethodVector[objectArrayList_index].get(i).invoke(objectArrayList.get(objectArrayList_index), getObject(indexes[objectArrayList_index][i], objectTypeVector[objectArrayList_index].get(i), resultSet));
}
arrayList.add(objectArrayList.get(objectArrayList_index));
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
just copy paste this code call method copyFromResultSet(class, ResultSet )
pass two perameters first is class name and second is resultset.
i am sure this is working properlly