1

Trying to first make sure this part of my project is working before implementing it into a GUI.

Trying to first create a new table in the data base called n012345_Accounts with 4 columns:

  • Account Number
  • Name
  • Balance
  • Lock

Then I want to populate the data of this table by reading the lines of the file I have created with in Accounts.txt which includes the following

Number Name Balance Locked

1001 Isabel_Newton 2000 yes
1002 Blake_Wool 1500 yes 
1003 Martha_Curie 3000 no
1004 Nortom_Eef 1500 no
1009 Dan_Heckler 2000 yes
1010 Timothy_Wicket 4000 no
1011 Jane_Doe 5000 no

The purpose of this is to practice my understanding of using PreparedStatements and transactions. If anyone can see what the error is that is not allowing the creation of the table I would appreciate the input.

Currently when running my project the console returns

unable to create new table for accounts

//Create a GUI application for a bank
//it should manage fund transfers from one account to another

//1
//Start
//@ the start up it should create a table name YourStudentNumber_Accounts ( n012345)
//it should also populate this table with the information stored in the file provided ("Accounts.txt")

//2
//Then the application will ask for
    //account number the funds are to be transferred from
    //amount to be transferred
    //account number funds are to be transferred to

//3
//Upon exit the application will present the contents of the Accounts table in standard output

//USE PREPARED STATEMENTS and TRANSACTIONS wherever appropriate
//All exceptions must be handled

import oracle.jdbc.pool.OracleDataSource;

import java.io.*;
import java.sql.*;

public class Main {

    public static void main(String[] args) throws SQLException{
        OracleDataSource ods = new OracleDataSource();
        ods.setURL("jdbc:oracle:thin:n012345/luckyone@calvin.humber.ca:1521:grok");

        //try to connect to the database connection we have declared
        try(Connection con = ods.getConnection()) {

                //create a statement object
                try (Statement stmt = con.createStatement()) {
                    try (ResultSet rs = stmt.executeQuery("CREATE TABLE n012345_Accounts (AccountNumber float(4) , Name varchar(25), Balance float(9), Lock varchar(25))")) {

                        try (BufferedReader reader = new BufferedReader(new FileReader("Accounts.txt"));) {
                            String line;
                            //do not automatically commit statements
                            con.setAutoCommit(false);
                            while ((line = reader.readLine()) != null) {
                                //inputting data into a String array splitting data by the space between the items in the file
                                String[] fields = line.split(" ");
                                String queryString = "INSERT INTO n012345_Accounts (AccountNumber, Name, Balance, Lock) VALUES(?,?,?,?)";
                                try (PreparedStatement statement = con.prepareStatement(queryString);) {
                                    statement.setFloat(1, Float.parseFloat(fields[0]));
                                    statement.setString(2, fields[1]);
                                    statement.setFloat(3, Float.parseFloat(fields[2]));
                                    statement.setString(4, fields[3]);
                                    statement.executeUpdate();
                                } catch (Exception e) {
                                    System.out.println("There was an error inserting into the database.");
                                }
                                System.out.println("Accounts.txt data was populated into the table n01494108_Accounts");
                            }
                        } catch (Exception e) {
                            System.out.println("unable to read the file.");
                        }
                        con.commit();
                    } catch (SQLException ex) {
                        System.out.println("unable to create new table for accounts");
                    }
                    //closes the statement

                } catch (Exception e) {
                    //using rollback() to ensure no statements in a transaction are committed if an exception error occurs
                    con.rollback();
                }
            }catch (SQLException ex){
                //closes connection
            }

    } //closes main method
} // closes main class
Abra
  • 19,142
  • 7
  • 29
  • 41
