NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: login cez mysql

V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
cheki
Člen
Avatar
cheki:28.2.2017 21:27

cawes, pokusam sa spravit program do ktoreho sa budem prihlasovat menom/heslo. Spravil som si DB a spravil triedu na pripojenie k DB (mam to na mysql). GUI robim v javaFX cez scene builder.

public class LoginModel {
    Connection connStatus;


    public LoginModel() {
        connStatus = DBconnect.Connector();
        if (connStatus == null) {
            System.out.println("connection not successful");
            System.exit(1);
        } else {
            System.out.println("connection is successful");
        }
    }

    public boolean isDBConnected() {
        try {
            return !connStatus.isClosed();
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }



    public boolean isLogin(String user, String pass) throws SQLException {

        PreparedStatement ps = null;
        ResultSet rs=null;
        boolean login = false;

        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/dblogin", "root", "");

        /*
        user = "momo";
        pass = "momo";
        */


      /*
       if (pass.isEmpty())
            pass = "";
            */


        String sql;
        try {
            Class.forName("com.mysql.jdbc.Driver");

            sql = "select user,password from login where user = ? and password = ?";
            // sql="SELECT user, password FROM `login` WHERE user = " + txtUser.getText() " and password = "test"";


            ps = conn.prepareStatement(sql);
            ps.setString(1, user);
            ps.setString(2, pass);
            rs = ps.executeQuery(sql);

            if(rs == null) {
                System.out.println("xxxxx");
            }else {
                System.out.println("yyyyy");
            }

            while (rs.next()) {

                String CheckUser = rs.getString("user");
                String CheckPass = rs.getString("password");
                if (CheckUser.equals(user) && CheckPass.equals(pass)) {
                    System.out.println("login OK");
                    login = true;
                } else {
                    System.out.println("login FAIL");
                    login = false;
                }

            }
        } catch (SQLException e) {
            return false;
        } catch (ClassNotFoundException ce) {

        } finally {
            ps.close();
             if (rs != null) {
                 rs.close();
             }else {
                 System.out.println("rs = null");
             }
        }return login;
    }
}

problem mam niekde v try {}. chcem aby po zadani mena heslo program overil tieto udaje s DB a ak sa zhoduju tak ma pusti dalej. Problem mam ze mi to neoveri a vzdy skonci s tym ze som zadal zle heslo.
Problem bude niekde v rs. Cez breakpointy mi to preskocilo celu cast kde to porovnava a cely cas mam v rs null, neviem preco. Vedel by mi niekto s tym pls pomoct? dakujem
btw som zaciatocnik tak ak su tam nejake amaterske chyby tak sa za ne ospravedlnujem..

 
Odpovědět
28.2.2017 21:27
Avatar
Vojta Bereščák:1.3.2017 0:48

Nevim jestli to je tim, ale zkus misto
rs = ps.executeQue­ry(sql);
dat jen
rs = ps.executeQuery();
ty si z stringu priprvis statement, pak ho zcnes plnit a potom das provyst znovu novej sql (kterej uz asi nebude naplnenej).

 
Nahoru Odpovědět
1.3.2017 0:48
Avatar
Vojta Bereščák:1.3.2017 0:50

Plus ted v dokumentaci ctu ze executeQuery(sql) by nikdy nemelo vratit null (bud Result set nebo vyjimka). Tzn jeste jednou to oddebuguj.

Returns: a ResultSet object that contains the data produced by the given query; never null

 
Nahoru Odpovědět
1.3.2017 0:50
Avatar
cheki
Člen
Avatar
cheki:1.3.2017 8:06

dik pomohlo to, lamal som si nad tym dlho hlavu Vedel som ze nema vracat null ale stale vracal...skusal som vsetko mozne a nic :D ale aspon som sa vdaka tomuto naucil pouzivat breakepointy :) myslim ze coskoro sem pridam dalsi problem... tak zatial dik :)

 
Nahoru Odpovědět
1.3.2017 8:06
Avatar
cheki
Člen
Avatar
cheki:1.3.2017 10:27

