Dodawanie danych do tabeli.

0

Witam. Mam bazę danych, w której jest tabela samoloty:

create table samoloty (
  id_samolotu number(6,0) constraint samoloty_pk primary key,
  nazwa varchar2(20),
  typ varchar2(20),
  pojemnosc number(6,0)
); 

I chcę w programie napisanym w Javie dodać wpis do bazy. W programie mam menu i wybieram przycisk dodaj samolot i wyskakuje mi jFrame z trzema jTextami do wprowadzenia nazwy, typu i pojemności. Napisałem coś takiego do dodania tych danych:

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        String sql = " INSERT INTO samoloty VALUES (?,?,?,?)";
        String server = "localhost";
        int port = 1521;
        String database = "XE";
        String login = "HR";
        String password = "asdfghj";
        int p;
        
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            String connectionString = "jdbc:oracle:thin:@" + server + ":" + port + ":" + "XE";
            Connection con = DriverManager.getConnection(connectionString, login, password);
            PreparedStatement cs = null;
            p = Integer.parseInt(jTextField3.getText());
            
            cs.setInt(1, 0);
            cs.setString(2, jTextField1.getText());
            cs.setString(3, jTextField2.getText());
            cs.setInt(4, p);
 
            cs.executeUpdate();
            cs.close();
            con.close();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e);
        }
    } 

Jednak po wypełnieniu pól i kliknięciu dodaj powyższa metoda wywala błąd: NULLPointerException.
Mam pytanie czy powyższa metoda jest dobra? Powinna mi dodać wpisy do tabeli?
Czy jeśli w tabeli mam np. zmienne typu number a jText przyjmuje Stringi to muszę tak jak powyżej

 p = Integer.parseInt(jTextField3.getText()); 

konwertować typ String na int aby do tabeli wprowadzić daną za number?

1
int id = Integer.parseInt(jTextField1.getText());
        int employess_id = Integer.parseInt(jTextField2.getText());
        // String departments_id= String.valueOf(jComboBox1.getSelectedItem());

        String departments_name = String.valueOf(jComboBox1.getSelectedItem());


        String driver = "oracle.jdbc.driver.OracleDriver";
        String serverName = "localhost";
        String portNumber = "1521";
        String sid = "XE";
        String url = "jdbc:oracle:thin:@" + serverName + ":" + portNumber + ":" + sid;
        String pass = "xxx";
        String user = "xxx";
        String sql = "INSERT INTO time_work(id, employess_id, departments_name) VALUES (?,?,?)";

        try {
            Class.forName(driver);
            Connection con = DriverManager.getConnection(url, user, pass);
            PreparedStatement cs = con.prepareStatement(sql);
           
            cs.setInt(1, id);
            cs.setInt(2, employess_id);
            cs.setString(3, departments_name);
         
    
            cs.executeUpdate();
            cs.close();
            con.close();

        } catch (Exception e1) {
            JOptionPane.showMessageDialog(null, e1.getMessage());
        }

ten przykład powinien pomoc

0

Mam jeszcze pytanie. Dodam sobie np. wpis w tabeli o id 1. A potem usunę go przez SQL Developer z tabeli za pomocą delete from samoloty. To potem gdy wywołam select *from samoloty tabela faktycznie jest pusta. Jednak gdy znów odpalę program i chcę dodać wpis o id 1 to program się zawiesza i nic nie robi. Pomaga dopiero usunięcie tabeli drop table samoloty i utworzenie jej znowu za pomocą create.

0

String sql = "INSERT INTO time_work(employess_id, departments_name) VALUES (?,?)";

        cs.setInt(1, employess_id);
        cs.setString(2, departments_name);

Id - doda się automagicznie.

0

Zmieniłem na takie coś:

String sql = " INSERT INTO samoloty(nazwa, typ, pojemnosc) VALUES (?,?,?)";
int p = Integer.parseInt(jTextField3.getText());

        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            String connectionString = "jdbc:oracle:thin:@" + server + ":" + port + ":" + database;
            Connection con = DriverManager.getConnection(connectionString, login, password);
            PreparedStatement cs = con.prepareStatement(sql);
            
            cs.setString(1, jTextField1.getText());
            cs.setString(2, jTextField2.getText());
            cs.setInt(3, p);
            JOptionPane.showMessageDialog(null, "Wpis został dodany");
            cs.executeUpdate();
            cs.close();
            con.close();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e);
        } 

