Java + Sql (NetBeans)

0

Witam. Mam problem w tworzeniu procedur w JDBC. Klikajac praw. przyc myszy na subfolderze nie mam takiej mozliwosci, zatem probowalem to zrobic manualnie wstukujac zapytanie SQL (nie wyrzuca bledu skladni):

ALTER PROCEDURE "APP"."newAccount"( IN login char(20), IN passw varchar (30))
/* RESULT( column_name column_type, ... ) */
BEGIN
	insert into USERSDATA(LOGIN,PASSWORD)
    values (login,passw);
    commit;
END;

Z tego co wiem to komunikacja w javie z SQL odbywac sie moze poprzez obiekt Statemant lub PreparedStatement lub CallableStatement. Dwoma pierwszymi metodami udalo mi wykonac zapytania w SQL. Teraz bym chcial zrobic procedure zapisana w SQL i sie do niej odwolac poprzez Call'a. Czy cos robie zle? Czy moze to wina zlego sterownika z ktorego korzystam komunikujac sie z baza danych.
korzystam ze sterownika: org.apache.derby.jdbc.ClientDriver.

Z góry dzieki za wszelką pomoc.

0

Nam lepszą propozycję. Weź zapomnij o SQL i zainteresuj się JPA. Znacznie wygodniejsze i przystępniejsze.

User user = new User(login, pass);
entityManager.getTransaction().begin();
entityManager.persist(user);
entityManager.flush(); // tu czyścisz cache, bo operacje są cachowane
entityManager.getTransaction().commit();

Od razu bardziej elegancko.

0

Bycmoze jest bardziej eleganckie, ale chyba do mojego projektu za ciezkie. Mam napisac midlet przechowujacy dane na serwerze, a tych danych nie bedzie za wiele. Wiec moze ktos ma jakies pomysly czemu nie mam mozliwosci tworzenia procedur?

0

Procedury SQL sluza do wywolywania blokow instrukcji. Na pewno w Twoim przypadku jest to wlasciwe rozwiazanie? Druga rzecz, to czy tworzysz prawidlowa deklaracje procedury? Dokumentacja Derby nie wspomina o skladni: "ALTER PROCEDURE...", w przeciwienstwie do: "CREATE PROCEDURE...". W jaki sposob probujesz odwolac sie do procedury z poziomu kodu Java?

0

CREATE tez probowalem. Chodzi o to ze w netBeansie są foldery w bazie danych (tabele, widoki i procedury). Tabele i widoki moge tworzyc dzieki IDE klikajac ppm, natomast jak klikam na folderze proceduty to mam tylko na liscie do wyboru "execute command" oraz "refresh". Nie ma create procedure. Dlatego probowalem to zrobic przez execute command wydajac polecenie CREATE ... Nie wyswietla mi bledu skladni. Dostaje informacje o pomyslnym wykonaniu komendy. W folderze nic nie dostaje nawet po zrobieniu refresh'a :-(

0

Mam jeszcze jedno pytanie. Czy mogę otworzyc polaczenie z bazą danych tworzac klase komunikujaca sie z BD, a zamknac połączenia nadpisujac metode finalize. Chodzi mi wlasciwie o to czy w pozniejszym etapie moga pojawic sie jakies bledy? Czy moge przez dluzszy czas utrzymywac połączenie z bazą danych. Bo nieciekawie wyglada to, gdy wywylujac metode z tej klasy za kazdym razem musze otwierac i zamykac polaczenie. No i jak do bazy danych trafiaja zapytania to jak wyglada synchronizacja z nia?

0

Nie wiem, czy to bedzie w stanie pomoc w Twoim przypadku, ale ponizej jest metoda tworzenia wewnetrznych procedur (stored procedure) w przypadku MySQL:

