Educoder/Touge JAVA——JAVA の高度な機能: JDBD (パート 1)

目次

レベル 1: JDBC 接続データベース

関連情報

データベースドライバーをロードする

接続を確立する

書かれたSQL文を実行する

リソースを解放する

プログラミング要件

レベル 2: テーブル内のデータに対する JDBC 操作

関連情報

データベース接続を指定する

指定されたテーブルにデータを挿入します

テーブル内のデータをクエリする

プログラミング要件

レベル 3: JDBC トランザクション

関連情報

事務

トランザクションの基本要素 (ACID)

オープントランザクション

コミットとロールバック

プログラミング要件


レベル 1: JDBC 接続データベース

関連情報

JDBC API次のインターフェイスとクラスが提供されます。

DriverManager: このクラスの管理データベース ドライバーのリスト。JDBCサブプロトコルが認識され、データベース接続を確立するために使用される最初のドライバー。

Driver: このインターフェイスはデータベース サーバーとの通信を処理します。私たちがDriverオブジェクトと直接対話することはほとんどありません。プログラミングでデータベースに接続するには、まず特定のベンダーのデータベース ドライバーをロードする必要があります。

Connection: このインターフェイスには、データベースに接続するためのすべての方法が含まれています。Connectionオブジェクトは通信コンテキストを表します。つまり、データベースとのすべての通信は接続オブジェクトのみを経由します。

StatementSQL: 静的ステートメントを実行し、生成された結果を返すために使用されるオブジェクト。一部の派生インターフェイスはパラメーターも受け入れることができますPrepareStatement

ResultSet: さまざまなタイプのフィールドを取得するメソッドを提供します。(操作対象はクエリStatement実行後の結果です)SQL

SQLException: このクラスは、データベース アプリケーションで発生したエラーを処理します。

使用する手順はJDBC次のとおりです。

データベースドライバーのロード → データベース接続の確立 ( Connection) →SQLステートメントを実行するオブジェクトの作成Statement→ 実行結果の処理 ( ResultSet) → リソースの解放

このタスクを完了するには、1. データベース ドライバーのロード方法、2. データベース接続の確立方法、3. 書かれたステートメントの実行方法、4. リソースの解放を習得する必要がありますSQL

データベースドライバーをロードする

ドライバーは、データベースとの通信チャネルを開くためにロードされます。

mysq-connector-javaドライバーを登録する前に、ベンダー固有のデータベース ドライバーとインポートされたパッケージを読み込む必要がありますjar。方法としては、プロジェクト内にディレクトリを作成しlib、その下にパッケージを置きますjar

jar次に、パッケージを右クリックBuild Path→パッケージのインポートAdd to Build Pathを完了しますjarjarパッケージをプロジェクトにインポートした後、ドライバーの登録を開始します。

Javaデータベース ドライバーのロードには通常、Classクラス の静的メソッドが使用されforName()、構文形式は次のとおりです。

  1. Class.forName(String driverManager)

例:

  1. try {
  2. Class.forName("com.mysql.jdbc.Driver" );
  3. } catch (ClassNotFoundException e) {
  4. e.printStackT\frace();
  5. }

ロードが成功すると、ロードされたドライバ クラスは に登録されDriverManager、ロードが失敗するとClassNotFoundException例外がスローされます。

接続を確立する

DriverManagerデータベース ドライバーが正常に読み込まれたら、静的メソッドを使用してデータベースへの接続を確立できますgetConnection()次のように:

  1. Connection conn = DriverManager.getConnection(url, user, password);

URLこれは、データベースの場所を特定し、アドレスを通じてプログラムの接続情報をURL伝えるために使用されますJDBC

データベースがない場合は、次URLのように記述して接続のみを確立します。

データベースがある場合testURL書き込み方法は次のとおりです。

これは、データベースのデフォルトのポート番号であるaddress および対応するデータベースのユーザー名とパスワードlocalhost置き換えることができます。IP127.0.0.13306MySQLuserpassword