Niestety wywala błąd: cannon insert NULL into (HR, samoloty ID_Samolotu).
Czyli jednak nie dodaje się samo.;/

0

Spróbowałem dodać sekwencje do tabeli, ale nie chce utworzyć tabeli, gdzie zrobiłem błąd?

create sequence id_sam;
create table samoloty (
  id_samolotu number(6,0) default nextval('id_sam') constraint samoloty_pk primary key,
  nazwa varchar2(20),
  typ varchar2(20),
  pojemnosc number(6,0)
); 
1
CREATE SEQUENCE SEQUENCE_
START WITH 1
INCREMENT BY 1;
 DROP SEQUENCE xxxx.SEQUENCE_

DROP TRIGGER SEQUENCE_trigger


CREATE OR REPLACE TRIGGER SEQUENCE_trigger
BEFORE INSERT
ON nazwa_tab
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT SEQUENCE_.nextval INTO :NEW.id FROM dual;
END;
/
show err

może to pomoże

0

Nie będę zakładał nowego tematu, ale teraz mam problem z usunięciem. Mam tabele jTable, która mi wyświetla wszystkie dane znajdujące się w bazię i chcę usunąć jeden wiersz z tej tabeli. Chciałem to zrobić tak, że zaznaczamy kursorem wiersz w tej tabeli i klikamy przycisk usuń. Napisałem coś takiego:

    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
        jTable1.getSelectedRow();
        String server = "localhost";
        int port = 1521;
        String database = "XE";
        String login = "HR";
        String password = "asdfghj";
        
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            String connectionString = "jdbc:oracle:thin:@" + server + ":" + port + ":" + database;
            Connection con = DriverManager.getConnection(connectionString, login, password);
            Statement cs = con.createStatement(
                ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_UPDATABLE);
            
            ResultSet dane = cs.executeQuery("Select * from samoloty");
            
            if (dane.getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
                System.out.println("ResultSet non-updatable.");
            } else {
                System.out.println("ResultSet updatable.");
            }
            dane.moveToCurrentRow();
            dane.deleteRow();
            cs.close();
            con.close();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e);
        }
    } 

Jednak nie chce mi usunąć i dostaję: ResultSet non-updatable. Co zrobić aby usunąć ten wiersz?

1

przykład :

Class.forName(driver);
Connection con = DriverManager.getConnection(url, user, pass);
String dane = "DELETE FROM samoloty WHERE id = ?"; 

DELETE = con.prepareStatement(dane);

DELETE.setInt(1, id);
DELETE.executeUpdate();

DELETE.close();

warto sobie utworzyć klasę za pomocą której będziesz wywoływał obiekt połączenia.

0
String dane = cs.executeQuery("DELETE FROM samoloty WHERE id = ?"); 

Nie może być typu String. Zgłasza mi, że ma być ResultSet.

Poza tym mój kod jest wzorowany na tym: http://www.roseindia.net/tutorial/java/jdbc/jdbcresultset/jdbcresultsetdeleterow.html
Wydaje mi się, że powinno działać.

1

a bez tego cs.executeQuery ...

lub użyj własnie tego obiektu *ResultSet *, jak w przykładzie :

Statement stmt = connection.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE,  ResultSet.CONCUR_UPDATABLE);
          
ResultSet rs = stmt.executeQuery("SELECT * from user");
   while(rs.next()){
        if(rs.getInt(1)==1){
          rs.deleteRow();
                System.out.println("Deleted user_id :" + rs.getInt(1));
        }
         else{
            System.out.println("user_id :" + rs.getInt(1));
       }
   }
   
0

Coś nie tak jest wydaje mi się z dostępem do bazy. Bo wyskakuje to: ResultSet non-updatable. I dlatego chyba nie mogę wykonać żadnych operacji na bazie.

1

brakuje wybrania wiersza , można to zrobić:
najpierw wybierz wiersz, a potem usuń :

private void jTable1MousePressed(java.awt.event.MouseEvent evt) {

  int rec = jTable1.getSelectedRow();
  jTextField1.setText(jTable1.getValueAt(rec, 0).toString());
  jComboBox1.setSelectedItem((jTable1.getValueAt(rec, 4).toString()));
// ...
}
0