try {
    conn = DriverManager.getConnection("jdbc:mysql://host:3306/mydb", "", "");
    String storedProcedure =
            "create procedure newAccount(in login char(40) , in passwd char(40)) " +
            "begin " +
            "insert into users(login, passwd) values (login, passwd); " +
            "end";
    Statement s = conn.createStatement();
    s.executeUpdate(storedProcedure);
    CallableStatement cs = conn.prepareCall("{call newAccount(?, ?)}");
    cs.setString(1, "mylogin");
    cs.setString(2, "mypass");
    cs.execute();
} catch(SQLException sqle) {
   sqle.printStackTrace();
} finally {
    if(conn != null) {
        try {
            conn.close();
        } catch(SQLException sqle) {
            sqle.printStackTrace();
        }
    }
}

Natomiast z poziomu uslug w NetBeans wystarczy wywolac komende SQL:

DELIMITER @@
DROP PROCEDURE IF EXISTS mydb.newAccount@@
CREATE PROCEDURE mydb.newAccount(IN login CHAR(40), IN passwd CHAR(40))
BEGIN
    INSERT INTO users(login, passwd) VALUES (login, passwd);
END@@
DELIMITER ;

Procedura powinna sie wtedy pojawic na liscie procedur zadanej bazy. Reczne wywolanie:
CALL mydb.newAccount('mylogin', 'mypassword');

Michko napisał(a)

Mam jeszcze jedno pytanie. Czy mogę otworzyc polaczenie z bazą danych tworzac klase komunikujaca sie z BD, a zamknac połączenia nadpisujac metode finalize. Chodzi mi wlasciwie o to czy w pozniejszym etapie moga pojawic sie jakies bledy? Czy moge przez dluzszy czas utrzymywac połączenie z bazą danych.

Wywolanie metody protected void finalize() jest gwarantowane przez GC i odbywa sie w momencie, gdy ten stwierdzi, ze dany obiekt nie jest juz potrzebny (brak "widzialnych" referencji). Jednak sposob dzialania samego GC jest nieprzewidywalny i zalezny od implementacji JVM, wiec tak naprawde nigdy nie bedziesz mial pewnosci, czy dane polaczenie jest juz zamkniete, czy jeszcze wisi.
Lepszym wyjsciem byloby napisanie czegos w stylu menadzera polaczen z baza danych (DBConnectionManager), ktory odpowiednio sparametryzowany zarzadzalby polaczeniem (lub pula polaczen). W zaleznosci od strategii moglby trzymac polaczenie, albo zrywac je za kazdym wywolaniem zapytania SQL.

0

Michkoz (now Cfaniak):

Dzieki za odp. ale nie pomoglo z tym tworzeniem procedur.
Po wykonaniu czegos takiego:

DELIMITER @@
DROP PROCEDURE IF EXISTS APP.newAccount@@ 
CREATE PROCEDURE APP.newAccount(IN log CHAR(20), IN passwd CHAR(20))
BEGIN
    INSERT INTO USERSDATA(LOGIN, PASSWORD) VALUES (log, passwd);
END@@
DELIMITER ;

Otrzymuje ponizsze komunikaty o błędzie:

Error code -1, SQL state 42X01: Błąd składniowy: Encountered "EXISTS" at line 1, column 19.
Line 2, column 1

Error code -1, SQL state 42X01: Błąd składniowy: Encountered "BEGIN" at line 2, column 1.
Line 3, column 1
0

Witam,
wybacz, ze dopiero teraz, ale ostatnio troche zabiegany jestem. SQL ma to do siebie, ze w zaleznosci od RDBMS, jego skladnia moze sie znaczaco roznic. Podany wczesniej przyklad dotyczy MySQL. Dla Derby wyglada to z lekka inaczej. Ponizej krotki HowTo, na podstawie ogolnych inf. z dokumentacji.

Stored procedures w Derby
Tworzenie wewnetrznych procedur odbywa sie w dwoch etapach:

1. tworzenie (definiowanie) ciala procedury jako zrodlo Java
Silnik Derby wymaga, aby definicja stored procedure znajdowala sie w publicznej klasie, w publicznej statycznej metodzie, ktora nie zwraca zadnego wyniku (void), oraz ew. moze wyrzucac wyjatek java.sql.SQLException. Przyklad:

package derbysample;

import java.sql.*;

public class MyProcedures {
    public static void addAccount(String login, String password) throws SQLException {
        Connection conn = DriverManager.getConnection("jdbc:default:connection");
        PreparedStatement ps = conn.prepareStatement("INSERT INTO vir.users VALUES(?, ?)");
        ps.setString(1, login);
        ps.setString(2, password);
        ps.executeUpdate();
        ps.close();
        conn.close();
    }

    public static void getAccounts(ResultSet[] data) throws SQLException {
        Connection conn = DriverManager.getConnection("jdbc:default:connection");
        Statement s = conn.createStatement();
        data[0] = s.executeQuery("SELECT * FROM vir.users");
        conn.close();
    }
}

Klasa znajduje sie w pakiecie derbysample oraz operuje na bazie danych o nazwie VIR, bez uwierzytelniania. jdbcconnection oznacza, ze sterownik JNDI pobiera domyslne wartosci biezacej bazy dla danego polaczenia. W przypadku metody getAccounts(ResultSet[] data) zwracany jest wynik zapytania. Tutaj uwaga: ResultSet MUSI pozostac otwarty, aby CallableStatement, wywolujace metode, mialo do niego dostep. Tak przygotowany zestaw definicji procedur mozna skompilowac i zapakowac do pliku .jar, a nastepnie plik ten wrzucic w jakies widoczne miejsce (np. do katalogu %DERBY_INSTALL%/lib)

2. rejestrowanie procedury w bazie danych
Gdy metody dla procedur sa juz "wystawione", trzeba je zarejestrowac do bazy danych, w taki sposob:

call sqlj.install_jar('lib/derbysample.jar', 'APP.derbysample');
call syscs_util.syscs_set_database_property('derby.database.classpath', 'APP.derbysample');

create procedure vir.addAccount(in login varchar(40), in password varchar(40))
parameter style java
language java
external name 'derbysample.MyProcedures.accAccount';

create procedure vir.getAccounts()
parameter style java
language java
dynamic result sets 1
reads sql data
external name 'derbysample.MyProcedures.getAccounts';

W zaleznosci od narzedzi, komendy mozna wywolac albo z okna "Execute Command..." w NetBeans, albo (bardziej prawdopodobne) z dolaczonego do Derby narzedzia: ij. Pierwsze dwie komendy instaluja pakiet .jar z procedurami oraz ustawiaja go w classpath bazy danych.
Kolejne dwie sekcje to rejestrowanie procedur: pierwsza z dwoma parametrami, aktualizujaca baze danych (domyslny parametr: MODIFIES SQL DATA); druga bez parametrow, zwracajaca wynik zapytania (parametr: READS SQL DATA oraz DYNAMIC RESULT SETS 1). Tutaj trzeba zwrocic uwage, w jaki sposob przekazywany jest wynik zapytania w kodzie zrodlowym Java (metoda getAccounts(ResultSet[] data).

Tak przygotowane stored procedures mozna teraz wywolac komendami:

call vir.addAccount('jan', 'nowak');
call vir.getAccounts();

lub z poziomu kodu Java:

conn = DriverManager.getConnection("jdbc:derby://localhost:1527/vir");

CallableStatement cs = conn.prepareCall("{call vir.addAccount(?, ?)}");
cs.setString(1, "jan");
cs.setString(2, "nowak");
cs.executeUpdate;

CallableStatement cs = conn.prepareCall("{call vir.getAccounts()}");
ResultSet rs = conn.executeQuery();

Szczegoly tworzenia procedur: http://db.apache.org/derby/docs/10.1/ref/rrefcreateprocedurestatement.html
Troche wiecej o tworzeniu w Derby: http://www.vsj.co.uk/databases/display.asp?id=466

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