I am trying to create Oracle SQL scripts for creating/replacing several views by using information acquired from the data dictionary.
I already managed to set up a working database connection via JDBC drivers and a query to the data dictionary, which works as well and returns the correct values.
However upon storing the queried information in a String array - which is then added to an ArrayList of String[] - something seems to go wrong, as all arrays seem to have the same values in their respective index positions and I don't have a clue why that is.
Here's my code, I'd appreciate if someone can spot the error:
public ArrayList<String[]> getDataDictionary(ArrayList<String> dbInfo, String table) throws SQLException {
ArrayList<String[]> result = new ArrayList<String[]>();
String[] resultTemp = new String[2];
... connection variables (URL, User, Pass)
... get connection, etc.
try {
Statement statement = con.createStatement();
ResultSet rs = statement.executeQuery("SELECT COLUMN_NAME,DATA_TYPE FROM USER_TAB_COLUMNS WHERE TABLE_NAME = '" + table + "'");
while (rs.next()) {
resultTemp[0] = rs.getString("COLUMN_NAME");
resultTemp[1] = rs.getString("DATA_TYPE");
// database values
System.out.println(rs.getString("COLUMN_NAME"));
System.out.println(rs.getString("DATA_TYPE"));
// array values
System.out.println(resultTemp[0]);
System.out.println(resultTemp[1]);
//The above sout's return the proper values for each pass of the loop
//This is what feels the strangest to me. The values are correct here, but when queried later they are wrong
result.add(resultTemp);
}
String[] test = new String[2];
// sout's return wrong values now, i.e. the value returned is always the same for all arrays queried in the ArrayList
//I don't understand how that can be, because the correct values were added to the ArrayList a few lines above and now they are wrong with no changes made
test = result.get(0);
System.out.println(test[0]);
System.out.println(test[1]);
test = result.get(1);
System.out.println(test[0]);
System.out.println(test[1]);
test = result.get(2);
System.out.println(test[0]);
System.out.println(test[1]);
rs.close();
statement.close();
con.close();
return result;
} catch(Exception e)
{
e.printStackTrace();
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error!");
alert.setHeaderText("Invalid SQL!");
alert.setContentText("Please verify the information you provided!");
alert.showAndWait();
return null;
}
You should create the array instance inside the loop.
while (rs.next()) {
String[] resultTemp = new String[2];
resultTemp[0] = rs.getString("COLUMN_NAME");
resultTemp[1] = rs.getString("DATA_TYPE");
....
Failing to do so causes the same array to be added to result multiple times.
You store a reference to the same object in every loop.
You have to create in every lopp a new Array:
while (rs.next()) {
resultTemp = new String[2];
resultTemp[0] = rs.getString("COLUMN_NAME");
resultTemp[1] = rs.getString("DATA_TYPE");
// database values
System.out.println(rs.getString("COLUMN_NAME"));
System.out.println(rs.getString("DATA_TYPE"));
// array values
System.out.println(resultTemp[0]);
System.out.println(resultTemp[1]);
//The above sout's return the proper values for each pass of the loop
//This is what feels the strangest to me. The values are correct here, but when queried later they are wrong
result.add(resultTemp);
}
You are overriding the same array , String[] resultTemp = new String[2];
while (rs.next()) {
String[] resultTemp = new String[2];
resultTemp[0] = rs.getString("COLUMN_NAME");
resultTemp[1] = rs.getString("DATA_TYPE");
Intialise it inside the while loop. So that when you add
result.add(resultTemp);
result will hold the list of resultTemp[] objects inside it .
Related
How can I query data from my database and assign it to an array of strings? In this attempt I noticed I would receive an out of bounds error before I included the resultSet.next() call since it seems that ResultSet starts at 0 and is not called like a list / array (meaning you can access the contents with its index).
public String[][] retrieveNameAndLocation() {
final String table = "customers";
try {
ResultSet resultSet = statement.executeQuery(
"SELECT " +
"first_name," +
"location" +
" FROM " + table
);
resultSet.next();
final String[] names = (String[]) (resultSet.getArray(1).getArray());
final String[] location = (String[]) (resultSet.getArray(2)).getArray();
final String[][] nameAndCountry = {names, location};
resultSet.close();
return nameAndCountry;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
Anyways the above code resulted in a SQLFeatureNotSupportedException. My next attempt was to simply call the the columns by name since I noticed it was an option inside of getArray, however that also resulted in the not supported exception.
public String[][] retrieveNameAndLocation() {
final String table = "customers";
try {
ResultSet resultSet = statement.executeQuery(
"SELECT " +
"first_name," +
"location" +
" FROM " + table
);
resultSet.next();
final String[] names = (String[]) (resultSet.getArray("first_name").getArray());
final String[] location = (String[]) (resultSet.getArray("location")).getArray();
final String[][] nameAndCountry = {names, location};
resultSet.close();
return nameAndCountry;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
I am not really sure why I need to include resultSet.next() because it seems like it's just broken since why would they include an option to query columns if they forced you to loop through the indexes?
I think you misunderstand the purpose of method getArray. Some DBMSs, like Oracle, have "array" data types. Hence the getArray method – to query a database table column whose type is an array type. I have no experience with MySQL but it appears that it does not have an array type. Hence the JDBC driver for MySQL does not need to implement the getArray method and that's why you get the SQLFeatureNotSupportedException.
You need to iterate through the ResultSet and build up your array. However since you usually don't know how many rows there are in a ResultSet, I usually use a List and then, if required, convert it to an array because when you declare an array you need to know its size.
I would also define a record and declare a List of records.
(Note that below code is not compiled and not tested since I don't have your database and I can't simulate it since the code in your question is not a minimal, reproducible example.)
public record NameAndCountry(String name, String location) {
public static java.util.List<NameAndCountry> retrieveNameAndLocation() {
final String table = "customers";
try {
ResultSet resultSet = statement.executeQuery(
"SELECT " +
"first_name," +
"location" +
" FROM " + table
);
java.util.List<NameAndCountry> list = new java.util.ArrayList<>();
while (resultSet.next()) {
String name = resultSet.getString(1);
String location = resultSet.getString(2);
NameAndCountry row = new NameAndCountry(name, location);
list.add(row);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
String[] Titulo = {
"ID",
"CDEP",
"NOMDEP",
"POB"
}; //This is the head of the Jtable
Mnc2 = new DefaultTableModel(null, Titulo);
String[] Filas = new String[4];
try { //HERE IS THE CONECTION TO THE BDD(ACCESS)
Conexion_DDB Conn = new Conexion_DDB();
//Prepared Query
PreparedStatement Consulta = Conn.getConnection().prepareStatement("SELECT * FROM [DEPARTAMENTOS]");
ResultSet Resultadobm = Consulta.executeQuery();
while (Resultadobm.next()) {
//This is the part thath I don't know how to get the Strings or values for each row
Filas[0] = Resultadobm.getString("CDEPID");
Filas[1] = Resultadobm.getString("CDEP");
Filas[2] = Resultadobm.getString("POBDEP");
Filas[3] = Resultadobm.getString("NOMDEP");
//There are more records but just for example
while (Resultadobm.next()) {
//This is the part thath I don't know how to get the Strings or values for the first two rows
Mnc2.addColumn(Filas);//Add the columns
}
/*At this part, I'm trying to get the values equals or higher than 50,000 to show then in the same table at the same time with the two first records found*/
//If you can help me here too I would appreciate it a lot
int Menora = 50000;
if (Mnc2.getValueAt(1, 1).equals(Menora)) {
Tabla_Busquedas.setValueAt(Mnc2, 1, 1);
}
Conn.Desconexion(); //Close the connection
} catch (SQLException ex) {
Logger.getLogger(Form_Tabla.class.getName()).log(Level.SEVERE, null, ex);
}
}
while (Resultadobm.next()) { //This is the part thath I don't know how
to get the Strings or values for the first two rows
I am not sure I understand right.I think you can terminate the loop after you fetched first two rows:
while (Resultadobm.next() && Resultadobm.getRow() <= 2) {
// ...your code
}
You can go to the source:
"SELECT TOP 2 * FROM [DEPARTAMENTOS] ORDER BY [SomeUniqueField]");
I have 2 panels in my form which bound to a parent panel which has its layout set to card layout.
In the JFrame's constructor, a database operation is performed and data is taken and used to fill a JList.
Then when a user clicks on an item, a new panel ( as part of CardLayout ) shows up with a JTable filled with data taken from a database according to the selection made by the user in the listbox .
The program is basically a clinic management system.
In this JFrame, the cashier can see the id numbers of patients who are to pay their bills . These id numbers are displayed as a list in the JList.
On clicking the list, a patient id is selected and then the drugs prescribed are queried from the database and displayed in the table along with drug id & price.
The problem is that I get an ArrayOutOfBoundsException whenever I try to add a row to the JTable.
These are declared outside the mouseclick event (globally)
private Connection medDbConn = Connect("medicines.db");
private PreparedStatement mPst = null;
private ResultSet mRs = null;
private Connection conn = Connect("bills.db");
private PreparedStatement pst = null;
private ResultSet rs = null;
private ArrayList medicines_fine = new ArrayList();
private ArrayList medicines_fine_name = new ArrayList();
private ArrayList medicines_fine_qty = new ArrayList();
private ArrayList medicines_id = new ArrayList();
private ArrayList medicines_price = new ArrayList();
private ArrayList medicines_subtotal = new ArrayList();
private Double cf = 0.00;
/**
* Creates new form ViewBills
*/
private DefaultListModel listmodel;
private DefaultListModel model;
The following is executed in the mouseclick event of the JList .
// GET SELECTED VALUE FROM LIST
String listvalue = (String) jList1.getSelectedValue();
// SPLIT THE SELECTED LIST VALUE INTO ID AND DATETIME
String[] datas = listvalue.split("=");
// datas[0] = id and datas[1] = datetime
// STORE PATIENTID and DATETIME
String Patient_Id = datas[0].trim();
String DateTime = datas[1].trim();
String medicines_raw = null;
String[] medicines;
String[] keypair;
try {
// CONNECT THE DATABASE & PREPARE IT . THEN SET THE VALUES & FURTHER EXECUTE QUERY TO GET RESULT INTO "rs"
pst = conn.prepareStatement("SELECT CONSULTFEE,MEDICINES FROM VIEWBILLS WHERE ID=? AND DATETIME=?");
pst.setString(1, Patient_Id);
pst.setString(2, DateTime);
rs = pst.executeQuery();
// IF THERE IS A RECORD , THEN DO SOMETHING
if (rs.next()) {
cf = rs.getDouble("consultfee");
// GET THE RAW VALUE IN THE FORMAT Aspirin=12,sdsd=1,asdasd=2
medicines_raw = rs.getString("medicines");
// SPLIT THE WORD BY COMMAS AND STORE INTO ARRAY , SO EACH INDEX has Aspirin=12 kind of values
medicines = medicines_raw.split(",");
for (int i = 0; i < medicines.length; i++) {
medicines_fine.add(medicines[i]);
}
for (int i = 0; i < medicines_fine.size(); i++) {
keypair = medicines_fine.get(i).toString().split("=");
medicines_fine_name.add(keypair[0]);
System.out.println(keypair[0]);
System.out.println(keypair[1]);
medicines_fine_qty.add(keypair[1]);
}
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
CardLayout cl = (CardLayout) Parent.getLayout();
cl.show(Parent, "card3");
// SECOND DATABASE CONNECTION STARTS HERE ...
for (int i = 0; i < medicines_fine_name.size(); i++) {
try {
pst = medDbConn.prepareStatement("SELECT ID,SELLPRICE FROM MEDICINES WHERE NAME=?");
pst.setString(1, (String) medicines_fine_name.get(i));
rs = pst.executeQuery();
if (rs.next()) {
medicines_id.add(rs.getString("id"));
medicines_price.add(rs.getDouble("sellprice"));
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
for ( int i = 0; i < medicines_fine_name.size() ; i++) {
tblmodel.addRow(new Object[] {medicines_id.get(i),medicines_fine_name.get(i),medicines_price.get(i),medicines_fine_qty.get(i)});
}
}
The whole thing sometimes run without error if the last for loop is removed . ( but that beats the purpose )
And Yeah , I said "sometimes" .. I am very much confused and as you can see, this code is written in a very ugly manner. I had written it the normal way, but this ArrayIndexOutOfBoundsException made me re-write the whole code 3 time, which ended in me writing pretty bad & ugly code but with the error still hanging on.
Pls let me know if anything is still unclear
Edit1: Basically what i'm trying to do is from the selected string in jlist , separate the datetime part and id part using split() function and store them to an array . Then use this id and name to select medicines from database . "medicines" is a string containing comma separated values like Aspirin=2,Amoxylin=5,etc=2,etc=10 where =10 means 10 of them ( indicating quantity . Then the drug name is stored into an arraylist and qty into another . Then use this medicine_name to get the medicine_id and sellprice. Finally set all this into a table .
The problem is here:
for ( int i = 0; i < medicines_fine_name.size() ; i++) {
tblmodel.addRow(new Object[] {medicines_id.get(i),medicines_fine_name.get(i),medicines_price.get(i),medicines_fine_qty.get(i)});
}
You are iterating over index in arraylist where there are no elements present.
What you are doing is you are firing two queries, in first query say you got 10 records.
Now in second query you iterate over your 10 records (processed and passed in arrayList from first query result) and fire in query 10 times. You may or may not get record and you do:
if (rs.next()) {
medicines_id.add(rs.getString("id"));
medicines_price.add(rs.getDouble("sellprice"));
}
if out of 10 you get record for 5 then size of medicines_id, medicines_price arraylist would be just 5.
Now comes your final loop as above. Here in the for loop you try to iterate over medicines_id,medicines_fine_name,medicines_price,medicines_fine_qty until size of 10 as per first query (medicines_fine_name.size()).
so when your i goes to index 6, you try to get on say
medicines_id.get(6)
but this element you never populated as per your second query hence ArrayIndexOutOfBoundException.
To fix this, one way would be to use else part to populate dummy value to id and price like below:
if (rs.next()) {
medicines_id.add(rs.getString("id"));
medicines_price.add(rs.getDouble("sellprice"));
} else {
medicines_id.add(rs.getString("9999"));
medicines_price.add(rs.getDouble("10.00"));
}
I want to use a method that extracts a list of id's from my database. I managed to do so with List String but it won't work with List String[], which i really need to obtain.This is my try statement:
try {
connection = getJNDIConnection(connectionName);
pstmt = connection.prepareStatement(sqlQuery);
// set the input parameters
pstmt.setLong(1, groupId);
resultSet = pstmt.executeQuery();
if (resultSet.next()) {
result = new ArrayList<String[]>();
do {
Array resultStr = resultSet.getArray(1);
result.addAll(resultStr);//here is the problem
if (Constants.DEBUG_MODE.equals("true")) {
logger.debug("[{}] Get the customers list id from database GROUPS_CUSTOMERS table={}", methodName, result);
}
} while(resultSet.next());
}
}
Eclipse is giving me back this message : "The method addAll(Collection) in the type List is not applicable for the arguments (Array) ".
Can i try something else?
Thank you very much.
That's because Array is not an implementation of Collection interface. You can try the following:
String[] arr = (String[]) resultSet.getArray(1).getArray();
result.add(arr);
Hope the cast in the first line works. If not, you'll have to find the actual type you need to cast to by using a debugger.
private void populateJlist(){
try
{
Connection connection = newConnection.createConnection();
Statement newStat = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet res = newStat.executeQuery("SELECT AccName FROM AccList");
String data = "";
while (res.next()){
data += res.getString("AccName") + " ";
}
String acclist[] = data.split(" ");
AccountList = new JList(acclist);
newStat.close();
connection.close();
}
catch(SQLException e){
System.err.println("SQLException: " + e.getMessage());
}
}
WHAT IS SHOULD DO - The method will query the DB AccName column from AccList Table and get all account names and insert them onto a Jlist
WHAT I NEED HELP WITH - I need help implementing a Jlist which will be filled with fields from a DB column.
I tried by searching online for help and the nearest to a solution was what I manage to do above.
I learnt that there are 2 possible ways
Resultset -> Array -> Jlist
Resultset -> Vector -> Jlist
however I dont know how to do those conversions either. I would say I am a new beginner in JAVA. Any detailed help is appreciated.
As you say, using either an array or a vector would be cleaner and easier than your split solution. Personally, I would suggest the Vector. Basically, you want to create an empty vector, iterate over the result set adding each value to the vector via the Vector.add(Object o) method, then create the jlist outside the loop with the vector. Something like this (warning: untested)
Vector<String> temp = new Vector<String>();
while (res.next()) {
temp.add(res.getString("AccName"));
}
Jlist acctList = new Jlist(temp);