So im getting this NPE whenever im trying to return an ArrayList object into an FXCOLLECTIONS list.
Here is the Code.
Method return the al to FXCOLLECTIONS.
public ArrayList<MeetBooking> selectMeetBookings()
{
ArrayList<MeetBooking> meetBookingArrayList = new ArrayList<>();
System.out.println("Trying to select from table meetBooking");
try
{
//Query the database and storing the result in an object of type ResultSet
sqlString = "SELECT * FROM CPC.meetBooking ORDER BY bookingID ASC";
rs = stmt.executeQuery(sqlString);
//Use the methods of class ResultSet in a loop
// to display all of the data in the result
while (rs.next())
{
int id = rs.getInt("bookingID");
Date bookingDateTime = rs.getDate("bookingDateTime");
System.out.println(bookingDateTime.toString());
int empID = rs.getInt("employeeID");
String bookingcmnt = rs.getString("bookingComment");
MeetBooking meetBooking = new MeetBooking();
meetBooking.setBookingID(id);
meetBooking.setBookingDate(bookingDateTime.toString());
meetBooking.setEmployeeID(empID);
meetBooking.setBookingComment(bookingcmnt);
meetBookingArrayList.add(meetBooking);
}
}
catch (Exception e)
{
e.printStackTrace();
}
return meetBookingArrayList;
}
Public Class MeetBooking
//Method to set a date as a string utilises Stringproperty and //simplestringproperty
public void setBookingDate(String value)
{
bookingDate.set(value);
}
//Controller access to first method
public ArrayList<MeetBooking> getMeetBookings()
{
return dbcon.selectMeetBookings();
}
// UI access to controller.getMeetBooks
meetBookingObservableList = FXCollections.observableArrayList(controller.getMeetBookings());
Im not quite sure how to solve this, but i think the Date is the culprit.
However I've been debugging this for a long time and need your expertise.
One potential reason for the NPE is that your database can contain Null values in some of your columns.
If you have Nulls in the bookingDateTime or the employeeID columns, then you will get an exception in one of the following lines:
Date bookingDateTime = rs.getDate("bookingDateTime");
System.out.println(bookingDateTime.toString());
int empID = rs.getInt("employeeID");
If I remember my Java, the Date class can contain a null. However, if the value is null, then bookingDateTime.toString() will attempt to convert the Null to string. A Null does not have a method, so you get that NullPointerException.
Also, an int cannot store Nulls, so you have a similar issue when attempting to force a Null into empID.
Related
I have a problem with loading objects from a SQLite database.
First of all, this is my table definition:
CREATE TABLE MyTable (
rowid INTEGER PRIMARY KEY,
data BLOB
);
This is the simple class which I want to store and reload:
public class MyHashMap extends HashMap<String, Integer> {
private static final long serialVersionUID = 0L;
}
Then I'm filling the map with some data and store it with an SQL INSERT statement in the database. Everything works fine and if I execute a SELECT (with the sqlite3 command-line client) I will see the correct information.
Now I'm using the java.sql package to load the object:
String sql = "SELECT data FROM MyTable WHERE rowid = 1";
MyHashMap map = null;
try {
try (Statement stmt = db.createStatement()) {
try (ResultSet rs = stmt.executeQuery(sql)) {
if (rs.next()) {
map = rs.getObject("data", MyHashMap.class);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
There's no exception thrown but my map variable is null. I debugged the program and I can say that the getObject method is called as expected.
First, you definition of MyHashMap is incorrect
public class MyHashMap extends HashMap<Integer, String> {
private static final long serialVersionUID = 0L;
}
The main issue, though, is that SQL doesn't store Java objects; it merely stores rows of records, which consist of fields. You need to read these records one by one, and store them in your map. Roughly as follows:
MyHashMap map = new MyHashMap();
final String sql = "SELECT rowid, data FROM MyTable";
try (final Statement stmt = connection.createStatement;
final ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
map.put(rs.getInt(1), rs.getString(2));
}
}
Please note that there's a good chance that reading a Blob into a String will fail. Usually, JDBC drivers are clever enough to convert data types, but if you have raw binary data in your blob, you cannot read it into a string. You would need the getBlob method instead, and deal with the resulting object. But I can't tell from your code what you'll be storing in that blob.
Ok, I found a solution with the following method:
private Object getObjectFromBlob(ResultSet rs, String columnName)
throws ClassNotFoundException, IOException, SQLException {
InputStream binaryInput = rs.getBinaryStream(columnName);
if (binaryInput == null || binaryInput.available() == 0) {
return null;
}
ObjectInputStream in = new ObjectInputStream(binaryInput);
try {
return in.readObject();
} finally {
in.close();
}
}
I am facing troubles when building a generic preparedStatement : I have 8 SQL Tables, which are all manipulated the same way, so I'd like to build a unique manager which could insert into / select from any of the 8 tables.
To do so, each table has a descriptor, which can provide the fields of a table, its name and the array of values when inserting.
In the manager, the prepared statement to insert is of the following form :
"INSERT INTO " + table_name + " VALUES (?)"
Then, I fill the gap with something like
myPreparedStatement.setString(1, values.getAllValues());
the getAllValues() method must return a string which holds every fields, like " 'This', 'Is', 3, 'example' ".
I have no problem with strings and numbers, but I can't add any date in those values...
Using September 3rd, 2008 as example, I used the following formats :
2008-09-03,
08-09-03,
080903,
03092018, but all fail. "yyMMdd" format seemed like the best option from what I saw here and there, but I have the error :
"java.sql.SQLDataException: ORA-01843: not a valid month"
And I have no idea why... has anyone faced this issue before ?
I know there are lots of posts here that talks about inserting dates in database, but they all use the
preparedStatement.setDate(pos, Date);
Statement, and I can't do that since the dates aren't in the same position in all of my tables.
EDIT :
As asked in the comment, here is a minimal sample that reproduce what I'm trying to do. If you want to reproduce as well, I let you handle the connection and database setup :
public class Sample {
public void saveAll() throws ServiceException {
Connection c = null;
PreparedStatement ps = null;
String sql = "INSERT INTO " + getTableName() +" VALUES (?)";
try {
c = getConnection();
c.setAutoCommit(false);
batch = c.prepareStatement(sql);
batch.setString(getAllFieldValues());
int res = batch.executeUpdate();
c.commit();
} catch (BatchUpdateException b) {
throw new ServiceException("Erreur lors de l'exécution du batch", b);
} catch (SQLException s) {
throw new ServiceException("Impossible de sauvegarder les beans en base.", s);
} finally {
getManager().close(batch);
freeConnection(c);
}
}
public String getAllFieldValues() {
return "'Hello', 'World', 42, '171228'";
}
public String getTableName() {
return "myTableName";
}
}
There is no such thing as generic preparedStatement in JDBC. To insert four columns in table T you must use
INSERT into T (col1,col2,col3,col4) values (?,?,?,?)
You may ommit the first list with the column names, but this is a bad practice as you trust on the actual columns of the table that may change.
Using only
INSERT into T values (?,?,?,?)
work fine until somebody modifies the table by adding or dropping a column and will fail afterwards.
All bind variables must be set extra with the setXXX method with appropriate type and index of the column starting with 1.
stmt.setInt(1,100)
stmt.setString(2,'xxx')
If I can understand your question correctly. For dynamically placing your date value in prepared statement you can override setString() method to have your custom code to check for date value or else.
Or rather in case you can also have local method to check if coming string is of format date.
For this you can simply pass Date String with some prefix attached so that you can check it in custom setString() method.
setString(String string, int position){
if(string.contains("SPECIFIC_PREFIX_CONSTANT")){
//batch.setDate(position, string.substring("REMOVE PREFIX AND ATTACH"));
}else{
//batch.setString(position, string);
}
}
Ok guys, I managed to have my stuff working, big thanks to all of you !
In case somebody else would end on my question, I'll recap the Code I have now, which works :)
So, as said previously, we have one Manager that interacts with the database and which has no knowledge of the table's he interacts with.
Here is the code of the save method of this manager :
public void saveAll(AbstractBeanClass[] values, String refSelected) {
// connexion setup
Connection c = null;
PreparedStatement batch = null;
// fetch table's fields, to prepare the placeholders
String fields = values[0].getAllFields();
String sql = "INSERT INTO " + values[0].getTableName() + " (" + fields + ") VALUES (";
StringBuffer places = new StringBuffer();
int [] res = null;
// Start at 1 to have one field left, to end the parenthesis
for(int i = 1; i < values[0].getNumberOfFields(); i++) {
places.append("?, ");
}
// last field
places.append("?)");
sql = sql.concat(places.toString()); // We now have a full (?, ..., ?)
try {
c = getConnection();
c.setAutoCommit(false);
batch = c.prepareStatement(sql);
// Filling the batch
int j = 1;
for(AbstractBeanClass bean : values) {
int i = 1;
for(String type : bean.getAllTypes()) {
switch(type) {
case "int" : {
batch.setInt(i, (int) bean.getOrderedValue(i));
}
break;
case "String" : {
batch.setString(i, (String)bean.getOrderedValue(i));
}
break;
case "Date" : {
batch.setDate(i, (java.sql.Date) bean.getOrderedValue(i));
}
break;
}
i++;
}
batch.addBatch();
// In case of numerous insertions, some Databases don't allow more than 1000 inserts at a time
if(j%1000 == 0) {
res = batch.executeBatch();
for(int k : res) {
if(k == Statement.EXECUTE_FAILED) {
getManager().close(batch);
freeConnection(c);
throw new RuntimeException("Error while inserting values.");
}
}
}
j++;
}
// last execution
res = batch.executeBatch();
for(int i : res) {
if(i == Statement.EXECUTE_FAILED) {
getManager().close(batch);
freeConnection(c);
throw new RuntimeException("Error while inserting values in database.");
}
}
c.commit();
logger.debug("Insertion succeeded, we inserted " + j + " lines.");
} catch (BatchUpdateException b) {
throw new RuntimeException("Error in batch : ", b);
} catch (SQLException s) {
throw new RuntimeException("Error : we couldn't save the values : ", s);
} finally {
getManager().close(batch);
freeConnection(c);
}
}
So this is the main part of the program, but it needs the table descriptor. To keep it simple, I made an abstract class which declares the methods I need, and all table descriptors extends this class, here is the declaration :
package com.fr.sncf.fret.boctarification.domaine.referentiel;
import java.io.Serializable;
import java.text.SimpleDateFormat;
public abstract class DaoGenericReferentielBean implements Serializable {
private static final long serialVersionUID = 1L;
protected String allFields;
// the date Format used to insert the dates in base
protected final SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd");
public DaoGenericReferentielBean() {
// empty constructor
}
/**
* Return all columns' names, ordered according to database's order
* #return
*/
public String getAllFields() {
return this.allFields;
}
/**
* Returns all values ordered by columns' order
* #return String
*/
public abstract String getAllFieldsValues();
/**
* #return the table name
*/
public abstract String getTableName();
/**
* #return the number of field in this table
*/
public abstract int getNumberOfFields();
/**
* Returns the ordered list of column's type
*/
public abstract String[] getAllTypes();
/**
* Return the value corresponding to the given index
* Values are treated here according to the database's columns order
* #param index the column's number
* #return an Object, either an int, or a String, or a Date
*/
public abstract Object getOrderedValue(int index);
}
All you need now is to describe your table according to this model, Hope it helps !
I have in one java class a method which SELECT one coloumn from a table from my database, and that column is an INT type in the database, and then I select items from that coloumn, put it in a List and return this List. Here is the method:
public List<Long> vratiSveSifreRacuna() throws SQLException {
String sqlVratiSifruRacuna = "SELECT RacunID FROM racun";
Statement stat = konekcija.createStatement();
ResultSet rs = stat.executeQuery(sqlVratiSifruRacuna);
Long racunID = 0L;
List<Long> sifre = new ArrayList<Long>();
while (rs.next()){
racunID = rs.getLong("RacunID");
sifre.add(racunID);
}
return sifre;
}
Now, how can I return a list from this method and put in another list?
When I try to do it, it doesn`t work...like it sees the returned list empty or something...
Why is that happenning? Is this method ok?
I want to have a method which returns a whole coloumn from from a database table as List and then I want to use this List somehow...
As you said, you have an INT value in your database and you're using getLong() to try and get an INT value which is probably why it's not working.
Try to use this instead:
while (rs.next()){
racunID = (Long) rs.getInt("RacunID");
sifre.add(racunID);
}
return sifre;
EDIT 1 (Simplified) :
while (rs.next()){
sifre.add(new Long(rs.getInt("RacunID")));
}
return sifre;
You don't even need to add to a new List, just pass your original list along in parameters:
public void vratiSveSifreRacuna(List<Long> passedList) throws SQLException {
String sqlVratiSifruRacuna = "SELECT RacunID FROM racun";
Statement stat = konekcija.createStatement();
ResultSet rs = stat.executeQuery(sqlVratiSifruRacuna);
Long racunID = 0L;
List<Long> sifre = passedList;
while (rs.next()){
racunID = rs.getInt("RacunID"); //column is int, it will automatically upcast to long don't worry about that
sifre.add(racunID);
}
//set sifre to null now to let it get garbage collected :)
sifre=null
}
Call the method as follows now:
yourclassreference.vratiSveSifreRacuna(yourListLong);
Keep your method as it is (side-effects on parameters should be avoided).
Call the method, store the result, and add it to the other list you want to complete.
List<Long> foo = ...; // i don't know where it comes from
List<Long> bar = vratiSveSifreRacuna();
foo.addAll(bar);
See java.util.List#addAll API
i have try to develop one java app.here am getting information from mysql database.
my code is:
public class RetailerWs {
public int data(){
int count=0;
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/pro","root","");
PreparedStatement statement = con.prepareStatement("select * from orders where status='Q' AND MONTH(date) = MONTH(CURDATE()) AND YEAR(date) = YEAR(CURDATE())");
ResultSet result = statement.executeQuery();
while(result.next()) {
// Do something with the row returned.
count++; //if the first col is a count.
}
}
catch(Exception exc){
System.out.println(exc.getMessage());
}
return count;
}
}
the other class is :
public class Demo {
public static void main(String[] args){
RetailerWs obj = new RetailerWs();
System.out.println(obj.data());
}
}
Here i have to check the query and display count value is successfully.but my doubt is the query matched item is zero means the output is displayed blankly.but i wish to need it is display 0.not display blank screen..so please help me how is to do.
Create the object of class RetailerWs.
RetailerWs obj =new RetailerWs ();
System.out.println(obj.data());
The statement
System.out.println(new RetailerWs().data());
wil always, unconditionally print an integer value, even if that value is 0. Unless an exception prevents it from executing, that is.
I have created one form, which contain information of user like name, contact no, photo id number, job profile etc. Once he enter all the information, it will store in database. When he login for second time, after entering photo id number whole information should display on the form, without he enters. I am using key typed event for this. I have tried this code, but it is throwing exception as
java.sql.SQLException: Before start of result set
public void show()
{
try
{
String id=photo_id_num.getText();
System.out.println(""+id);
Connect c=new Connect();
con=c.getConnection();
Statement stmt=con.createStatement();
String queryPhotoid = "select * from tbl_visitor ";
ResultSet rs1= stmt.executeQuery(queryPhotoid);
while (rs1.next())
{
if(id.equals(rs1.getString(6)))
{
// Read values using column name
String name = rs1.getString(2);
int contno = rs1.getInt(3);
String orgname = rs1.getString(4);
String jobpro = rs1.getString(5);
String category = rs1.getString(7);
String date = rs1.getString(8);
int noofpeople = rs1.getInt(9);
Blob image = rs1.getBlob(10);
int extrapeople = rs1.getInt(11);
System.out.println("Name:"+name+" Contact_no:"+contno+"Org_Name:"+orgname+" Job_profile:"+jobpro+"Category:"+category+"Date:"+date+"No_Of_People:"+noofpeople+"image:"+image+"Having extra people:"+extrapeople);
}
}
}
catch (SQLException sqlEx)
{
sqlEx.printStackTrace();
}
}
When you fetch result set the cursor is prior to the first record so you need to take cursor to the first record by executing resultSet.next(), Here in your case you are reading before positioning the cursor
System.out.println("ranu"+rs1.getString(6));
while (rs1.next());
So you first need to do rs.next() then only you can read the records
So make it as follows
ResultSet rs1= stmt.executeQuery(queryPhotoid);
while (rs1.next()) {
System.out.println("ranu"+rs1.getString(6));
if(id.equals(rs1.getString(6)))
{
// blah blah..
}
//blah
}