Dobra zrobiłem coś takiego tylko, że na konkretnym id, bo z tym zaznaczaniem jeszcze sobie nie poradziłem. Jak pobrać ten indeks i wstawić w zapytanie?

    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        int rec = jTable1.getSelectedRow();
        String server = "localhost";
        int port = 1521;
        String database = "XE";
        String login = "HR";
        String password = "asdfghj";
        
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            String connectionString = "jdbc:oracle:thin:@" + server + ":" + port + ":" + database;
            Connection con = DriverManager.getConnection(connectionString, login, password);
            Statement sta = con.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE,  ResultSet.CONCUR_UPDATABLE);
            String sql = "delete FROM samoloty where id_samolotu = 98";
            int delete_rows = sta.executeUpdate(sql);
            JOptionPane.showMessageDialog(null, delete_rows);
            sta.close();
            con.close();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e);
        }
    } 

Jeszcze mam problem z metodą, która ma mi po dodaniu odświeżać listę samolotów, Mianowicie gdy jej użyję a mam w bazie 2 wpisy to po ponownym jej użyciu te wpisy się dublują itd. Ilekroć jej użyję to tak jakby się nie czyściła tylko powielała wpisy w tabeli.
Np. Mam wpisy w tabeli o id 13 i 14 użyję tej metody to mam 13, 14, 13, 14 kolejny raz to znów mam 13, 14, 13, 14, 13, 14 i tak za każdym razem. Wydaje mi się, że na początku czyszczę całą tabelę.

    private void wyswietlSamoloty() {
        
        ResultSet dane = baza.getData("Select * from samoloty");
        Vector<Vector> tab = new Vector<Vector>();
        jTable1.selectAll();
        jTable1.clearSelection();
        try {
            while (dane.next()) {
                Vector<String> row = new Vector<String>();
                row.addElement("" + dane.getInt(1));
                row.addElement("" + dane.getString(2));
                row.addElement("" + dane.getString(3));
                row.addElement("" + dane.getInt(4));
                tab.addElement(row);
                
                ((DefaultTableModel)jTable1.getModel()).addRow(row);
            }
            dane.close();
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(null, "Błąd pobierania rekordu");
            e.printStackTrace();
        }
        jTable1.repaint();
    } 
1

musisz utworzyć model a potem go wyzerować removeRow

 int ile = Model.getRowCount();
 for (int i = ile - 1; i >= 0; i--) {
   Model.removeRow(i);
 }

Metoda, która porusza się po zbiorze rekordów to: next .

while (rs.next()) {
Object[] objects = new Object[colNo];
for (int i = 0; i < colNo; i++) {
objects[i] = rs.getString(i + 1);

}

która dodaje nowe wiersze do modelu. Poinformowanie JTable1, że dane się zmieniły przez uzycie: Model.fireTableDataChanged();

poczytaj :

http://docs.oracle.com/javase/tutorial/uiswing/start/compile.html

niżej NEXT

0
    private void wyswietlSamoloty() {
        
        ResultSet dane = baza.getData("Select * from samoloty");
        Vector<Vector> tab = new Vector<Vector>();
        jTable1.selectAll();
        jTable1.removeAll();
        try {
            while (dane.next()) {
                Vector<String> row = new Vector<String>();
                row.addElement("" + dane.getInt(1));
                row.addElement("" + dane.getString(2));
                row.addElement("" + dane.getString(3));
                row.addElement("" + dane.getInt(4));
                tab.addElement(row);
                
                ((DefaultTableModel)jTable1.getModel()).addRow(row);
            }
            dane.close();
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(null, "Błąd pobierania rekordu");
            e.printStackTrace();
        }
        jTable1.repaint();
    } 

A tak nie można? Przecież biorę jTable1.selectAll(); i faktycznie zaznacza wszystko, ale nie usuwa. Przecież jTable1.removeAll(); powinno usunąć całą zawartość tabeli.

1
   private void jButton7ActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here:
     
        String driver = "oracle.jdbc.driver.OracleDriver";
        String serverName = "localhost";
        String portNumber = "1521";
        String sid = "xe";
        String url = "jdbc:oracle:thin:@" + serverName + ":" + portNumber + ":" + sid;
        String pass = "xxx";
        String user = "xxx";

        int id = Integer.parseInt(jTextField1.getText());

        try {
            Class.forName(driver);
            Connection con = DriverManager.getConnection(url, user, pass);
            String DELETEString = "DELETE FROM nazwa_tab WHERE id = ?";
            PreparedStatement DELETE = con.prepareStatement(DELETEString);
            DELETE.setInt(1, id);
            DELETE.executeUpdate();
            DELETE.close();
            con.close();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e.getMessage());
        }


    }