書かれたSQL声明を実行する

接続が確立されたら、Connectionインターフェイスのメソッドを使用してオブジェクトcreateStatement()を取得し、そのメソッドを通じてステートメントを実行できます。StatementexecuteUpdate()SQL

  • statementオブジェクトを作成する

    1. try {
    2. Statement statement = conn.createStatement();
    3. } catch (SQLException e) {
    4. e.printStackT\frace();
    5. }
  • データベースを作成する

    1. try {
    2. String sql1="drop database if exists test";
    3. String sql2="create database test";
    4. statement.executeUpdate(sql1);//执行sql语句
    5. statement.executeUpdate(sql2);
    6. } catch (SQLException e) {
    7. e.printStackT\frace();
    8. }
  • テーブルを作成する

    1. try {
    2. statement.executeUpdate("use test");//选择在哪个数据库中操作
    3. String sql = "create table table1(" +
    4. "column1 int not null, " +
    5. "column2 varchar(255)" +
    6. ")";
    7. statement.executeUpdate(sql);
    8. } catch (SQLException e) {
    9. e.printStackT\frace();
    10. }

リソースを解放する

Jdbcプログラムの実行後は、データベースと対話するためにプログラムが実行プロセス中に作成したオブジェクトを解放することを忘れないでください。これらのオブジェクトは通常、 およびResultSetオブジェクトStatementですConnection

特にConnectionオブジェクトは非常に希少なリソースであり、使用後はすぐに解放する必要があり、Connection適切なタイミングで適切に閉じられないと、システムのダウンタイムが発生しやすくなります。

Connection使用の原則は、できるだけ遅く作成し、できるだけ早くリリースすることです。

リソース解放コードを確実に実行できるようにするには、リソース解放コードをfinallyステートメントに配置する必要があります。

  1. finally {
  2. try {
  3. if(statement!=null)
  4. statement.close();
  5. if(conn!=null)
  6. conn.close();
  7. } catch (SQLException e) {
  8. e.printStackT\frace();
  9. }
  10. }

プログラミング要件

右側のエディターでコードを補足し、次の対応するタスクを完了します。

  1. データベース ドライバーをロードします。[プラットフォーム データベース接続のユーザー ( )userroot、パスワード ( password) は123123]

  2. データベースを作成しますmysql_db

  3. テーブルを作成しますstudent

studentテーブル構造は次のとおりです。

フィールド名 タイプ 述べる 制約
ID 整数 学生証 空ではない
名前 varchar(20) 学生の名前 なし
セックス varchar(4) 学生の性別 なし
整数 学生時代 なし
//jdbcConn.java
package jdbc;

import java.sql.*;

