Javaオペレーティングデータベースに関するJDBCの基本的な知識のレビュー

JDBCとは何ですか?

  • JDBCは(Javaデータベースコネクティビティ)であり、SunCompanyによってJava言語で記述されたデータベースをリンクするための標準のルールインターフェイスです。

JDBCは私たちのために何ができますか?

  • jdbcは、統合されたJavaコードのセットを使用して、すべてのリレーショナルデータベースを操作します。インターフェイスの操作は次のとおりです。
    ここに画像の説明を挿入
  • Sun Companyは、統合されたデータベースドライバーインターフェイスを提供します。主要なデータベースベンダーは、Sun Companyが提供するインターフェイスに基づいて独自の実装クラスを作成し、それらをjarパッケージにパッケージ化します。このようなjarパッケージは、主要メーカーのデータベースドライバーになっています。特定のデータベースでは、データベースに対応するjarパッケージをインポートするだけで、データベースに正常に接続できます。(実行される実際のコードは、ドライバーjarパッケージの実装クラスです)。

JDBCはどのように使用されますか?

使用手順:

1.ドライバーjarパッケージをインポートします

手動インポート

  1. mysql-connector-java-5.1.37-bin.jarをプロジェクトのlibsディレクトリにコピーします
  2. 右クリック->ライブラリとして追加
    ここに画像の説明を挿入

Maven依存関係のインポート

ドライバーステップの登録

1.データベース接続オブジェクト接続を取得します2.SQLを
定義します
3.SQLステートメントのオブジェクトステートメントを取得します
4.SQLを実行して返された結果を受け取り
ます5.結果を処理します
7.リソースを解放します

Java操作データベースの場合