to mi działa , sprawdź sobie dobrze

1

zdarzenie : jTableMousePressed odpowiada za pobranie wiersza

 int rec = jTable1.getSelectedRow();
 jTextField1.setText(jTable1.getValueAt(rec, 0).toString());

Prawym na tab:

EVENTS -> MOUSE -> MousePressed

0

Dzięki. Teraz po kliknięciu faktycznie pobiera odpowiednią rzecz:

    private void jTable1MousePressed(java.awt.event.MouseEvent evt) {
        int rec = jTable1.getSelectedRow();
        s = (jTable1.getValueAt(rec, 0).toString());
        JOptionPane.showMessageDialog(null, s);
    } 

Jednak usuwanie nadal nie działa. Najeżdżam na odpowiedni wiersz. Dałem nawet sobie outputa, żeby wyświetlił jaka wartość jest pobierana i faktycznie pobiera prawidłowa wartość.

To jest kod, w którym wykorzystuje tą zmienną do usunięcia:

    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {                                         

        String server = "localhost";
        int port = 1521;
        String database = "XE";
        String login = "HR";
        String password = "asdfghj";

        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            String connectionString = "jdbc:oracle:thin:@" + server + ":" + port + ":" + database;
            Connection con = DriverManager.getConnection(connectionString, login, password);
            Statement sta = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
            String sql = "delete FROM samoloty where id_samolotu = s";
            int delete_rows = sta.executeUpdate(sql);
            JOptionPane.showMessageDialog(null, delete_rows);
            sta.close();
            con.close();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e);
        }
    }   

Tą metodę mam przypisaną do przycisku usuń. Jednak po wciśnięciu usuń wyskakuje błąd syntaxerror ora-00904 "S": invalid identifier.

0
    private void odswiezSamoloty() {

        ResultSet dane = baza.getData("Select * from samoloty");
        Vector<Vector> tab = new Vector<Vector>();
        int count = jTable1.getRowCount();
        int del = 0;
        JOptionPane.showMessageDialog(null, count);
        for(int i = 0; i < count; i++) {
            ((DefaultTableModel)jTable1.getModel()).removeRow(i);
            del++;
            JOptionPane.showMessageDialog(null, "Usunieto: " + del);
        }
        try {
            while (dane.next()) {
                Vector<String> row = new Vector<String>();
                row.addElement("" + dane.getInt(1));
                row.addElement("" + dane.getString(2));
                row.addElement("" + dane.getString(3));
                row.addElement("" + dane.getInt(4));
                tab.addElement(row);
                ((DefaultTableModel) jTable1.getModel()).addRow(row);
            }
            dane.close();
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(null, "Błąd pobierania rekordu");
            e.printStackTrace();
        }
        jTable1.repaint();
    } 

Poprawiłem, ale problem jest z pętlą. Mam przykładowo 2 rekordy w tabeli a pętla wykonuje się tylko raz. Tak samo jak mam np. 3 to wykonuje się 2. Zawsze wykonuje się o ten 1 raz za mało. Sprawdzam zmienną count i np. gdy mam 2 rekordy ma ona wartość 2, jednak potem pętla z warunkiem i < count wykonuje się tylko raz dla 0 a nie dla 0 i 1. Co jest nie tak?

0

Pomoże ktoś?

1

może przykład pomoże :

		
        String driver = "oracle.jdbc.driver.OracleDriver";
        String serverName = "localhost";
        String portNumber = "1521";
        String sid = "XE";
        String url = "jdbc:oracle:thin:@" + serverName + ":" + portNumber + ":" + sid;
        String pass =  "xxx";
        String user =  "xxx";
        String sql = "select t.id, kol2, kol3, kol4, kol5 from samochody "; //  order by t.id użyj gdy tab łączy się z inną 
           

        try {

            String[] tableColumnsName = {"ID ", "kol2", "kol3", "kol4", "kol5"};
            DefaultTableModel Model = (DefaultTableModel) jTable1.getModel();  // chodziło mi o ten obiekt Model 
            Model.setColumnIdentifiers(tableColumnsName);
            Class.forName(driver);
            Connection con = DriverManager.getConnection(url, user, pass);
            PreparedStatement ps = con.prepareStatement(sql);

            ResultSet rs = ps.executeQuery();
            ResultSetMetaData rsmd = rs.getMetaData();
            int colNo = rsmd.getColumnCount();

            int ile = Model.getRowCount(); // ilosc wierszy w Modelu , a nie tab (na Modelu sie operuje a jego wprowadźmy do jTable1  )
            for (int i = ile - 1; i >= 0; i--) { // ilość jest numerowana od 0 dlatego jest -1 
                Model.removeRow(i); // zerowanie tab , dane będą wprowadzane od początku 
            }
            jTable1.removeColumn(null);
            while (rs.next()) {
                Object[] objects = new Object[colNo]; // tablica kolumn
                for (int i = 0; i < colNo; i++) {
                    objects[i] = rs.getString(i + 1); // przejście do kolejnej dlatego +1
                }
                Model.addRow(objects); // tu dodajemy do Modelu 
                Model.fireTableDataChanged(); 
            }


            ps.close();
            con.close();
            jTable1.setModel(Model); // wprowadzenie obiektu Model do tabelki  jTable1 

        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e.getMessage());
   
        }