public class jdbcConn {
	public static void getConn() {
		try {
			// 1.注册驱动
			Class.forName("com.mysql.jdbc.Driver");

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		/********** End **********/

		/********** Begin **********/
		Connection conn = null;
		Statement statement = null;
		try {
			// 2.建立连接并创建数据库和表
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/", "root", "123123");
			String sql1 = "drop database if exists mysql_db;";
			String sql2 = "create database mysql_db;";
			statement = conn.createStatement();
			statement.execute(sql1);
			statement.execute(sql2);
			statement.execute("use mysql_db");
			String sql3 = "create table student(id int not null,name varchar(20),sex varchar(4),age int)";
			statement.execute(sql3);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (statement != null)
					statement.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}
//test1.java
package jdbcTest;

import jdbc.jdbcConn;
import java.sql.*;

public class Test1 {
    public static void main(String[] args) throws SQLException {
        jdbcConn.getConn();
        try {
            Class.forName("com.mysql.jdbc.Driver" );
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        String url = "jdbc:mysql://localhost:3306/mysql_db";
        Connection conn = DriverManager.getConnection (url,"root","123123" );
        PreparedStatement pst = null;
        try {
            pst = conn.prepareStatement("select * from student");
            ResultSetMetaData rsd = pst.executeQuery().getMetaData();
            for(int i = 1; i <= rsd.getColumnCount(); i++) {
                String columnTypeName = rsd.getColumnTypeName(i);
                String columnName = rsd.getColumnName(i);
                int columnDisplaySize = rsd.getColumnDisplaySize(i);
                System.out.println(columnName+" "+columnTypeName+"("+columnDisplaySize+")");
            }
        } catch(SQLException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (pst!=null)
                    pst.close();
                if (conn != null)
                    conn.close();
            } catch(SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

レベル 2: テーブル内のデータに対する JDBC 操作

関連情報

データベース接続を指定する

すでにデータベースがある場合は、次のように接続時にデータベースを直接指定して、test_dbデータベースとの接続を確立できます。

  1. String url = "jdbc:mysql://localhost:3306/test_db";
  2. Connection conn = DriverManager.getConnection (url,"root","123123" );

SQL接続時にデータベースを指定する場合、データベースを選択するためのステートメントを記述する必要はありません。

指定されたテーブルにデータを挿入します

接続が確立したら、 table にデータを挿入するsqlステートメントを作成し、Statementオブジェクトのメソッドを使用してステートメントexecuteUpdate()を実行しsql、テーブル内のデータを変更します (このメソッドはinsertupdate、 、deleteステートメントに適用できますsql)。sqlクエリ ステートメントの場合は、次executeQuery()のメソッドを使用します。

  1. try {
  2. Statement statement = conn.createStatement();
  3. statement.executeUpdate("insert into table1(column1,column2) values(101,'xxx')");
  4. } catch (SQLException e) {
  5. e.printStackT\frace();
  6. }

準備されたステートメント

上記の直接使用はStatement、テーブルにデータを挿入するため、SQL次の例のように、操作中に上記のテーブルから分離されたインジェクションが発生する危険性があります。

  1. String id = "5";
  2. String sql = "delete from tablename where id=" + id;
  3. Statement st = conn.createStatement();
  4. st.executeQuery(sql);//查询到表中将无数据
  5. //如果用户传入的id为“5 or 1=1”,那么将删除表中的所有记录

この状況のSQLインジェクションを防ぐには、インジェクションをPreparedStatement効果的に防止します(ステートメントはプログラムの実行前にプリコンパイルされており、パラメータは実行時に動的に渡されます。データベースなどのパラメータに機密文字が含まれている場合でも、それらは命令としてではなく、処理されるパラメータ値のフィールド属性として使用されます)sqlSQLPreprareStatementor '1=1'SQL

PreparedStatement次のように使用します。

  1. PreparedStatement statement = conn.prepareStatement("insert into table1(column1,column2) values(?,?)");//使用占位符来先占个位置
  2. statement.setInt(1,101);//占位符顺序从1开始,根据数据库中字段相应的类型存入数据
  3. statement.setString(2, "XXX");//也可以使用setObject
  4. statement.executeUpdate();//每执行一个sql语句就需要执行该方法

テーブル内のデータをクエリする

Jdbcプログラム内でステートメントの実行結果をResultSet表すために使用されます。Sql

Resultset実行結果をカプセル化するとき、メソッドはtableResultSetに似ています。オブジェクトはテーブルのデータ行を指すカーソルを維持します。最初は、カーソルは最初の行の前にあります。カーソルがResultSet.next()特定のデータを指すようにメソッドを呼び出します。行を選択し、この行のデータを取得するメソッドを呼び出します。

  1. //编写查询sql语句
  2. PreparedStatement statement = conn.prepareStatement("select * from table1");
  3. ResultSet resultSet = statement.executeQuery();//将执行结果给ResultSet
  4. while (resultSet.next()) {//循环判断表中是否还有数据
  5. int id = resultSet.getInt(1);//通过列的索引查询
  6. String name = resultSet.getString("column2");//通过列名查询
  7. }

プログラミング要件

右側のエディターのコードを補足し、前の章で作成したデータベースmysql_dbのテーブルにデータを挿入しstudent、挿入されたデータを出力します。

ID 名前 セックス
1 張三 19
2 李思 女性 18
3 ワン・ウー 20

ヒント:クラスはパッケージ化されておりstudent、右側のフォルダーで表示でき、このクラスは直接使用できます。

package jdbc;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class jdbcInsert {
    public static void insert(){
		/**********   Begin  **********/
        try {
            //加载驱动
            Class.forName("com.mysql.jdbc.Driver");

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
		/**********   End   **********/
		Connection conn = null;
		PreparedStatement statement = null;
		/**********   Begin  **********/
        //连接并插入数据
		try{
			String url = "jdbc:mysql://localhost:3306/mysql_db?useUnicode=true&characterEncoding=utf8";
			String user = "root";
			String password = "123123";
			conn = DriverManager.getConnection(url, user, password);

			String sql = "insert into student(id,name,sex,age) values (1,'张三','男',19),(2,'李四','女',18),(3,'王五','男',20)";

			statement = conn.prepareStatement(sql);
			statement.executeUpdate();
			String sql1 = "select * from student";
			ResultSet rs = statement.executeQuery(sql1);

			Student student = null;
			while (rs.next()) {
				int id = rs.getInt(1);
				String name = rs.getString(2);
				String sex = rs.getString(3);
				int age = rs.getInt(4);
				student = new Student(id, name, sex, age);
				System.out.println(
						student.getId() + " " + student.getName() + " " + student.getSex() + " " + student.getAge());
			}
		
		} catch (SQLException e) {
            e.printStackTrace();
        }
		/**********   End   **********/
		finally {
            try {
                if (statement != null)
                    statement.close();
                if (conn != null)
                    conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

レベル 3: JDBC トランザクション

関連情報

事務

あるシナリオを想定すると、人事管理システムがあり、個人を削除する場合は、その個人の基本情報だけでなく、その個人に関連するメールボックスや記事などの情報も削除する必要があります。これらのデータベース操作ステートメントは、トランザクションを作成できるようになります。

トランザクションは、変更をいつコミットしてデータベースに適用するかを制御します。SQL単一のステートメントまたはステートメントのグループを論理単位として扱いSQL、いずれかのステートメントが失敗すると、トランザクション全体が失敗します。

ビジネスの基本要素 ( ACID)

  • アトミック性 ( Atomicity): トランザクションのグループ、成功または撤退。

  • 整合性 ( Consistency): トランザクションの前後で、データベースの整合性制約に違反していません。Aたとえば、A が B にお金を送金する場合、お金を差し引くだけで受け取らないことは不可能ですB

  • 分離 ( Isolation): トランザクションは独立して実行されます。トランザクション処理の結果が他のトランザクションに影響を与える場合、他のトランザクションは取り消されます。トランザクションを100%分離するには速度を犠牲にする必要があります。

  • 永続性 ( Durability): トランザクションが完了すると、トランザクションによってデータベースに対して行われたすべての更新はデータベースに保存され、ロールバックすることはできません。

オープントランザクション

モノを開くには、呼び出し可能なオブジェクトのメソッドで、JDBCドライバーがデフォルトで使用する自動コミット モードを使用するのではなく、手動トランザクションサポートを有効にする必要がありますブール値が に渡されると自動コミットはオフになります。これは、オンにするのと同じです。ブール値を渡してオンに戻すこともできます。ConnectionsetAutoCommit()falsesetAutoCommit()true

  1. Connection conn = DriverManager.getConnection (url,"root","123123" );
  2. conn.setAutoCommit(false);//关闭自动提交开启事务

コミットとロールバック

mysqlデータベースではsql、デフォルトではすべての文が自動的に送信されますが、手動トランザクション サポートに設定すると (つまり、トランザクションが手動で開かれている)、送信する必要があるときに手動で送信できます。

  1. conn.commit();//提交事务

sql複数のステートメントが一度に送信された場合、sqlそれらが合法であるかどうか、また、そのうちの 1 つが違法である場合にsqlのステートメントを変更する必要があるかどうかを検討する必要があります。トランザクションの基本要素を確保するには、手動で制御へのトランザクションのロールバックsql: 以下の実行:

  1. try{
  2. Connection conn = DriverManager.getConnection (url,"root","123123" );
  3. conn.setAutoCommit(false);//开启事务
  4. PreparedStatement ps = conn.prepareStatement("insert into table1(column1,column2) values(1,'xx1')");
  5. ps.executeUpdate();
  6. ps = conn.prepareStatement("insert in table1(column1,column2) values(1,'xx1')");
  7. ps.executeUpdate();
  8. conn.commit();//提交事务
  9. } catch (SQLException e) {
  10. try {
  11. conn.rollback();//回滚事务 回滚到你开始事务之前
  12. } catch (SQLException e1) {
  13. e1.printStackT\frace();
  14. }
  15. }

上記のコードが実行された後、データベース内のデータは更新されません。2 番目のステートメントの構文がinsert間違っているため、トランザクションはロールバックされ、前のステートメントはinsert無効になります。catch通常、トランザクションのロールバックはキャプチャのために配置されます。

トランザクションを開始した後は、ロックされている可能性のあるデータを時間内に保持commitまたは。rollback

これを使用しない場合でも、使用した場合と同じ効果がrollback()ありますrollback()が、使用しないと、rollback()ロックされたデータが時間内に解放されない可能性があり (時間の経過とともに解放されるまで待つ必要があります)、次のトランザクション操作に影響します。

プログラミング要件

プロンプトに従って、右側のエディタのコードを補足し、新しいSQLステートメントと間違ったステートメントを作成して、トランザクションを送信します。最初の新しいSQLステートメントはデータベース内で変更する必要があり、後続の間違ったSQLステートメントは実行されません。 。

挿入ステートメントを追加するための具体的な要件は次のとおりです。 、Zhao Liu、女性、データmysql_dbデータベーステーブルstudent新しいエントリを追加しますid4namesexage21

ヒント:トランザクションは各ステートメントSQLの後にコミットできます。

package jdbc;

import java.sql.*;

public class jdbcTransaction {

    public static void transaction(){
        try {
            Class.forName("com.mysql.jdbc.Driver" );
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Connection conn = null;
        PreparedStatement ps = null;
        /**********  Begin   **********/
        //连接数据库并开启事务
        try {
			String url = "jdbc:mysql://localhost:3306/mysql_db?useUnicode=true&characterEncoding=utf8";
			conn = DriverManager.getConnection(url, "root", "123123");
			conn.setAutoCommit(false);
			String sql = "insert into student(id,name,sex,age) values(4,'赵六','女',21)";
			ps = conn.prepareStatement(sql);
			ps.executeUpdate();
			conn.commit();
			String sql1 = "daj;ljd";
			ps = conn.prepareStatement(sql1);
			ps.executeUpdate();
			conn.commit();
			String sql2 = "select * from student";
			ResultSet rs = ps.executeQuery(sql2);
			Student student = null;
			while (rs.next()) {
				int id = rs.getInt(1);
				String name = rs.getString(2);
				String sex = rs.getString(3);
				int age = rs.getInt(4);
				student = new Student(id, name, sex, age);
				System.out.println(
						student.getId() + " " + student.getName() + " " + student.getSex() + " " + student.getAge());
			}
        } catch (SQLException e) {
            try {
                //回滚
                conn.rollback();
                
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        }
        /**********  End   **********/
        finally {
            try {
                if(ps!=null)
                    ps.close();
                if (conn != null)
                    conn.close();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        }
    }
}

おすすめ

転載: blog.csdn.net/zhou2622/article/details/128382970