DevSteph
  • 43
  • 4
  • 1
    Don't catch exceptions like that -- you are either hiding the fact that the exception happens at all with your last `catch`, or losing the details of the error, when you just print a message. Try-with-resources does *not* need a catch -- just let the exception be thrown by `main` and learn to read what it says. – tgdavies Dec 15 '22 at 23:53
  • I don't see any obvious coding error, have verify that the user has permissions to create tables and have you executed the create table command directly from the Oracle SQL command line? – MZM Dec 16 '22 at 00:35
  • @tgdavies I know how to read thanks for that, just as i said our teacher wants us to get familiar with try catch so if I am using them incorrectly i am all ears but being rude is not needed – DevSteph Dec 16 '22 at 01:14
  • @MZM I have used this exact url and connected prior to my database and created a table so that is why I am confused as to what is not working now. I tried what someone suggested below and changed it to just execute() instead of executeQuery() but that resulted in more errors as I tried to adjust my code accordingly but now I am lost. As what I have written above follows my lecture instructions and any documentation or projects I've done prior. – DevSteph Dec 16 '22 at 01:16
  • @DevSteph not trying to be rude. Reading exceptions and stack traces is a skill which takes time to acquire. – tgdavies Dec 16 '22 at 01:26
  • @tgdavies oh okay thank you, so used to members being volatile on here. I am definitely trying to learn reading errors better. And don't want to over use the try catch. Do you have any more suggestion as to how to implement it better? Like should I always be pass the error into a method so I still see it if I am going to use try catch then? like before I have used catch( SQL Exception ex) { System.out.println(ex); } Is that better practise? – DevSteph Dec 16 '22 at 01:31
  • Very briefly there are four ways to handle an exception: 1. Don't catch it at all, let the caller handle it. If it's a checked exception, you declare that youe method throws it, and it becomes part of your API, if it's unchecked, then your program will terminate (which, if it's a fatal problem like a null pointer, or a syntax error in your SQL, is exactly what you want) – tgdavies Dec 16 '22 at 01:46
  • 2. Wrap it in another exception and rethrow it. For example, if you get a checked exception in your function, which should be fatal (something the caller cannot do anything about), then you should wrap the exception in an unchecked exception and throw that. When you wrap an exception *always* pass the original exception as the `cause` of the new exception. – tgdavies Dec 16 '22 at 01:47
  • 3. Log it and continue. If you are processing a series of records, then an error processing one doesn't have to prevent you processing the others. Use `exception.printStackTrace()` to report the exception. 4. Log it and do something different. You might catch a `NumberFormatException` and use a default value instead, for instance. – tgdavies Dec 16 '22 at 01:47
  • Oracle known for certain peculiarities/strict idiom that must be follow (don't know if this will fix it, but when all fails, go to the basics) - First, specify the table name and schema name to which the new table belongs on the CREATE TABLE clause. https://www.oracletutorial.com/oracle-basics/oracle-create-table/ – MZM Dec 16 '22 at 02:27
  • @tgdavies that explanation was really helpful thank you so much! – DevSteph Dec 16 '22 at 02:48
  • @MZM ill check that out thank you, I think that is part of my error as vini below has helped me in a chat with the issue of using they name "Lock" in my table column as it is a keyword but still encountering other errors, I have since fixed my try catch statements though and now they are showing actual errors so I have a better idea of what is going on thank you both! – DevSteph Dec 16 '22 at 02:50

2 Answers2

1

Use execute instead of executeQuery when you are trying to create a table.

Vini
  • 8,299
  • 11
  • 37
  • 49
  • Okay thank you but do you mind reminding me what I need to change then for the type like instead of ResultSet – DevSteph Dec 15 '22 at 23:48
  • `execute` returns a boolean value indicating if the first result is a `ResultSet` or not. Quoting the documentation "true if the first result is a ResultSet object; false if it is an update count or there are no results" – Vini Dec 15 '22 at 23:54
  • Having said that, your code is not using the`ResultSet` anyways, so you can as well remove it. – Vini Dec 15 '22 at 23:59
  • okay, well can you expand then please as when I change it to execute it give me an incompatible types found error – DevSteph Dec 15 '22 at 23:59
  • Okay I did try removing it but ended up with a bunch of errors in my try catches and when reformatting it got more issues, I thought most of my logic was correct so if you can give more insight as to the proper execution it would be greatly apprecaited – DevSteph Dec 16 '22 at 00:00
  • can you share the details of errors/exceptions you are getting? – Vini Dec 16 '22 at 00:01
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/250450/discussion-between-vini-and-devsteph). – Vini Dec 16 '22 at 00:03
  • 1
    Issue ended up coming down to hiding errors through try catch that indicated a type issue as my accounts.txt file contained the column names at the top throwing off my intention of populating the data correctly to the table. Thanks everyone! I really understand more of what I didn't know I didn't understand before XD – DevSteph Dec 16 '22 at 03:02