wypadało, aby była klasa która tworzy połączenie , a jej obiekt w przycisku wywołujesz.

0

Chodzi Ci o tworzenie połączenia? To zaraz po logowaniu nawiązywane jest połączenie. W klasie Baza Danych mam:

    public void connect(String server, int port) {

        String database = "XE";

        String login = "HR";

        String password = "asdfghj";

        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");

            String connectionString = "jdbc:oracle:thin:@" + server + ":" + port + ":" + database;
            con = DriverManager.getConnection(connectionString, login, password);

            if (con != null) {
                connected = true;
            }

        } catch (SQLException s) {
            System.out.println("Blad sql " + s.getErrorCode() + "" + s.getSQLState());
        } catch (Exception e1) {
            System.out.println("Blad:" + e1);
        }
    } 

Obiekt tej klasy jest tworzony w klasie zarządzanie zaraz po zalogowaniu. Czyli niepotrzebnie w każdej metodzie używam tego?

                Class.forName("oracle.jdbc.driver.OracleDriver");
                String connectionString = "jdbc:oracle:thin:@" + server + ":" + port + ":" + database;
                Connection con = DriverManager.getConnection(connectionString, login, password); 

i potem się rozłączam con.close.

Tylko jak to zrobić? Przekazywać do każdej klasy obiekt Connection z połączeniem? Tylko właśnie nie wiem czy robię to dobrze. Jeśli mam np. klasę JFrame odpowiedzialną za dodawanie tworzy ona osobne okienko i żeby przekazać do niej jakiś obiekt muszę zrobić tak. Tutaj podam przykład z tym Connection:

W klasie Zarządzaj tworze Connection, jednak ta klasa otwiera też inne obiekty JFrame, więc muszę ten Connection przekazać w następujący sposób:

Utworzyć zmienną statyczną w klasie dodaj.

public class DodajSamolot extends javax.swing.JFrame {

    static BazaDanych bd;
    static Connection con; 

Przekazywanie w konstruktorze:

    public DodajSamolot(BazaDanych x, Connection y) {
        super("Dodawanie samolotu");
        initComponents();
        setLocationRelativeTo(null);
        pack();
        setDefaultCloseOperation(HIDE_ON_CLOSE);
        this.setSize(300, 200);
        bd = x;
        con = y;
    }

Muszę dać zmienną statyczną bo potem nie chce mi się wywołać run dla JFrame dodajSamolot:

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new DodajSamolot(bd, con).setVisible(true);
            }
        });
    }

Nie wiem czy to co robię jest zgodne z jakimikolwiek zasadami programowania, ale jak to inaczej zrobić?

1

Jednym z sposobów zmniejszenia ilości kodu i jego czytelności jest pogrupowanie go na klasy.

Proponuje np zrobienie klasy gdzie jest wykonane połączenie z baza i klasy do obsługi przycisków. W zdarzeniach jakie wykonują przyciski można wykonać wywołanie obiektu z odpowiednia metoda do obsługi przycisku. W klasie obsługi przycisku dla każdej metody wywołać obiekt połączenia. Tylko pamiętaj aby wywołać obiekt w klasie z innej klasy musi po niej dziedziczyć , czyli być widoczny dla niej . Klasa połączenie powinna być dziedziczona w klasie gdzie są metody do obsługi . To jest jedno z skromniejszych rozwiązań.

0 użytkowników online, w tym zalogowanych: 0, gości: 0