How to compare ArrayList with SQLite Table Row? - java

Let's say I have a sqlite table named "table" with the rows id, text1, text2
now I have an ArrayList with the content, let's say:
id:0,text1:this is the first text,text2: this is the second text
id:21, text1: blabla, text2: blabla2
...
now i want to make a comparision between sqlite row and every single element row in arraylist.
for example i want to say delete every row in sqlite table which is not equal with any row in arraylist.
I could not find any equal thread that contains my question.. maybe you can help me or give me some link. thank u

Here you have some example code. You should get the idea:
public void removeRows(DatabaseAdapter dbAdapter, ArrayList<SomeObject> list) {
SQLiteDatabase db = dbAdapter.openWritableDatabase();
Cursor rows = db.query(/ *perform some query on SQLite db*/);
while(rows.moveToNext()) {
int id = rows.getInt(0);
String text1 = rows.getString(1);
String text2 = rows.getString(2);
boolean included = false;
for(SomeObject obj : list) {
if(obj.getId() == id && obj.getText1().equals(text1) && obj.getText2().equals(text2)) {
included = true;
break;
}
}
if(!included) {
db.delete(/*perform deletion of row*/);
}
}
}
Edit: To add to database those objects from list which are not yet in it do something like this:
public void addListToDb(DatabaseAdapter dbAdapter, ArrayList<SomeObject> list) {
SQLiteDatabase db = dbAdapter.openWritableDatabase();
Cursor rows = db.query(/ *perform some query on SQLite db*/);
for(SomeObject obj : list) {
boolean included = false;
while(rows.moveToNext()) {
int id = rows.getInt(0);
String text1 = rows.getString(1);
String text2 = rows.getString(2);
if(obj.getId() == id && obj.getText1().equals(text1) && obj.getText2().equals(text2)) {
included = true;
break;
}
}
rows.moveToPosition(-1);
if(!included) {
db.insert(/*perform insert of object*/);
}
}
}
There is also another way to accomplish this task. Loop over elements of your list and add every element to database using SQLiteDatabase#insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm) method and pass SQLiteDatabase.CONFLICT_IGNORE as a conflictAlgorithm. Above method will add element if it not yet exists in database. Otherwise it will ignore it. Important thing to remember is that when we try to insert a row which already exists in database with CONFLICT_IGNORE conflict algorithm we will get -1 result instead of primary key of existing row (Android documentation is misleading here).

Related

ArrayList updated inserting one row but Jtable still not refresh

I've to create a java swing app that allows the user to menage some Oracle tables.
I've implemented the JTable in this way:
public class TableModel extends AbstractTableModel{
.
.
.
public List <List <String> > result = null;
.
.
.
public void createTable(ResultSet r) throws SQLException {
rs = r;
numcols = getColumnCount();
result = new ArrayList();
while (rs.next()) {
List <String> row = new ArrayList<>(numcols);
for (int i=1; i<= numcols; i++)
row.add(rs.getString(i).replace("00:00:00.0", "")); //just managing stuffs .. nothing important. Don't care of this replace.
result.add(row);
}
fireTableStructureChanged();
}
public void addRow(){
List <String> row = new ArrayList<>();
for(int i=1;i<=getColumnCount();i++)
row.add("");
result.add(row);
fireTableStructureChanged();
}
public Object getValueAt(int row, int col) {
return result.get(row).get(col);
}
public int getColumnCount() {
if (rs == null) {
return 0;
}
try {
return rs.getMetaData().getColumnCount();
} catch (SQLException e) {
System.err.println("error in colcount");
return 0;
}
}
public int getRowCount() {
int totalRows = 0;
try {
rs.last();
totalRows = rs.getRow();
rs.beforeFirst();
} catch(Exception ex) {
return 0;
}
return totalRows ;
}
}
so, I store database data into the arraylist and then I print the table using the arraylist.
Now in the addRow() function I add to that arraylist an empty record (in my mind an empty record is a record composed of all null ("") strings).
Finally using the fireTableStructureChanged() method I expect the table to refresh itself.. but this will never occur and I don't understand why.
I've already checked that the new row is successfully loaded into the arraylist:
I got all the data stored in the table of the Database into the arraylist and the new row is successfully loaded in the arraylist.
so I swear the problem is about that fireTableStructureChanged() method.
Thanks :3
Try using fireTableRowsInserted(int firstRow, int lastRow) instead of fireTableStructureChanged()
Here's the javadoc for the structure changed ...
Notifies all listeners that the table's structure has changed. The number of columns in the table, and the names and types of the new columns may be different from the previous state. If the JTable receives this event and its autoCreateColumnsFromModel flag is set it discards any table columns that it had and reallocates default columns in the order they appear in the model. This is the same as calling setModel(TableModel) on the JTable.
So that one will only work if the columns types changed ...
If you are lazy go for this one: fireTableDataChanged()
I found the solution.
That's quite embarassing..
#tsolakp you helped me a lot!
Since before using ArrayList I was working on ResultSet directly, I forgot to update getrowcount.
So, since the inserting was only "client side" on the arraylist, the rows displayed were only "n" (where n was the number of rows on the database). So I would never displayed my new row since it was not loaded into the database.
That's all :)
Maybe working hard on coding, makes these errors invisible :X