0

Your code is printing unable to create new table for accounts because database table N012345_ACCOUNTS already exists. Once you create a database table, you can't re-create it. Hence the very first time you run your code – assuming that the database table does not exist – the database table will be successfully created however the next time you run your code, you will get unable to create new table for accounts – unless you drop the table before running your code again. By the way, I recommend printing the stack trace in catch blocks rather than just some error message alone.

You can use DatabaseMetaData to check whether the database table already exists and create it if it doesn't.

After creating the database table, your next task is to populate it. I recommend using batching.

You populate the database table with data that you read from a text file. You need to verify the data read from the text file. According to the sample text file contents in your question, you need to ignore the first two lines of the file.

The below code uses text blocks, NIO.2, try-with-resources and multi-catch.

import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Main {

    private static void createTable(Connection conn) throws SQLException {
        String sql = """
create table N012345_ACCOUNTS (
  ACCOUNT_NUMBER   number(4)
 ,ACCOUNT_NAME     varchar2(30)
 ,ACCOUNT_BALANCE  number(14,2)
 ,ACCOUNT_LOCKED   varchar2(3)
 ,constraint ACCT_PK primary key (ACCOUNT_NUMBER)
 ,constraint ACCT_LOCKS check (ACCOUNT_LOCKED in ('no','yes'))
)
                """;
        try (Statement s = conn.createStatement()) {
            s.executeUpdate(sql);
            System.out.println("Database table N012345_ACCOUNTS created.");
        }
    }

    private static void populateTable(Connection conn) throws IOException, SQLException {
        String sql = "insert into N012345_ACCOUNTS values (?, ?, ?, ?)";
        Path path = Paths.get("accounts.txt");
        try (BufferedReader br = Files.newBufferedReader(path);
             PreparedStatement ps = conn.prepareStatement(sql)) {
            String line = br.readLine();
            conn.setAutoCommit(false);
            while (line != null) {
                String[] fields = line.split(" ");
                if (fields.length == 4) {
                    try {
                        BigDecimal number = new BigDecimal(fields[0]);
                        String name = fields[1];
                        BigDecimal balance = new BigDecimal(fields[2]);
                        String locked = fields[3];
                        ps.setBigDecimal(1, number);
                        ps.setString(2, name);
                        ps.setBigDecimal(3, balance);
                        ps.setString(4, locked);
                        ps.addBatch();
                    }
                    catch (NumberFormatException xNumberFormat) {
                        // Ignore.
                    }
                }
                line = br.readLine();
            }
            int[] results = ps.executeBatch();
            int success = 0;
            for (int result : results) {
                if (result == 1) {
                    success++;
                }
            }
            System.out.printf("Inserted %d rows.%n", success);
            if (success == results.length) {
                conn.commit();
            }
            else {
                conn.rollback();
            }
        }
    }

    public static void main(String[] args) {
        String url = "jdbc:oracle:thin:n012345/luckyone@calvin.humber.ca:1521:grok";
        try (Connection conn = DriverManager.getConnection(url)) {
            DatabaseMetaData dbmd = conn.getMetaData();
            ResultSet rs = dbmd.getTables(null, null, "N012345_ACCOUNTS", null);
            if (!rs.next()) {
                createTable(conn);
            }
            else {
                System.out.println("Database table N012345_ACCOUNTS already exists.");
            }
            populateTable(conn);
        }
        catch (IOException | SQLException x) {
            x.printStackTrace();
        }
    }
}

Refer to the following (in no particular order):

Abra
  • 19,142
  • 7
  • 29
  • 41