pozeram teraz triedu na spojenie s DB a tam mi to takto ide (no ale mam tam Statement nie Prepare..)

public class DBconnect {

    public static Connection Connector() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            System.out.println("Error");
            return null;
        }
        Connection connection;//=null;

        try {
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/dblogin", "root", "");
            Statement stmt;

            stmt = connection.createStatement();
            String sql = "Select * from login";
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                int id = rs.getInt("id");
                String user = rs.getString("user");
                String password = rs.getString("password");

                System.out.println("ID " + id);
                System.out.println("User " + user);
                System.out.println("Password " + password);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }

        return connection;
    }
    }
 
Nahoru Odpovědět
1.3.2017 10:27
Avatar
Vojta Bereščák:1.3.2017 12:41

Statement je zjednodussene jen string s sql ktery se preda DB. PreparedStatement je dvoufazovy. Ty pripravis dotaz a potom do nej vkladas parametry. Dle meho nazoru u prepared statement executeQuery(String sql) zustalo jen jako pozustatek od rodice Statement a dle meho neni dobre ho pouzivat a je lepsi vyuzivat jen executeQuery(). V kazdem pripade to vyresetuje tvoji snahu s pripravou parametru v radcich vyse.

 
Nahoru Odpovědět
1.3.2017 12:41
Avatar
cheki
Člen
Avatar
cheki:1.3.2017 12:47

okej cize je lepsie potom pouzivat PreparedStatement. Bolo by teda lepsie prepisat triedu DBconnect a namiesto statement tam dat prepared?

 
Nahoru Odpovědět
1.3.2017 12:47
Avatar
cheki
Člen
Avatar
cheki:16.3.2017 13:02

ked mam okno kde su ulozene nejake choiceboxy, textfieldy atd.. po ich vyplneni chcem aby sa udaje zapisali do DB. Je potrbne vzdy nadviazat spojenie??

String sql;
       try {
           Class.forName("com.mysql.jdbc.Driver");

           sql = "select user,password from login where user = ? and password = ?";
           // sql="SELECT user, password FROM `login` WHERE user = " + txtUser.getText() " and password = "test"";


           ps = conn.prepareStatement(sql);
           ps.setString(1, user);
           ps.setString(2, pass);
           rs = ps.executeQuery(sql);

(nie zrovna tento kod ale princip je rovnaky?)

 
Nahoru Odpovědět
16.3.2017 13:02
Avatar
Petr
Člen
Avatar
Petr:17.3.2017 9:39

Principy u databazovych aplikaci jsou nasledujici:

  • pokud aplikace provede jeden dotaz a pak dlouho nic, pak je nutne spojeni uzavrit
  • pokud aplikace provadi dotazy casto pak je naopak nutne si spojeni drzet a nevytvaret nove, protoze to je take narocna operace
  • pokud aplikace provadi velke mnozstvi dotazu (vice uzivatelu najednou) pak se pouziva tzv. connection pool - otevre se nekolik spojeni, ktere se udrzuji a ty se pak rovnomerne prideluji na pozadani. Jenom prosimte connection pool neimplementuj sam ale pouzij uz nejaky hotovy pokud by jsi to potreboval. Je to pomerne slozite a kdyz tam udelas chybu tak mas zadelano na poradne problemy.
  • jeste posledni poznamka Class.forName neni nutne v dnesni dobe volat pokud vis ze ten driver je na classpath (mas to treba vyresene v zavislostech), prakticky kazdy driver ma uz dnes v manisfestu jarka sekci, ktera zajisti ze ho java zaregistruje pri startu tvoji aplikace, coz drive (hodne davno) zajistovalo prave Class.forName. Samozrejme pokud by ti driver chybel na classpath tak se ti nepodari vytvorit spojeni do DB.
Editováno 17.3.2017 9:39
 
Nahoru Odpovědět
17.3.2017 9:39
Avatar
cheki
Člen
Avatar
cheki:18.3.2017 22:55

mozes ten posledny bod trocha viac vysvetlit? dik.
no a takto: mam rieseny login cez db (tak ako to je hore). tam som spojenie uzavrel, ako prebehne login tak sa spojenie ukonci. (tvoj bod c.1). V aplikacii budem pridavat data do db. Budu v nej textfieldy, comboboxy atd.(v tabulke asi 6 atributov). To budu len inserty do tabulky a potom v aplikaciu budu rozne reporty(grafy) cize budem tahat z tych udajov co sa vkladali. cize tam bude lepsie nechat otvorene spojenie?? (teda asi bod 2) mi iba tak v hlave prebehlo ci by sa to nedalo riesit nejak transakciami (este neviem ako by som to napisal ale myslienka neni zla :D).

toto je troska mimo temy ale je to k aplikacii: Mam textfield kde potrebujem dat ciselne hodnoty s desatinou ciarkou (najlepsie asi double). Je mozno to nejak preparsovat na double?? najlepsie by bolo ak by nenapisalo ziaden iny znak iba cisla (a teda ciarku alebo bodku). S tymito hodnotami potrebujem dalej pracovat (nasobit). Hladal som na nete nejake riesenie ale nejak sa mi nepodarilo. Tam kde bude cisto len int som spravil toto:

tfKurz.textProperty().addListener((observable, oldValue, newValue) -> {
           if(!newValue.matches("[0-9]*")) {
               tfKurz.setText(oldValue);
               // System.out.println(oldValue);

           }
       });

pre double to ale zatial neviem poriesit
dik za rady a pomoc :)

 
Nahoru Odpovědět
18.3.2017 22:55
Avatar
cheki
Člen
Avatar
cheki:18.3.2017 23:12