public class JdbcTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            /*connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test2",
            "root","root");*/
             connection = DriverManager.getConnection("jdbc:mysql:///test2",
                    "root", "root");
            statement = connection.createStatement();

            String  sql = "update account set balance = 1000; -- where id =1;";
            int i = statement.executeUpdate(sql);
            if(i<1){
                System.out.println("执行失败!!!");
            }else{
                System.out.println(i);
                System.out.println("执行成功!!!");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            if(statement !=null){
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(connection !=null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
}

jdbcで一般的に使用されるオブジェクト

DriverManagerドライバー管理オブジェクト

DriverManager管理オブジェクトは何をしますか?
実際、DriverManagerが行うことは、主に次の2つの部分で構成されています。

1.ドライバーを登録します

ドライバを登録すると、実際にどのデータベースドライバjarパッケージが使用されているかがシステムに通知されます。
DriverManagerには静的関数があります。

public static void registerDriver(Driver driver)
                           throws SQLException

しかし、コードを書いたとき、Class.forNameがドライバーをロードするために直接使用されていることがわかりました

Class.forName("com.mysql.jdbc.Driver");

2つの関係は何ですか?
実際、秘密はcom.mysql.jdbc.Driverのソースコードにあります。ソースコードには静的メソッドがあります。ファイルがclass.forName( "xxx")でロードされると、comの静的コードブロックになります。 mysql.jdbc.Driverは自動的に実行され、静的コードは次のようになります。ブロックに登録されたドライバーのコードは自動的に実行され、ソースコードの一部は次のとおりです。

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

注:mysql-connector-javaバージョン5.0以降では、ステートメントClass.forName( "xxx")を省略できます。設定ファイルは5.0以降に追加されたため、プログラムの読み込み時に設定ファイルの内容が自動的に読み込まれるため、上記の手順は省略できます。
ここに画像の説明を挿入

2.データベース接続を取得します

コードメソッドを取得します。

  static Connection getConnection(String url, String user, String password)
 

パラメータ

  • url:接続パスを指定します
    構文:jdbc:mysql:// ipアドレス(ドメイン名):ポート番号/データベース名
    例:jdbc:mysql:// localhost:3306 / test1
    詳細:接続がローカルmysqlサーバーの場合、 mysqlサービスのデフォルトポートは3306であるため、URLは次のように省略できます。jdbc:mysql:///データベース名
    user:ユーザー名
    password:password

接続データベース接続オブジェクト

特徴
  1. データベース接続を取得します。
 Statement  createStatement();
 PrepareStatement  prepareStatement(String sql);
  1. 経営業務
  • トランザクションを開始します。setAutoCommit(boolean autoCommit):トランザクションを開始するための呼び出しメソッドはfalseです。
  • トランザクションをコミットしますcommit();
  • トランザクションrollback();をロールバックします。

SQLを実行するステートメントオブジェクト

静的SQLステートメントを実行し、それらが生成する結果を返すために使用されるオブジェクト。

boolean execute(String sql) throws SQLException

上記のSQLは任意のSQLを実行できます。

int executeUpdate(String sql) throws SQLException

通常の状況では、SQLはDML(挿入、更新、削除)ステートメント、DDL(データ定義言語)(作成、変更、ドロップ)ステートメントの
戻り値を実行し、インプレッションの行数を示します。DMLステートメントは次のように判断できます。影響を受ける行数実行が成功し、戻り値が0より大きいかどうかに関係なく、実行は成功します。それ以外の場合は失敗します。

ResultSet executeQuery(String sql)  :执行DQL(select)语句

ResultSet:結果セットオブジェクト

クエリの結果をカプセル化するために使用されます。
getXxx():データを取得します。
Xxx:int getInt()、String getString();などのデータ型を表します。
パラメーター:

  • int:は、次のように1から始まる列番号を表します。getString();
    String:列名を表します。例:getDouble( "balance")
ケースナンバーワン
public class Jdbc02Test {
    public static void main(String[] args) {
        List<Emp> all = findAll();
        for (Emp emp :
                all) {
            System.out.println(emp);
        }
    }
    public static List<Emp> findAll(){
        Connection connection =null;
        Statement statement = null;
        ResultSet resultSet = null;
        LinkedList<Emp> emps =null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql:///test2",
                    "root", "root");
            statement = connection.createStatement();
            String sql = "select * from account;";
            resultSet = statement.executeQuery(sql);

            /*while (resultSet.next()){
                int anInt = resultSet.getInt(1);
                String name = resultSet.getString("name");
                double balance = resultSet.getDouble("balance");
                System.out.println(anInt+"----->"+name+"----->"+balance);
            }*/
             emps = new LinkedList<>();

            while (resultSet.next()){
                Emp emp = new Emp();
                emp.setId(resultSet.getInt(1));
                emp.setName(resultSet.getString("name"));
                emp.setBalance(resultSet.getDouble("balance"));
                emps.add(emp);
            }

        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally {

            if(resultSet != null){
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(statement != null){
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(connection != null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
        return emps;
    }
}

検索結果:
ここに画像の説明を挿入

ケース2

リストフォームを使用して、クエリの結果を出力します。
エンティティクラス:

public class Emp {
    private  int id;
    private  String name;
    private  Double balance;
    public Emp() {
    }
    public Emp(int id, String name, Double balance) {
        this.id = id;
        this.name = name;
        this.balance = balance;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }
    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", balance=" + balance +
                '}';
    }
}

テストカテゴリ:

public class JdbcTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            /*connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test2",
            "root","root");*/
             connection = DriverManager.getConnection("jdbc:mysql:///test2",
                    "root", "root");
            statement = connection.createStatement();
            String  sql = "update account set balance = 1000; -- where id =1;";

            int i = statement.executeUpdate(sql);
            if(i<1){
                System.out.println("执行失败!!!");
            }else{
                System.out.println(i);
                System.out.println("执行成功!!!");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            if(statement !=null){
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if(connection !=null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
}

ここに画像の説明を挿入

PreparedStatement

SQLインジェクションの問題:
  • SQLをスプライシングする場合、SQLのいくつかの特別なキーワードが文字列のスプライシングに関与します。JDBCUtilsのケース2の場合のSQLインジェクションなどのセキュリティ問題が発生します
  1. 気軽にユーザーを入力し、パスワードを入力します:a 'または' a '=' a
  2. 実際のデータベースで実行されるSQLは次のとおりです
select 
	* 
from 
	account 
where 
	username = 'woailuo' 
and 
	password= 'wo' 
or 
	'ailuo' = 'ailuo';
SQLインジェクションの問題を解決する方法

Sunは、SQLインジェクションの問題を解決するためのPreparedStatementオブジェクトを提供しています。

プリコンパイルされたSQL

パラメータの使用?プレースホルダーとして

JDBCUtilsクラスを抽出します

ケースナンバーワン

リソースファイルの読み込みとツールクラスへのリソースファイルの解放を抽象化し、データベース操作を実装します

資源

url=jdbc:mysql:///test2
username=root
password=root
driver=com.mysql.jdbc.Driver

エンティティクラス

public class Emp {
    private  int id;
    private  String name;
    private  Double balance;
    public Emp() {
    }
    public Emp(int id, String name, Double balance) {
        this.id = id;
        this.name = name;
        this.balance = balance;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }
    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", balance=" + balance +
                '}';
    }
}

ツール

public class JDBCUtils {
    private  static  String url;
    private  static  String username;
    private  static  String password;
    private  static  String driver;
    //静态代码块,加载资源文件
    static {
        try {
            Properties properties = new Properties();
            //加载文件
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            URL resource = classLoader.getResource("jdbc.properties");
            String path = resource.getPath();
            System.out.println(path);
            properties.load(new FileReader(path));
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
            driver = properties.getProperty("driver");
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static  Connection  getConnection(){
        Connection connection = null;
        try {
             connection = DriverManager.getConnection(url, username, password);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            return connection;
        }
    }

    public static void close(Statement statement, Connection connection){
        if(statement != null){
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    public static void close(ResultSet resultSet, Statement statement, Connection connection){
        if(resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(statement != null){
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

テストクラス

Connection connection =null;
        Statement statement = null;
        ResultSet resultSet = null;
        LinkedList<Emp> emps =null;
        try {
             connection = JDBCUtils.getConnection();
            String sql = "select * from account;";
            statement = connection.createStatement();
            resultSet = statement.executeQuery(sql);
             emps = new LinkedList<>();
            while (resultSet.next()){
                Emp emp = new Emp();
                emp.setId(resultSet.getInt(1));
                emp.setName(resultSet.getString("name"));
                emp.setBalance(resultSet.getDouble("balance"));
                emps.add(emp);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,statement,connection);
            return emps;
        }

試験結果
ここに画像の説明を挿入

ケース2

デモンストレーションコード:
ツールクラスとリソースファイルはケース1と一致しており、ケース2はエンティティクラスを必要としないため、データテーブルを少し変更する必要があります。
データベースを変更する必要があります。

use test2;

alter TABLE account  add PASSWORD VARCHAR(20);

ALTER TABLE account CHANGE PASSWORD password VARCHAR(20);

ALTER TABLE account CHANGE NAME username VARCHAR(20);

UPDATE account SET PASSWORD = 'zhangsan' WHERE `NAME`='zhangsan'; 
UPDATE account SET PASSWORD = 'lisi' WHERE `NAME`='lisi'; 
SELECT * FROM account;
desc account;

データベーステーブルとテーブル構造は次のとおりです。

ここに画像の説明を挿入ここに画像の説明を挿入
テストカテゴリ:

public class jdbc03Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = scanner.nextLine();
        System.out.println("请输入密码:");
        String password = scanner.nextLine();
        boolean flag = login(username, password);
        if(flag){
            System.out.println("登录成功!!!");
        }else {
            System.out.println("登录失败!!!");
        }

    }
    public static boolean login(String username, String password){
        Connection connection =null;
        Statement statement = null;
        ResultSet resultSet = null;
        boolean loginFlag = false;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "select * from account where username = '"+username+"' and password= '"+password+"';";
            System.out.println(sql);
            statement = connection.createStatement();
            resultSet = statement.executeQuery(sql);

            if(resultSet.next()){
                loginFlag = true;
                System.out.println(resultSet.getString(2));
                return  loginFlag;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,statement,connection);
        }
        return loginFlag;
    }
}

SQLインジェクションの問題を示します。
アカウント番号:woailuoパスワード:wo 'または' ailuo '=' ailuoを入力するだけ
で、ログインに成功したことがわかりました。
ここに画像の説明を挿入
SQLインジェクションの問題は依然として非常に深刻であることがわかります。
PreparedStatementがSQLインジェクションの問題を解決できることはすでにわかっています。次のケース3は、PreparedStatementオブジェクトの使用方法を示しています。

ケース3

リソースクラスとツールクラスはケース2と同じままで、ステートメントオブジェクトはpreparestatementに変更されます

public class JDBC04Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = scanner.nextLine();
        System.out.println("请输入密码:");
        String password = scanner.nextLine();
        boolean flag = login(username, password);
        if(flag){
            System.out.println("登录成功!!!");
        }else {
            System.out.println("登录失败!!!");
        }
    }
    public static boolean login(String username,String password){
        if(username == null || password==null){
            return false;
        }
        Connection connection =null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        boolean loginFlag = false;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "select * from account where username = ? and password= ?;";
            System.out.println(sql);
            preparedStatement = connection.prepareStatement(sql);
            //需要给问好赋值
            preparedStatement.setString(1,username);
            preparedStatement.setString(2,password);
            resultSet = preparedStatement.executeQuery();

            if(resultSet.next()){
                loginFlag = true;
                System.out.println(resultSet.getString(2));
                return  loginFlag;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,preparedStatement,connection);
        }
        return loginFlag;
    }
}

ここに画像の説明を挿入
SQLインジェクションが失敗しました。この問題は解決されました。

jdbcトランザクション制御

jdbcトランザクション制御プロセス

トランザクション制御では、Connectionオブジェクトを使用できます。
トランザクションを開きます。

  • setAutoCommit(boolean autoCommit):このメソッドを呼び出して、パラメーターをfalseに設定します。つまり、SQLを実行する前にトランザクションを開始します。

トランザクションをコミットします。

  • commit();同じトランザクションでのすべてのSQL実行が完了した後、トランザクションを送信します。

トランザクションをロールバックします。

  • rollback(); catchでトランザクションをロールバックします

トランザクション管理も実装できます

ケースナンバーワン

この場合、ツールクラスとリソースクラスは、抽出されたJDBCUtilsクラスと一致しています。

テストクラス

public class JDBC05Test {
    public static void main(String[] args) {
        System.out.println("----------交易开始前----------");
        List<Emp> all = findAll();
        for (Emp emp :
                all) {
            System.out.println(emp);
        }
        transaction("zhangsan","lisi",500);
        System.out.println("------交易完成后-------");
        all=findAll();
        for (Emp emp :
                all) {
            System.out.println(emp);
        }
    }

    public static boolean transaction(String user1, String user2, double val ){
        Connection connection =null;
        PreparedStatement preparedStatement1 = null, preparedStatement2=null;
        ResultSet resultSet = null;
        try {
            connection = JDBCUtils.getConnection();
            connection.setAutoCommit(false);
            String sql1 = " update account set balance = balance - ? where username = ?";
            String sql2 = " update account set balance = balance + ? where username = ?";
            preparedStatement1 = connection.prepareStatement(sql1);
            preparedStatement2 = connection.prepareStatement(sql2);
            preparedStatement1.setDouble(1,val);
            preparedStatement1.setString(2,user1);
            preparedStatement2.setDouble(1,val);
            preparedStatement2.setString(2,user2);

            int i = preparedStatement1.executeUpdate();
           // int i2= 4/0;
            int i1 = preparedStatement2.executeUpdate();
            connection.commit();

        } catch (Exception e) {
            try {
                if(connection !=null){
                    connection.rollback();
                }
            } catch (SQLException sqlException) {
                sqlException.printStackTrace();
            }
            e.printStackTrace();
            return false;
        }finally {
            JDBCUtils.close(resultSet,preparedStatement1,connection);
            JDBCUtils.close(resultSet,preparedStatement2,connection);
        }
        return  true;
    }
    
    public static List<Emp> findAll(){
        Connection connection =null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        LinkedList<Emp> emps =null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "select * from account;";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            emps = new LinkedList<>();
            while (resultSet.next()){
                Emp emp = new Emp();
                emp.setId(resultSet.getInt(1));
                emp.setUsername(resultSet.getString("username"));
                emp.setBalance(resultSet.getDouble("balance"));
                emp.setPassword("password");
                emps.add(emp);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,preparedStatement,connection);
            return emps;
        }
    }
}

トランザクションに例外がない場合、トランザクション全体が正常に実行されます。
ここに画像の説明を挿入
トランザクションに例外がある場合、トランザクションは直接ロールバックされます。

public class JDBC05Test {
    public static void main(String[] args) {
        System.out.println("----------交易开始前----------");
        List<Emp> all = findAll();
        for (Emp emp :
                all) {
            System.out.println(emp);
        }
        transaction("zhangsan","lisi",500);
        System.out.println("------交易完成后-------");
        all=findAll();
        for (Emp emp :
                all) {
            System.out.println(emp);
        }
    }

    public static boolean transaction(String user1, String user2, double val ){
        Connection connection =null;
        PreparedStatement preparedStatement1 = null, preparedStatement2=null;
        ResultSet resultSet = null;
        try {
            connection = JDBCUtils.getConnection();
            connection.setAutoCommit(false);
            String sql1 = " update account set balance = balance - ? where username = ?";
            String sql2 = " update account set balance = balance + ? where username = ?";
            preparedStatement1 = connection.prepareStatement(sql1);
            preparedStatement2 = connection.prepareStatement(sql2);
            preparedStatement1.setDouble(1,val);
            preparedStatement1.setString(2,user1);
            preparedStatement2.setDouble(1,val);
            preparedStatement2.setString(2,user2);

            int i = preparedStatement1.executeUpdate();
            int i2= 4/0;
            int i1 = preparedStatement2.executeUpdate();
            connection.commit();

        } catch (Exception e) {
            try {
                if(connection !=null){
                    connection.rollback();
                }
            } catch (SQLException sqlException) {
                sqlException.printStackTrace();
            }
            e.printStackTrace();
            return false;
        }finally {
            JDBCUtils.close(resultSet,preparedStatement1,connection);
            JDBCUtils.close(resultSet,preparedStatement2,connection);
        }
        return  true;
    }

    public static List<Emp> findAll(){
        Connection connection =null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        LinkedList<Emp> emps =null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "select * from account;";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            emps = new LinkedList<>();
            while (resultSet.next()){
                Emp emp = new Emp();
                emp.setId(resultSet.getInt(1));
                emp.setUsername(resultSet.getString("username"));
                emp.setBalance(resultSet.getDouble("balance"));
                emp.setPassword("password");
                emps.add(emp);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,preparedStatement,connection);
            return emps;
        }
    }
}

ここに画像の説明を挿入
これまでのところ、jdbcの基本的な知識をここで確認します。

おすすめ

転載: blog.csdn.net/xueshanfeitian/article/details/109086494