Search code examples
javajavabeansderbyresultsetapache-commons-dbutils

BeanListHandler from dbutils library cannot create java class objects from a database resultset


I have created a class called Product and a table having the same name (Product) in apache derby database. Now i want to get the corresponding Product objects whenever i retrieve the rows from the database using BeanListHandler but always get an error. I have searched almost everywhere for solutions after which i still don't see where i went wrong in my code. Can someone please tell me where i am wrong. my code is shown below.

public class Product {

private long uniqueId; //Auto increment
private String productCode;  
private String productName;
private String productCategory;
private boolean available;
private double productPrice;
private int quantityOnHand;    

public Product(long uniqueId, String productCode, String productName, String productCategory, boolean available, double productPrice, int quantityOnHand) {
    this.uniqueId = uniqueId;    //Auto increment
    this.productCode = productCode;
    this.productName = productName;
    this.productCategory = productCategory;
    this.available = available;
    this.productPrice = productPrice;
    this.quantityOnHand = quantityOnHand;    }

@Override
public String toString() {
    return "Product{" + "uniqueId=" + uniqueId + ", productCode=" + productCode + ", productName=" + productName + ", productCategory=" + productCategory + ", available=" + available + ", productPrice=" + productPrice + ", quantityOnHand=" + quantityOnHand + '}';
}


public long getUniqueId() {
    return uniqueId;
}

public String getProductCode() {
    return productCode;
}

public String getProductName() {
    return productName;
}

public String getProductCategory() {
    return productCategory;
}

public boolean isAvailable() {
    return available;
}

public double getProductPrice() {
    return productPrice;
}

public int getQuantityOnHand() {
    return quantityOnHand;
}


public void setUniqueId(long uniqueId) {
    this.uniqueId = uniqueId;
}

public void setProductCode(String productCode) {
    this.productCode = productCode;
}

public void setProductName(String productName) {
    this.productName = productName;
}

public void setProductCategory(String productCategory) {
    this.productCategory = productCategory;
}

public void setAvailable(boolean available) {
    this.available = available;
}

public void setProductPrice(double productPrice) {
    this.productPrice = productPrice;
}

public void setQuantityOnHand(int quantityOnHand) {
    this.quantityOnHand = quantityOnHand;
}

@Override
public int hashCode() {
    int hash = 5;
    hash = 53 * hash + (int) (this.uniqueId ^ (this.uniqueId >>> 32));
    hash = 53 * hash + Objects.hashCode(this.productCode);
    hash = 53 * hash + Objects.hashCode(this.productName);
    hash = 53 * hash + Objects.hashCode(this.productCategory);
    hash = 53 * hash + (this.available ? 1 : 0);
    hash = 53 * hash + (int) (Double.doubleToLongBits(this.productPrice) ^ (Double.doubleToLongBits(this.productPrice) >>> 32));
    hash = 53 * hash + this.quantityOnHand;
    return hash;
}

@Override

    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    final Product other = (Product) obj;
    if (!Objects.equals(this.productCode, other.productCode)) {
        return false;
    }
    if (!Objects.equals(this.productName, other.productName)) {
        return false;
    }
    if (!Objects.equals(this.productCategory, other.productCategory)) {
        return false;
    }
    return true;
}

}

Below is the method to retrieve the Product rows and convert then into Product Objects. I have already imported and created every component needed to establish connection and perform the query(like private QueryRunner queryRunner=new QueryRunner(); private static final List EMPTY_PRODUCT_LIST=new ArrayList<>(); etc)

public List<Product> searchAllProducts() {
    ResultSetHandler<List<Product>> p = new BeanListHandler<>(Product.class);

    try{
   return   (List<Product>) queryRunner.query(connection, "SELECT * FROM PRODUCT", p);
        }
    catch(SQLException e){

              e.printStackTrace();
          }
     finally{
        try {
            DbUtils.close(connection);
        } catch (SQLException ex) {
            Logger.getLogger(ProductDatabaseHandler.class.getName()).log(Level.SEVERE, null, ex);
        }

        }
      return EMPTY_PRODUCT_LIST; }

And below is the error that i get.

Fri Dec 02 20:05:35 EAT 2016 : Apache Derby Network Server - 10.11.1.2 -     (1629631) started and ready to accept connections on port 1555
java.sql.SQLException: Cannot create main.java.models.Product:
main.java.models.Product Query: SELECT * FROM PRODUCT Parameters: []
at   org.apache.commons.dbutils.AbstractQueryRunner.rethrow(AbstractQueryRunner.java:392) 
at org.apache.commons.dbutils.QueryRunner.query(QueryRunner.java:351)
at org.apache.commons.dbutils.QueryRunner.query(QueryRunner.java:226)              
at main.java.database.ProductDatabaseHandler.searchAllProducts(ProductDatabaseHandler.java:226)

Solution

  • I think you need to have a no-arg constructor for your Product class with appropriate setter methods.

    BeanProcessor is responsible for converting Resultset into bean and below is the code where it creates the new instance of bean.

      protected <T> T newInstance(Class<T> c) throws SQLException {
        try {
            return c.newInstance();
    
        } catch (InstantiationException e) {
            throw new SQLException(
                "Cannot create " + c.getName() + ": " + e.getMessage());
    
        }
    

    Clearly it expects a no-arg constructor