I have an Access database which I need to retrieve all fields except the first and last and display it in a JTable. Everything works perfectly fine when I create my Object[][] but when i return it, i get a NullPointerException. I tried to find where there could be a null value in the database by printing the whole object out but that works fine and no values are null. Why would returning the Object[][] give me a NullPointerException and how can i fix it?
the stack trace is:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
public Object [] [] SetTrainingLogTable() throws SQLException
{
DatabaseConnection connection = new DatabaseConnection();
//Retrieves all the data from the TrainingLog table
ResultSet resultset = connection.SelectStatements("SELECT * FROM TrainingLog");
//Retrieves the number of entries
ResultSet numberofworkouts = connection.SelectStatements("SELECT COUNT(*) FROM TrainingLog");
int count = numberofworkouts.getInt(1);
number = count;
String[][] table = new String [count] [6];
//Number to incriment for while loops
int row = 0;
String date = "";
while(row<count)
{
date = resultset.getString(2);
table [row][0] = calculate.RefineDate(date);
table [row][1] = resultset.getString(3);
table [row][2] = resultset.getString(4);
table [row][3] = resultset.getString(5);
table [row][4] = resultset.getString(6);
table [row][5] = resultset.getString(7);
resultset.next();
row++;
}
Object[][] data = table;
connection.close();
return data;
}
I ran a debugger and it only gives the error when the return line is run.
It's best to post the stack trace and tell which line is raising the error. However, the typical way of writing such code is:
Connection con = ...;
Statement st = ...;
ResultSet rs = ...;
while (rs.next()) {
// ...
}
The result set starts out pointing before the first row. rs.next() returns whether there is a next row, and advances to it if it exists. Can you rewrite it in that style?
Other suggestions:
Can you create an actual object type instead of using Object[] to store the data from each row? Call it Workout.
Can you use a List<Workout> instead of your Object[][]?
Is the date stored in the database as a SQL DATE or TIMESTAMP? Then, don't convert it to a Java String: use java.sql.Date or java.util.Date. At work, I have a large old program that uses strings for dates, and it uses different formats to convert the values at different times. It's pretty miserable.
Don't use SELECT *. Give the names of the columns to return. Use the rs.getString("column_name") syntax.
There's no need to set one variable to the returned table and immediately set another variable to it.
Closing the connection or statement should be done in a finally block, or by try-with-resources.
Related
import java.util.ArrayList;
public class DataBase {
public ArrayList<String> nameList = new ArrayList<>();
public void nameAdd(String s, int i) {
if (i < nameList.size()){
nameList.add(i, s);
//string not adding to arrayList, ive probably done it wrong.
}
System.out.println(s);
System.out.println("nameList.size = " + nameList.size());
System.out.println("arrayList number = " + i);
}
}
I've been coding for about a month now so please excuse my noobieness but i'm trying to basically take a string from a GUI i've built, cut it up to get a name, and add that name to a "database" when the user clicks another button to add it to it. Ive already been able to increment the i which is supposed to set an index for the string within the arrayList but the arrayList isnt increasing in size and I get a whole bunch of errors thus the if statement ive added to stop it from trying to add to an index that isnt yet in the arrayList.
In your code I see your array nameList always empty.
Because you have this line:
public ArrayList<String> nameList = new ArrayList<>();
In this moment you create your array (empty), but in your nameAdd method if you pass this at the first time:
nameAdd('ADDFIRSTELEMENT', 0)
Your if statemnt is always false
if (i < nameList.size()){
nameList.add(i, s);
//string not adding to arrayList, ive probably done it wrong.
}
You must to change your check as follow:
if (i <= nameList.size())
Because if your index is the same of the size, you can add your element in the array.
If you want you can use the contains method of your nameList ArrayList object so you can see if your string is present in your array
I am populating data using 2 views inside a data delegate. I have to calculate running balance by sorting the based on transaction date. How do i sort the data and populate the running balance.
The delegate code is given below.
[PXVirtualDAC]
public PXSelectOrderBy<FundBalanceData, OrderBy<Asc<FundBalanceData.tranDate>>> fbdata;
protected virtual IEnumerable FBData()
{
List<FundBalanceData> importlist = new List<FundBalanceData>();
PXSelectBase<ARPayment> cmd = new PXSelectJoin<ARPayment, InnerJoin<GLTran, On<ARPayment.batchNbr, Equal<GLTran.batchNbr>>,
InnerJoin<PMProject, On<GLTran.projectID, Equal<PMProject.contractID>>>>,
Where<GLTran.projectID, Equal<Current<PMProject.contractID>>,
And<ARPayment.docType, Equal<ARPaymentType.prepayment>>>>(Base);
foreach(PXResult<ARPayment,GLTran,PMProject> line in cmd.Select())
{
FundBalanceData data = new FundBalanceData();
ARPayment arp = line;
PMProject pmp = line;
GLTran glt = line;
data.BAccountID = arp.CustomerID;
data.CreditAmount = glt.CreditAmt;
data.DebitAmount = glt.DebitAmt;
data.RefNbr = arp.RefNbr;
data.DocType = arp.DocType;
data.Desc = arp.DocDesc;
data.TranDate = arp.DocDate;
importlist.Add(data);
}
PXSelectBase<APAdjust> cmd2 = new PXSelectJoin<APAdjust, LeftJoin<GLTran, On<APAdjust.adjBatchNbr, Equal<GLTran.batchNbr>, And<APAdjust.adjdAPAcct, Equal<GLTran.accountID>>>,
InnerJoin<APPayment, On<APAdjust.adjgRefNbr, Equal<APPayment.refNbr>, And<APAdjust.adjgDocType, Equal<APPayment.docType>>>,
InnerJoin<APTran,On<APTran.refNbr,Equal<APAdjust.adjdRefNbr>,And<APTran.tranType,Equal<APAdjust.adjdDocType>>>>>>,
//InnerJoin<GLTran, On<APTran.projectID, Equal<GLTran.projectID>>>>>,
Where<APAdjust.adjgDocType, Equal<APPaymentType.prepayment>, And<APTran.projectID, Equal<Current<PMProject.contractID>>, And<GLTran.accountID, NotEqual<APPayment.aPAccountID>>>>>(Base);
foreach (PXResult<APAdjust,GLTran,APPayment,APTran> line in cmd2.Select())
{
FundBalanceData data = new FundBalanceData();
APPayment arp = line;
GLTran glt = line;
APAdjust apd = line;
data.BAccountID = arp.VendorID;
data.CreditAmount = glt.CreditAmt;
data.DebitAmount = glt.DebitAmt;
data.RefNbr = arp.RefNbr;
data.DocType = arp.DocType;
data.Desc = arp.DocDesc;
data.TranDate = arp.DocDate;
importlist.Add(data);
}
decimal? balance = decimal.Zero;
foreach(FundBalanceData data in importlist)
{
balance = balance + (data.CreditAmount - data.DebitAmount);
data.Balance = balance;
}
return importlist;
}
The array is not sorted by TranDate and the balance calculated is wrong
The result after implementing Samvel Petrosov suggestion
I was trying to sort the array on DateTime? and missed used the Value property. I have tried Samvel Petrosov suggestion and it worked.
Here is the part about sorting of the Result set of data views from T200 Acumatica Framework Fundamentals Course:
A data view executes the delegate by the following rules:
If a delegate is defined, invoke the delegate
If the delegate returns null, execute the BQL command
If the delegate returns an object, reorder the result according to the OrderBy clause of the BQL command
If a delegate is not defined, execute the BQL command
The result set returned by the data view is always sorted by the ORDER
BY clause specified in the type of the data view object. If you sort
data records in a different way within the delegate, the result set
will be reordered before it is returned by the data view.
The calculation of the Balance in your code is done before the return of the result set. That is way it is not calculated as you are waiting. The sorting is taking place after you return the result set.
UPDATE 1
Change your cmd and cmd2 to the following queries:
PXSelectBase<ARPayment> cmd = new PXSelectJoin<ARPayment, InnerJoin<GLTran, On<ARPayment.batchNbr, Equal<GLTran.batchNbr>>,
InnerJoin<PMProject, On<GLTran.projectID, Equal<PMProject.contractID>>>>,
Where<GLTran.projectID, Equal<Current<PMProject.contractID>>,
And<ARPayment.docType, Equal<ARPaymentType.prepayment>>>,OrderBy<Asc<ARPayment.DocDate>>>(Base);
PXSelectBase<APAdjust> cmd2 = new PXSelectJoin<APAdjust, LeftJoin<GLTran, On<APAdjust.adjBatchNbr, Equal<GLTran.batchNbr>, And<APAdjust.adjdAPAcct, Equal<GLTran.accountID>>>,
InnerJoin<APPayment, On<APAdjust.adjgRefNbr, Equal<APPayment.refNbr>, And<APAdjust.adjgDocType, Equal<APPayment.docType>>>,
InnerJoin<APTran,On<APTran.refNbr,Equal<APAdjust.adjdRefNbr>,And<APTran.tranType,Equal<APAdjust.adjdDocType>>>>>>,
//InnerJoin<GLTran, On<APTran.projectID, Equal<GLTran.projectID>>>>>,
Where<APAdjust.adjgDocType, Equal<APPaymentType.prepayment>, And<APTran.projectID, Equal<Current<PMProject.contractID>>, And<GLTran.accountID, NotEqual<APPayment.aPAccountID>>>>,OrderBy<Asc<APPayment.DocDate>>>(Base);
UPDATE 2
Try to add additional sorting by transaction date before the last loop:
importlist= importlist.OrderBy(x => x.TranDate.Value).ToList();
or if TranDate is not DateTime?
importlist= importlist.OrderBy(x => x.TranDate).ToList();
I need to get the list of column qualifiers available in a HBase table.
Suppose I have a table 'Customers' with column 'info:Age' and 'contact:PhoneNo'. To get the list of column families I see there's a method 'getColumnDescriptors' which returns the value 'info' and 'contact'.
But how to retrieve the full column names 'info:Age' and 'contact:PhoneNo' from the table or atleast the qualifiers 'Age' and 'PhoneNo' alone.
With the method 'getRowWithColumns' I am able to get the list of column names where I have to pass the row key value.
Will I be able to achieve this through any other convenient way?
Here is a working solution in Java as you asked, you just have to change a few things to translate it to C++.
Basically this method will scan the table and retrieves the column qualifiers, then I add them into a list if this list does not already contains it.
Here, I look at all the rows, but if all your rows always have the same columns, you can just scan the first row, using a Get for example (look at the HBase documentation, I've written several examples there).
public ArrayList<String> getColumnName(String tablename) {
ArrayList<String> properties = new ArrayList<String>();
try {
Table table = this.connection.getTable(TableName.valueOf(tablename));
Scan scan = new Scan();
ResultScanner rs = table.getScanner(scan);
try {
for (Result r = rs.next(); r != null; r = rs.next()) {
for (Cell c : r.rawCells()) {
String family = new String(CellUtil.cloneFamily(c));
String qualifier = new String(CellUtil.cloneQualifier(c));
System.out.println("Column Family : "+ family);
System.out.println("Column Qualifier : " + qualifier);
if (!properties.contains(qualifier))
properties.add(new String(CellUtil.cloneQualifier(c)));
}
}
} finally {
rs.close(); // always close the ResultScanner!
}
} catch (IOException e) {
e.printStackTrace();
}
return properties;
}
I have a set of text files that I am reading into a datatable. I want to be able to read the frist column (Id) and find out the highest number. Each of the files goes from 0 to at least 21 sequentially. I tried suggestions from the following link: How to select min and max values of a column in a datatable?
Sadly, I could not any to work. The one suggestion that kind of worked is shown in the second last line, but it returns a value of 8 or 9. Any suggestions as to how to properly get the results I am looking for?
string filePath = System.IO.Path.GetFullPath(curriculum);
DataTable curriculmDataTable = new DataTable();
curriculmDataTable.Columns.Add("Id");
curriculmDataTable.Columns.Add("Course");
curriculmDataTable.Columns.Add("Credit");
// Read in a file line-by-line, and store it
var txtFileLine = File.ReadAllLines(filePath).ToList();
//Reads line splits data to colums at tab (ASCII value 9)
txtFileLine.ForEach(line => curriculmDataTable.Rows.Add(line.Split((char)9)));
//Suggestions from link
int max = Convert.ToInt32(curriculmDataTable.Select("Id=max(Id)")[0][0]);
label1.Text = ""+ max;
The problem is that you have created string columns but you want to get the max-values according to their numeric value. The best way is to store the corrrect type in the first place. Then you could either use DataTable.Compute or Linq-To-DataSet:
create an int column:
curriculmDataTable.Columns.Add("Id", typeof(int));
convert the strings to int and add them to the table:
foreach(string line in File.ReadLines(filePath))
{
DataRow row = curriculmDataTable.Rows.Add();
string[] fields = line.Split(new[]{(char)9});
int id;
if(fields.Length == 3 && int.TryParse(fields[0], out id)
{
row.SetField("Id", id);
row.SetField("Course", fields[1]);
row.SetField("Credit", fields[2]);
}
}
Now you can use Linq:
int maxID = curriculmDataTable.AsEnumerable().Max(r => r.Field<int>("Id"));
DataTable.Compute (works also with earlier .NET versions):
int maxID = (int)curriculmDataTable.Compute("Max(Id)", "")
We can get max value from the column in a dataTable using this syntax
var maxValue = dataTblDetails.Compute("max(ColumnName)", string.Empty);
I wrote a simpe test to validate my own understanding of the thrift interface for Cassandra. It just inserts a row into the database (using the keyspace and column familty that come preconfigured with the cassandra installation), then reads it from the database and compares the results.
public class CassandraAPITest {
#Test
public void testCassandraAPI() throws Exception {
TTransport tr = new TSocket("localhost", 9160);
tr.open();
Client client = new Cassandra.Client(new TBinaryProtocol(tr));
String key = "123";
byte[] value = { 52, 53, 54 };
ColumnPath columnPath = new ColumnPath("Standard1");
columnPath.setColumn("abc".getBytes("UTF8"));
long timestamp = System.currentTimeMillis();
client.insert("Keyspace1", key, columnPath, value, timestamp, ConsistencyLevel.ONE);
SlicePredicate predicate = new SlicePredicate();
SliceRange sliceRange = new SliceRange();
sliceRange.setStart(new byte[0]);
sliceRange.setFinish(new byte[0]);
predicate.setSlice_range(sliceRange);
List<ColumnOrSuperColumn> result = client.get_slice("Keyspace1", key, new ColumnParent("Standard1"), predicate, ConsistencyLevel.ONE);
assertEquals(1, result.size());
byte[] actual = result.get(0).column.value;
assertArrayEquals(value, actual);
// client.remove("Keyspace1", key, columnPath, System.currentTimeMillis(), ConsistencyLevel.ONE);
tr.close();
}
}
This test runs fine. Of course it leaves a row behind in the database. I could delete the row at the end of the test by uncommenting the client.remove statement above (this also works fine). But what I tried instead was deleting the row via the command-line interface:
cassandra> connect localhost/9160
Connected to: "Test Cluster" on localhost/9160
cassandra> get Keyspace1.Standard1['123']
=> (column=616263, value=456, timestamp=1287909211506)
Returned 1 results.
cassandra> del Keyspace1.Standard1['123']
row removed.
cassandra> get Keyspace1.Standard1['123']
Returned 0 results.
The test fails afterwards. Inserting the row into the database seems to have no effect anymore, so the line assertEquals(1, result.size()) fails:
java.lang.AssertionError: expected:<1> but was:<0>
at org.junit.Assert.fail(Assert.java:91)
at org.junit.Assert.failNotEquals(Assert.java:618)
at org.junit.Assert.assertEquals(Assert.java:126)
at org.junit.Assert.assertEquals(Assert.java:443)
at org.junit.Assert.assertEquals(Assert.java:427)
at test.package.CassandraAPITest.testCassandraAPI(CassandraAPITest.java:48)
I don't get any error messages (neither on the client nor on the server) and I have no idea what the cause of the problem might be.
You are inserting with millisecond resolution but the CLI (and other high level clients) uses microseconds. So your second insert is in the past, compared to the delete, so Cassandra correctly ignores it.