vlastne ak som to spravne pochopil (ten kod) tak to nedava na int ale len nedovoli napisat znamky ale len cisla, no stale to je string

 
Nahoru Odpovědět
18.3.2017 23:12
Avatar
cheki
Člen
Avatar
cheki:19.3.2017 0:10

to parsovanie som poriesil takto, neviem ci to je dobre riesenie ale ide

@FXML
  public void parseDouble (ActionEvent event) throws Exception{
      try{
          Double kurz = Double.parseDouble(tfKurz.getText());
          System.out.println(kurz);

      }catch (NumberFormatException e){
          System.out.println("chyba v parsovani");
      }
  }
 
Nahoru Odpovědět
19.3.2017 0:10
Avatar
Petr
Člen
Avatar
Petr:20.3.2017 11:00

Ahoj,

  • http://stackoverflow.com/…gisterdriver tady je vysvetleno proc neni nutne volat Class.forName, jedine co ti class for name zajisti je, ze kdybys tam ten driver nemel tak ti to padne uz na tom Class.forName a ne az pri vytvareni connection
  • ten kus kodu s listenerem jen hlida zmeny v textovem poli a pokud napises neco jine jak cislici tak tam vrati starou hodnotu, samozrejme to jde upravit na desetinne cislo napr. nejak takto: [-+]?[0-9]\.?[0-9]
  • k JDBC driverum obecne: jak je popsano vyse na stackoverflow, drivery se registruji na zaklade meta informaci v *.jar, co neni az tak zname je jak se vybira driver. Funguje to pomerne jednoduse, DriverManager si drzi seznam driveru v poradi v jakem se registrovali. Pokazde kdyz se zavola getConnection s jdbc connection stringem tak se seznam prochazi od prvniho driveru, preda se mu connection string a pokud vrati null tak se pokracuje dalsim driverem, pokud vrati connection tak ho dostanes nazpet. Z toho mimo jine plyne, ze pokud dva drivery mohou akceptovat ten samy connection string, pak dostanes connection od driveru, ktery je v tom seznamu drive (byl drive zaregistrovan). Poradi registrace driveru je myslim zavisle od toho jak class loader nacita classy (nejsem si uplne jisty). Seznam se da modifikovat za behu programu, napriklad nektere frameworky toho vyuzivaji aby si tam pridaly wrapper na existujici driver (posadi vlastni driver na prvni misto) a pak loguji pristupy do DB nebo delaji jine oprace.
 
Nahoru Odpovědět
20.3.2017 11:00
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 13 zpráv z 13.