Apache POI autoSizeColumn() behaving weird

Please read full before marking as duplicate. I have seen all the related/similar questions already and I guess I have something weird happening here.
I'm using Apache POI version 3.9 to generate a 4 sheet workbook. Every time I'm done filling the sheet, I auto-size the columns. Here's the code:
for (String alias : map.keySet()) {
Sheet sheet = workbook.createSheet(getSheetNameForAlias(alias));
List<Object[]> resultList = (List<Object[]>) map.get(alias);
Collections.sort(resultList.subList(1, resultList.size()), getComparator(alias));
int rownum = 0;
for (Object[] array : resultList) {
rownum = populateRow(cellStyles, sheet, rownum, array, false);
}
for(int j=0; j< resultList.get(0).length; j++){
sheet.autoSizeColumn(j, false);
}
}
the populateRow function is:
private int populateRow(CellStyle[] cellStyles, Sheet sheet, int rownum, Object[] dataArr, boolean doAutoSizing) {
if (logger.isDebugEnabled()) {
logger.debug("Populating row ... #{} : {} ", sheet.getSheetName(), rownum);
}
int cellnum;
Row row = sheet.createRow(rownum++);
cellnum = 0;
if (ArrayUtils.isEmpty(dataArr)) {
logger.error("No data found for row ... #{} : {} ", sheet.getSheetName(), rownum);
return rownum;
}
for (Object obj : dataArr) {
Cell cell = row.createCell(cellnum++);
// get the type of the data inserted in the cell.
// Accordingly set the cell value
String data = String.valueOf(obj);
if (StringUtils.isBlank(data) || "null".equals(data)) {
cell.setCellValue(StringUtils.EMPTY);
} else {
if (NumberUtils.isNumber(data)) {
Double dbVal = NumberUtils.createDouble(data);
// Millions separator for Numeric fields
if (dbVal == Math.ceil(dbVal)) {
cell.setCellStyle(cellStyles[0]);
} else {
cell.setCellStyle(cellStyles[1]);
}
cell.setCellType(Cell.CELL_TYPE_NUMERIC); // for numeric , set cell type as numeric
cell.setCellValue(dbVal);
} else {
if(obj instanceof java.sql.Timestamp || obj instanceof java.sql.Date){
cell.setCellStyle(cellStyles[2]);
}
cell.setCellValue(data);
}
if (doAutoSizing) {
sheet.autoSizeColumn(cellnum - 1);
}
data = null;
}
obj = null;
}
return rownum;
}
The weird part is, columns of one out of the four sheets are getting resized incorrectly.
I tried re-writing the auto size logic with different approaches in my mind and discovered that the sheet, for which I'm getting this incorrect behaviour, if I try sheet.getRow(0), it gives out null which specifies that there is no data for that row but the excel being generated does not hold good with that, all four sheets have appropriate data. And in every case, the first row is always the headings so It couldn't be null even if there is no data beneath it.
I don't know what I'm missing but I tried and found that it is not a Font issue with the JVM.
Please let me know in case you need some other info.
EDIT: Observed that auto-sizing is working incorrectly for the sheet which has more than 100 rows. I don't know how to relate it to some logic. This is real WEIRD.
EDIT 2: I found the official reference for the reason given by Axel while looking for something else. This does suffice my confusion. Read the para on the following
link
Since you say it works up to 100 rows, it looks like you are using SXSSFWorkbook, not XSSFWorkbook. Then that behaviour has to be expected, since only a fixed number of rows are kept in memory, and only these rows will be considered. So, if I am right, you will have to switch to using XSSFWorkbook (provided this doesn't lead to OOMs when dealing with a large number of rows).

How to retrieve multiple row from database in java

I need to insert different result into the row of my JTable. I search my record by using purchaseID which is the pID, it will find 2 result for that particular purchaseID. The problem is when I insert it into row, it just duplicate the result of the first one. EG : P0001 have 2 purchase details and when I insert it into row, I have 2 same row. Is there any way for me to insert into row one by one ?
PS. I've been coding since morning, brain is not functioning well.
UI:
else if(e.getSource() == jbtRetrieve)
{
String pID = jTF3.getText();
Purchase purchase = purcControl.selectRecord(pID);
if (purchase != null) {
String pdCountStr = purchase.getPurchaseDetailsID();
String pdCountStr2 = pdCountStr.substring(2,5);
int pdCount = Integer.parseInt(pdCountStr2);
for(int g = 0; g<pdCount;g++){ //g =1
tableModel.addRow(new Object[]{ purchase.getPurchaseDetailsID(),purchase.getStockID(),purchase.getPrice(),purchase.getQuantity()});
}}
DA :
public Purchase getRecord(String pID){
String queryStr = "SELECT PD.PURCHASEDETAILID,PD.PURCHASEID,PD.STOCKID,PD.ORDERQTY,S.STOCKPRICE FROM "+tableName+" PD, STOCKS S WHERE PD.STOCKID = S.STOCKID AND PurchaseID = ?";
Purchase purchase = null;
System.out.println("asd");
try{
stmt = conn.prepareStatement(queryStr);
stmt.setString(1,pID);
ResultSet rs = stmt.executeQuery();
if(rs.next()){
purchase = new Purchase(pID, rs.getString("purchaseID"),rs.getString("stockID"),rs.getDouble("stockprice"),rs.getInt("orderqty"));
}
}
catch (SQLException ex){
JOptionPane.showMessageDialog(null,ex.getMessage(),"ERROR",JOptionPane.ERROR_MESSAGE);
}
return purchase;
}
Domain:
public Purchase(String purchaseDetailsID,String purchaseID,String stockID,double price,int quantity)
{
this.purchaseDetailsID = purchaseDetailsID;
this.purchaseID = purchaseID;
this.stockID = stockID;
this.price = price;
this.quantity = quantity;
}
public void setPurchaseID(String u){
this.purchaseID = u;
}
public String getPurchaseID(){
return purchaseID;
}
public String getPurchaseDetailsID(){
return purchaseDetailsID ;
}
public double getPrice(){
return price;
}
public String getStockID(){
return stockID;
}
public int getQuantity(){
return quantity;
}
public void setPurchaseDetailsID(String r){
this.purchaseDetailsID = r ;
}
public void setPrice(double p){
this.price = p;
}
public void setStockID(String s){
this.stockID = s;
}
public void setQuantity(int q){
this.quantity = q;
}
Control :
public Purchase selectRecord(String pID){
return purcDA.getRecord(pID);
}
Edit: Set Purchase to ArrayList<> to accept the List and I get this Exception.
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:635) at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
at ui.MainPurchasingFrame$ListenerClass.actionPerformed(MainPurchasingFrame.java:183)
code:
ArrayList<Purchase> purchase = purcControl.selectRecord(pID);
if (purchase != null) {
String pdCountStr = purchase.get(0).getPurchaseDetailsID();
String pdCountStr2 = pdCountStr.substring(2,5);
int pdCount = Integer.parseInt(pdCountStr2);
System.out.print(pdCount);
for(int g = 0; g<pdCount;g++){
tableModel.addRow(new Object[]{ purchase.get(g).getPurchaseDetailsID(),purchase.get(g).getStockID(),purchase.get(g).getPrice(),purchase.get(g).getQuantity()}); //This is where the exception occurs.
}
If you want to return multiple objects from a query, your return type should be either an array or a collection of that type.
So instead of defining
public Purchase getRecord(String pID){…}
You should define the DA method as:
public List<Purchase> getRecords(String pID) {…}
Inside the method, define a list object such as:
List<Purchase> foundPurchases = new ArrayList<>();
And then after issuing the query and getting the result set, you use a while loop to fill it:
while ( rs.next() ) {
purchase = new Purchase(pID, rs.getString("purchaseID"),rs.getString("stockID"),rs.getDouble("stockprice"),rs.getInt("orderqty"));
foundPurchases.add( purchase );
}
Then, after you finish and close your statement, you should return the foundPurchases:
return foundPurchases;
The calling code should, of course, expect to receive a List of purchases rather than a purchase, and then iterate and display it.
Now regarding your edited part. You are doing several things improperly.
First of all, you don't have to go inside the purchase records to see how many records there were. If there were none, the list will be empty. If there was 1, it's size is going to be 1, and if there are two, its size is going to be two.
Second, you actually don't need to know how many elements there are, because you can traverse a list by using its iterator, in a simple for loop:
ArrayList<Purchase> purchaseList = purcControl.selectRecord(pID);
for ( Purchase purchase : purchaseList ) {
…
}
You don't actually have to use get. You have the current individual purchase in the variable purchase (Note that I changed the name of your original variable to something that shows it's a list and not a purchase), and you can use it directly.
Note also that you don't need to check for nulls. The way I've written it, the DA method always returns a reference to a List, even if it's an empty list. And the loop always adds an actual new Purchase(…) to the list so the list's items are also never null.
One thing, though: from the way the error looks, it seems that you have only one row when the details ID says there should be two. Check your query directly with the database to be sure there are actually two records.
If you want to display an error when nothing was found, you should check with an if statement if the list is empty. This means that no records have been returned at all.
if ( purchasedList.isEmpty() ) {
// Display error dialog
} else {
// Do the for loop to fill the rows
}

Logical error when trying to remove an item from a JList

I have a JList that shows all the items I have added to the database. When I want to remove multiple items, say two items, just one of them gets removed. This is my code:
This method is from my class DAL:
public void removeStudent(Student student)throws SQLException{
PreparedStatement studentStatement = getConnected().prepareStatement(
"delete from student where spnr = ? and sname = ? and sadress = ? " +
" and stel = ? ");
studentStatement.setString(1, student.getIdNumber());
studentStatement.setString(2, student.getName());
studentStatement.setString(3, student.getAddress());
studentStatement.setString(4, student.getTel());
studentStatement.executeUpdate();
}
The class Controller:
public void removeStudent(Student student) throws SQLException{
dal.removeStudent(student);
}
and the class View. Used in the actionListener when the button remove is clicked.
private void removeStudent(){
try{
controller.getDal().getStudentData().getName();
controller.getDal().getStudentData().getAddress();
controller.getDal().getStudentData().getIdNumber();
controller.getDal().getStudentData().getTel();
controller.removeStudent(controller.getDal().getStudentData());
}catch(Exception e){
e.printStackTrace();
}
}
And the ActionEvent
if(infLst.getSelectedIndex() > -1){
int choice = JOptionPane.showConfirmDialog(null,
"Delete?" + "The student will be permamently deleted",
null,
JOptionPane.YES_NO_OPTION);
if(choice == JOptionPane.YES_OPTION){
//Removes from the JList
((DefaultListModel)infLst.getModel()).removeElementAt(index);
//And database
removeStudent();
}else{
return;
}
}else{
JOptionPane.showMessageDialog(null, "Please make sure you have selected an item from the list");
}
}}});
Please consider that I'm new in this field with database programming. Thanks in advance.
When I want to remove multiple items, say two items, just one of them gets removed.
Your code only has an if condition that checks the selected index so it will only ever delete one item.
If you want to delete all selected values then you need to use a method from JList that returns multiple values to delete. Look at the API for other getSelected...() methods that you can use for this purpose. Then you will need to create a loop to delete all the values.
The method that return Objects istead of index values will be easier to use since you can just delete the Object from the model and you don't need to worry about deleting the higher indexed value first.

