First, I'll give the codes I'm dealing with.
Action code for the "Save" Button.
private void saveBtActionPerformed(java.awt.event.ActionEvent evt) {
try {
Production production=new Production(batchNoValueLabel.getText(), productIDCombo.getSelectedItem(), rawMaterialUsedCombo.getSelectedItem(), dateValueLabel.getText(), rawMaterialBatchCombo.getSelectedItem(), weightInitialSpinner.getValue(), beforeWeightSpinner.getValue(), afterWeightSpinner.getValue(), finalWeightSpinner.getValue(), packingWeightSpinner.getValue(), noOfUnitSpinner.getValue(), wastageSpinner.getValue());
int res=ProductionController.addBatch(production);
if(res==1){
JOptionPane.showMessageDialog(this, "New Batch Added!");
String nextid = IDGeneration.getNextid("B", "production", "productionBatchID");
batchNoValueLabel.setText(nextid);
productIDCombo.removeAllItems();
ArrayList<String> getProductsDetails = ProductsController.getProductID();
for (String detail : getProductsDetails) {
productIDCombo.addItem(detail);
}
}else{
JOptionPane.showMessageDialog(this, "New Product Adding Failed!");
}
} catch (ClassNotFoundException | SQLException ex) {
Logger.getLogger(ProductsForm.class.getName()).log(Level.SEVERE, null, ex);
}
}
Then, the Model Class. (Getters and Setters are there, not pasted here)
public Production(String productionBatchID, Object finishedMaterialID, Object rawMaterialID, String productionDate, Object rawMatBatchID, Object initialWeight, Object beforeWeight, Object afterWeight, Object finalWeight, Object packingWeight, Object noOfUnits, Object wastage) {
this.productionBatchID = productionBatchID;
this.finishedMaterialID = (String) finishedMaterialID;
this.rawMaterialID = (String) rawMaterialID;
this.productionDate = productionDate;
this.rawMatBatchID = (String) rawMatBatchID;
this.initialWeight = (int) initialWeight;
this.beforeWeight = (int) beforeWeight;
this.afterWeight = (int) afterWeight;
this.finalWeight = (int) finalWeight;
this.packingWeight = (int) packingWeight;
this.noOfUnits = (int) noOfUnits;
this.wastage = (int) wastage;
}
And, finally the controller class.
public class ProductionController {
public static int addBatch(Production production) throws ClassNotFoundException, SQLException {
Connection conn=DBConnection.getConnection();
Statement stm=conn.createStatement();
String sql="insert into production (productionBatchID, finishedMaterialID, rawMaterialID, productionDate, rawMatBatchID, initialWeight, beforeWeight, finalWeight, packingWeight, noOfUnits, wastage) values ('"+production.getProductionBatchID()+"','"+production.getFinishedMaterialID()+"','"+production.getRawMaterialID()+"','"+production.getProductionDate()+"','"+production.getRawMatBatchID()+"','"+production.getInitialWeight()+"','"+production.getBeforeWeight()+"','"+production.getAfterWeight()+"','"+production.getFinalWeight()+"','"+production.getPackingWeight()+"','"+production.getNoOfUnits()+"','"+production.getWastage()+"');";
int rowCount=stm.executeUpdate(sql);
return rowCount;
}
}
And still, when I enter data in the GUI and try to send the data to the database, it gives out "java.sql.SQLException: Column count doesn't match value count at row 1" error. How to solve this? Oh, and here's the MySQL Table:
create table production(productionBatchID VARCHAR(4) NOT NULL,finishedMaterialID VARCHAR(4) NOT NULL,rawMaterialID VARCHAR(4) NOT NULL,productionDate VARCHAR(15),rawMatBatchID VARCHAR(4),initialWeight INT(5),beforeWeight INT(5),afterWeight INT(5),finalWeight INT(5),packingWeight INT(5),noOfUnits INT(5),wastage INT(5),CONSTRAINT PRIMARY KEY (productionBatchID))ENGINE=INNODB;
How to solve this?
Your VALUES clause has
'"+production.getAfterWeight()+"','"+production.getFinalWeight()+
But you only have finalWeight in the column list.
The error tells you this
insert into production (
productionBatchID, finishedMaterialID,
rawMaterialID, productionDate,
rawMatBatchID, initialWeight,
beforeWeight, finalWeight,
packingWeight, noOfUnits,
wastage)
values (
'"+production.getProductionBatchID()+"','"+production.getFinishedMaterialID()+"','"+
production.getRawMaterialID()+"','"+production.getProductionDate()+"','"+
production.getRawMatBatchID()+"','"+production.getInitialWeight()+"','"+
production.getBeforeWeight()+"','"+
production.getAfterWeight()+"','"+
production.getFinalWeight()+"','"+ there are 3 here
production.getPackingWeight()+"','"+production.getNoOfUnits()+"','"+
production.getWastage()+"');";
Also, parameterise your queries to mitigate SQL Injection risks please
There is mismatch in number of columns you are using in INSERT query, 'beforeWeight' is the column, whose values is missing, below is the corrected query:
String sql="insert into production (productionBatchID, finishedMaterialID, rawMaterialID, productionDate, rawMatBatchID, initialWeight, **beforeWeight**, finalWeight, packingWeight, noOfUnits, wastage) values ('"+production.getProductionBatchID()+"','"+production.getFinishedMaterialID()+"','"+production.getRawMaterialID()+"','"+production.getProductionDate()+"','"+production.getRawMatBatchID()+"','"+production.getInitialWeight()+"','"+production.getBeforeWeight()+"','"+production.getAfterWeight()+"','"+production.getBeforeWeight()+"','"+production.getFinalWeight()+"','"+production.getPackingWeight()+"','"+production.getNoOfUnits()+"','"+production.getWastage()+"');";
Related
I am trying to use STRUCT for the insertion of massive data in my table DATA_TABLE, but generate error (java.sql.SQLException: Fail to convert to internal representation) with data type field CLOB and I can't find a solution to my problem, my code:
My table
CREATE TABLE DATA_TABLE (DAT_ID NUMBER,
DAT_CODE VARCHAR2(10),
DAT_TEXT CLOB);
Create type object
CREATE OR REPLACE TYPE TY_OBJ_DATA AS OBJECT (DAT_ID NUMBER,
DAT_CODE VARCHAR2(10),
DAT_TEXT CLOB);
create type table from type object
CREATE OR REPLACE TYPE TY_TABLE_DATA AS TABLE OF SCHEMA.TY_OBJ_DATA;
My simplified java method
public static void bulkData(List<DataTable> listDataInfo) throws Exception {
DataSource ds = (DataSource) getEntityManager().getEntityManagerFactory().getProperties().get("javax.persistence.jtaDataSource");
OracleConnection connection = ds.getConnection().unwrap(OracleConnection.class);
try{
StructDescriptor typeTableObject = StructDescriptor.createDescriptor("SCHEMA.TY_OBJ_DATA", conect);
STRUCT[] structData = new STRUCT[DataTable.size()];
int counter= 0;
for (DataTable d : listDataInfo) {
Clob clob = connection.createClob();
STRUCT m = new STRUCT(typeTableObject, connection,
new Object[]{d.getDatId(),
d.getDatCode,
clob.setString(1, d.getDatText)});
structData [counter++] = m;
}
ArrayDescriptor tyTable = ArrayDescriptor.createDescriptor("SCHEMA.TY_TABLE_DATA", connection);
ARRAY array = new ARRAY(tyTable, connection, structData);
String sqlQuery = "{ CALL PACKAGE_BULK.PL_BULK_DATA }";
CallableStatement cst = conect.prepareCall(sqlQuery);
cst.setArray(1, array );
cst.execute();
} catch (Exception e) {
throw new Exception(e);
} finally {
try {
connection.close();
} catch (SQLException e) {
throw new Exception(e);
}
}
}
I omit the package code, because it is working correctly and is not my main problem. i Use ojdbc6 version 11.2.0, java 8 and Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit.
Is it possible to use STRUCT with fields of type CLOB? I am doing something wrong? my DatText field when it is remapped is of the String type and that was the best conversion that I managed to do from String to a clob but I still have problems, any idea how I can solve this? Thank you.
I know this is very old, but as I just came by:
I solved this issue by simply skipping the descriptors and using:
cst.setArray(i, ((OracleConnection) connection).createOracleArray("TY_TABLE_DATA", shiftArrayOneUp(new Object[]{d.getDatId(),
d.getDatCode(),
d.getDatText()}));
shiftArrayOneUp is just adding one empty value at the beginning (oracle array starts at 1, not at 0)
private Object[] shiftArrayOneUp(Object[] values) {
Object[] result = new Object[values.length + 1];
System.arraycopy(values, 0, result, 1, values.length);
return result;
}
As I had to adjust my code accordingly, I did not test what I was writing here.
Maybe some small adjustments need to be done
For my project i try to get all foreign key in my table using DatabaseMetada Object form jdbc but when i execute the following code the result set is always empty even if my table contain foreign key ?
ResultSet v_resultPrimaryKey = p_metadata.getImportedKeys(null, Tools.getDBName(), "bookmarks_tags");
if (v_resultPrimaryKey.next()) {
System.out.println("test");
v_resultPrimaryKey.beforeFirst();
v_resultPrimaryKey.beforeFirst();
while (v_resultPrimaryKey.next()) {
if (p_att.equals(v_resultPrimaryKey.getString("FKCOLUMN_NAME"))) {
v_fk = v_resultPrimaryKey.getString("PKTABLE_NAME") + "."
+ v_resultPrimaryKey.getString("PKCOLUMN_NAME");
v_fkName = v_resultPrimaryKey.getString("FK_NAME");
}
}
if(!v_fk.equals("")){
v_foreignKey = new ForeignKey(v_fkName, v_fk);
}
}
stumbled upon this and this may help in case anyone may see it
DatabaseMetaData p_metadata= connection.getMetaData();
ResultSet v_resultPrimaryKey = p_metadata.getImportedKeys(null, Tools.getDBName(), "bookmarks_tags");
if (v_resultPrimaryKey.next()) {
System.out.println("test");
v_resultPrimaryKey.beforeFirst();
v_resultPrimaryKey.beforeFirst();
while (v_resultPrimaryKey.next()) {
if (p_att.equals(v_resultPrimaryKey.getString("FKCOLUMN_NAME"))) {
String v_fk = v_resultPrimaryKey.getString("PKTABLE_NAME") + "."
+ v_resultPrimaryKey.getString("PKCOLUMN_NAME");
String v_fkName = v_resultPrimaryKey.getString("FK_NAME");
}
}
if(!v_fk.equals("")){
v_foreignKey = new ForeignKey(v_fkName, v_fk);
}
}
I'm using CachedRowSet. But when I call the insertRow() method, there is a SQLException failed to insert row.
Here is my code:
static final String DATABASE_URL = "jdbc:mysql://localhost:3306/javapos";
static final String USERNAME = "root";
static final String PASSWORD = "sbc";
public static void main (String [] agr) throws SQLException
{
CachedRowSetImpl rs = new CachedRowSetImpl();
rs.setUrl(DATABASE_URL);
rs.setUsername(USERNAME);
rs.setPassword(PASSWORD);
rs.setCommand("select * from uom order by itemid");
rs.execute();
while(rs.next()){
System.out.println(rs.getString("itemid") + " - " + rs.getString("uom"));
}
rs.moveToInsertRow();
rs.updateString(2,"Sample code");
rs.insertRow();
rs.moveToCurrentRow();
rs.acceptChanges();
}
When you call insertRow(), the Reference Implementation of CachedRowSet performs a check if all required columns have been populated and otherwise it throws an exception (source from Grepcode CachedRowSet.insertRow(), line numbers don't exactly match):
if (onInsertRow == false ||
insertRow.isCompleteRow(RowSetMD) == false) {
throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString());
}
The check is performed in InsertRow.isCompleteRow(RowSetMetaData):
public boolean isCompleteRow(RowSetMetaData RowSetMD) throws SQLException {
for (int i = 0; i < cols; i++) {
if (colsInserted.get(i) == false &&
RowSetMD.isNullable(i + 1) == ResultSetMetaData.columnNoNulls) {
return false;
}
}
return true;
}
In other words, when inserting a row you must provide a value for all columns that are not nullable (this includes the primary key). There seem to be two ways to work around this:
Setting a (random) value. This does require that your primary key is always generated (even if a value is provided).
Explicitly setting the column to null using updateNull. Using setNull doesn't work: it provides the same error, and using setObject(idx, null) results in a NullPointerException
When using your code with these changes I get an SQLException when calling acceptChanges as the implementation doesn't disable autoCommit (it seems to have been commented out), but it does explicitly call commit (which is invalid when in autoCommit). This doesn't seem to be easy to solve, except maybe explicitly providing a connection on execute, or creating your own implementation.
I think these kind of issues actually demonstrate how little the RowSet implementations are actually used (otherwise they would already have been flushed out long ago).
Note however that if this were the actual code you needed and don't need the disconnected characteristics of the CachedRowSet, then you could simply use an updatable result set.
Example:
beginAddRow(crs);
crs.updateString("TABLE_TYPE", "TABLE");
continueAddRow();
crs.updateString("TABLE_TYPE", "INDEX");
endAddRow();
static public CachedRowSet beginAddRow(CachedRowSet crs) throws SQLException {
crs.moveToInsertRow(); // onInsertRow = true
return crs;
}
static public CachedRowSet continueAddRow(CachedRowSet crs) throws SQLException {
crs.insertRow();
crs.moveToCurrentRow();
crs.moveToInsertRow();
return crs;
}
static public CachedRowSet endAddRow(CachedRowSet crs) throws SQLException {
crs.insertRow();
crs.moveToCurrentRow(); // onInsertRow = false;
crs.beforeFirst();
return crs;
}
I am trying to insert into Cassandra database using Datastax Java driver. But everytime I am getting below exception at prBatchInsert.bind line-
com.datastax.driver.core.exceptions.InvalidTypeException: Invalid type for value 1 of CQL type text, expecting class java.lang.String but class [Ljava.lang.Object; provided
Below is my method which accepts userId as the input and attributes as the Map which contains key as my Column Name and value as the actual value of that column
public void upsertAttributes(final String userId, final Map<String, String> attributes, final String columnFamily) {
try {
Set<String> keys = attributes.keySet();
StringBuilder sqlPart1 = new StringBuilder(); //StringBuilder.append() is faster than concatenating Strings in a loop
StringBuilder sqlPart2 = new StringBuilder();
sqlPart1.append("INSERT INTO " + columnFamily + "(USER_ID ");
sqlPart2.append(") VALUES ( ?");
for (String k : keys) {
sqlPart1.append(", "+k); //append each key
sqlPart2.append(", ?"); //append an unknown value for each key
}
sqlPart2.append(") "); //Last parenthesis (and space?)
String sql = sqlPart1.toString()+sqlPart2.toString();
CassandraDatastaxConnection.getInstance();
PreparedStatement prBatchInsert = CassandraDatastaxConnection.getSession().prepare(sql);
prBatchInsert.setConsistencyLevel(ConsistencyLevel.ONE);
// this line is giving me an exception
BoundStatement query = prBatchInsert.bind(userId, attributes.values().toArray(new Object[attributes.size()])); //Vararg methods can take an array (might need to cast it to String[]?).
CassandraDatastaxConnection.getSession().executeAsync(query);
} catch (InvalidQueryException e) {
LOG.error("Invalid Query Exception in CassandraDatastaxClient::upsertAttributes "+e);
} catch (Exception e) {
LOG.error("Exception in CassandraDatastaxClient::upsertAttributes "+e);
}
}
What wrong I am doing here? Any thoughts?
You need to combine the userId string to the object array, because the way you are passing it now is being seen as [string, object array] and java doesn't like that.
// instead of
// BoundStatement query = prBatchInsert.bind(userId, attributes.values().toArray(new Object[attributes.size()]));
// try, first combining the uid to the map of values
Collection<Object> params = new ArrayList<Object>(attributes.size() + 1);
params.add(userId);
for(Object o : attributes.values().toArray())
params.add(o);
// then passing in the new collection as an array
BoundStatement query = prBatchInsert.bind(params.toArray());
I have executed a query using JDBC and traversing the resultset I have stored all fields in List in java.
List<String> dataList=new ArrayList<String>();
while(res.next())
{
dataList.add(res.getString(1));
dataList.add(res.getString(2));
dataList.add(res.getString(3));
dataList.add(res.getString(4));
dataList.add(res.getString(5));
dataList.add(res.getString(6));
dataList.add(res.getString(7));
}
Iterator<String> it= dataList.iterator();
As I have added directly into list so how can I get this 7 fields while traversing the iterator.
Means:
while(it.hasNext())
{
String f1=it.next();
}
Like wise everytime I want 7 fields at a time
and next 7, next 7....... so on
Using this while loop how can I get those 7 fields (one row in table having 7 field) at a time.
I get little bit confuse here. Please help me.
Thanks
What you want to do is actually create another object that stores all seven of the values.
Then create a list of these entries so that you can access one row at a time, which is what I think you are asking.
First create a class for the row.
private static class Entry {
String[] row;
public Entry ( ResultSet r ) {
row = new String [ 7 ];
for (int i = 1; i <= 7; i++) {
row[i] = r.getString(i);
}
}
}
Using that, you can then create a list of Entry objects.
List<Entry> entryList = new ArrayList <Entry> ();
while(res.next())
{
entryList.add ( new Entry ( res ) );
}
Then, you can go ahead and loop through entryList and get any specific entry you would want.
Of course, if you have specific values, it might be wise to create instance variables of type String for Entry rather than an array of Strings.
By that I mean you could do this:
private static class Entry {
String column1; // rather than name column1 use what the column semantically represents
String column2;
// ...
public Entry ( ResultSet r ) {
column1 = r.getString(1);
// ...
}
This way, you can also calls like r.getInt(i) for certain columns which have an different type other than String.
Good luck!
I think your List declaration should be
List<Any DAO Object> instead of List<String>
While fetching from resultset, create a DAO object, add all fetched data into that object and then add that object into the list.
Then you can iterate and get each DAO object at each iteration.
You can use DatabaseMetaData class,
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost/testdb";
private static final String USERNAME = "root";
private static final String PASSWORD = "";
public static void main(String[] args) throws Exception {
Class.forName(DRIVER);
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
DatabaseMetaData metadata = connection.getMetaData();
ResultSet resultSet = metadata.getColumns(null, null, "users", null);
while (resultSet.next()) {
String name = resultSet.getString("COLUMN_NAME");
String type = resultSet.getString("TYPE_NAME");
int size = resultSet.getInt("COLUMN_SIZE");
System.out.println("Column name: [" + name + "]; type: [" + type + "]; size: [" + size + "]");
}
connection.close();
}