How to set and get the cell value of JavaFX Table like swing JTable

I am new to JavaFX and would like to know how to set and get the cell value of JavaFX Table like Swing JTable. i.e. an alternative of setValueAt() & getValueAt of Swing JTable in JavaFX Table.
//would like to get the index of column by Name
int index_RunnableQueueItem = tableQueue.getColumns().indexOf("RunnableQueueItem");
//would like to get the selected row
int row = tableQueue.getSelectionModel().getSelectedIndex();
if (index_RunnableQueueItem != -1 && row != -1) {
// would like to get the value at index of row and column.
//Update that value and set back to cell.
}
TableView really doesn't support this methodology.
Here's a somewhat brittle means of doing what you want, using reflection. It's entirely dependent upon you using PropertyValueFactory in your cell value factory so it can lookup the property name, though.
class MyItem
{
SimpleStringProperty nameProperty = new SimpleStringProperty("name");
public MyItem(String name) {
nameProperty.set(name);
}
public String getName() { return nameProperty.get(); }
public void setName(String name) { nameProperty.set(name); }
public SimpleStringProperty getNameProperty() { return nameProperty; }
}
...
TableView<MyItem> t = new TableView<MyItem>();
TableColumn col = new TableColumn("Name Header");
col.setCellValueFactory(new PropertyValueFactory<MyItem, String>("name"));
t.getColumns().addAll(t);
...
public void setValue(int row, int col, Object val)
{
final MyItem selectedRow = t.getItems().get(row);
final TableColumn<MyItem,?> selectedColumn = t.getColumns().get(col);
// Lookup the propery name for this column
final String propertyName = ((PropertyValueFactory)selectedColumn.getCellValueFactory()).getProperty();
try
{
// Use reflection to get the property
final Field f = MyItem.class.getField(propertyName);
final Object o = f.get(selectedRow);
// Modify the value based on the type of property
if (o instanceof SimpleStringProperty)
{
((SimpleStringProperty)o).setValue(val.toString());
}
else if (o instanceof SimpleIntegerProperty)
{
...
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
Retrieving a simple value from a JavaFx TableView Cell
You can use listeners as listed in other posts, but if you wish to get just a simple value from a cell you can use a simpler method
Example:
// Get the row index where your value is stored
int rowIndex = tableView.getSelectionModel().getSelectedIndex();
// Since you can't get the value directly from the table like the
// getValueAt method in JTable, you need to retrieve the entire row in
// FXCollections ObservableList object
ObservableList rowList =
(ObservableList) tableViewModelos.getItems().get(rowIndex);
// Now you have an ObservableList object where you can retrieve any value
// you have stored using the columnIndex you now your value is, starting
// indexes at 0;
// In my case, I want to retrieve the first value corresponding to the first column //index, and I know it is an Integer Value so I'll cast the object.
int columnIndex = 0;
int value = Integer.parseInt(rowList.get(columnIndex).toString());
Hope this expample helps you.

Categories