目次
レベル 1: JDBC 接続データベース
関連情報
JDBC API
次のインターフェイスとクラスが提供されます。
DriverManager
: このクラスの管理データベース ドライバーのリスト。JDBC
サブプロトコルが認識され、データベース接続を確立するために使用される最初のドライバー。
Driver
: このインターフェイスはデータベース サーバーとの通信を処理します。私たちがDriver
オブジェクトと直接対話することはほとんどありません。プログラミングでデータベースに接続するには、まず特定のベンダーのデータベース ドライバーをロードする必要があります。
Connection
: このインターフェイスには、データベースに接続するためのすべての方法が含まれています。Connection
オブジェクトは通信コンテキストを表します。つまり、データベースとのすべての通信は接続オブジェクトのみを経由します。
Statement
SQL
: 静的ステートメントを実行し、生成された結果を返すために使用されるオブジェクト。一部の派生インターフェイスはパラメーターも受け入れることができます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
を完了しますjar
。jar
パッケージをプロジェクトにインポートした後、ドライバーの登録を開始します。
Java
データベース ドライバーのロードには通常、Class
クラス の静的メソッドが使用されforName()
、構文形式は次のとおりです。
Class.forName(String driverManager)
例:
try {
Class.forName("com.mysql.jdbc.Driver" );
} catch (ClassNotFoundException e) {
e.printStackT\frace();
}
ロードが成功すると、ロードされたドライバ クラスは に登録されDriverManager
、ロードが失敗するとClassNotFoundException
例外がスローされます。
接続を確立する
DriverManager
データベース ドライバーが正常に読み込まれたら、静的メソッドを使用してデータベースへの接続を確立できますgetConnection()
。次のように:
Connection conn = DriverManager.getConnection(url, user, password);
URL
これは、データベースの場所を特定し、アドレスを通じてプログラムの接続情報をURL
伝えるために使用されますJDBC
。
データベースがない場合は、次URL
のように記述して接続のみを確立します。
データベースがある場合test
、URL
書き込み方法は次のとおりです。
これは、データベースのデフォルトのポート番号であるaddress 、および対応するデータベースのユーザー名とパスワードにlocalhost
置き換えることができます。IP
127.0.0.1
3306
MySQL
user
password
書かれたSQL
声明を実行する
接続が確立されたら、Connection
インターフェイスのメソッドを使用してオブジェクトcreateStatement()
を取得し、そのメソッドを通じてステートメントを実行できます。Statement
executeUpdate()
SQL
-
statement
オブジェクトを作成するtry {
Statement statement = conn.createStatement();
} catch (SQLException e) {
e.printStackT\frace();
}
-
データベースを作成する
try {
String sql1="drop database if exists test";
String sql2="create database test";
statement.executeUpdate(sql1);//执行sql语句
statement.executeUpdate(sql2);
} catch (SQLException e) {
e.printStackT\frace();
}
-
テーブルを作成する
try {
statement.executeUpdate("use test");//选择在哪个数据库中操作
String sql = "create table table1(" +
"column1 int not null, " +
"column2 varchar(255)" +
")";
statement.executeUpdate(sql);
} catch (SQLException e) {
e.printStackT\frace();
}
リソースを解放する
Jdbc
プログラムの実行後は、データベースと対話するためにプログラムが実行プロセス中に作成したオブジェクトを解放することを忘れないでください。これらのオブジェクトは通常、 およびResultSet
オブジェクトStatement
ですConnection
。
特にConnection
オブジェクトは非常に希少なリソースであり、使用後はすぐに解放する必要があり、Connection
適切なタイミングで適切に閉じられないと、システムのダウンタイムが発生しやすくなります。
Connection
使用の原則は、できるだけ遅く作成し、できるだけ早くリリースすることです。
リソース解放コードを確実に実行できるようにするには、リソース解放コードをfinally
ステートメントに配置する必要があります。
finally {
try {
if(statement!=null)
statement.close();
if(conn!=null)
conn.close();
} catch (SQLException e) {
e.printStackT\frace();
}
}
プログラミング要件
右側のエディターでコードを補足し、次の対応するタスクを完了します。
-
データベース ドライバーをロードします。[プラットフォーム データベース接続のユーザー ( )
user
はroot
、パスワード (password
) は123123
] -
データベースを作成します
mysql_db
。 -
テーブルを作成します
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
データベースとの接続を確立できます。
String url = "jdbc:mysql://localhost:3306/test_db";
Connection conn = DriverManager.getConnection (url,"root","123123" );
SQL
接続時にデータベースを指定する場合、データベースを選択するためのステートメントを記述する必要はありません。
指定されたテーブルにデータを挿入します
接続が確立したら、 table にデータを挿入するsql
ステートメントを作成し、Statement
オブジェクトのメソッドを使用してステートメントexecuteUpdate()
を実行しsql
、テーブル内のデータを変更します (このメソッドはinsert
、update
、 、delete
のステートメントに適用できますsql
)。sql
クエリ ステートメントの場合は、次executeQuery()
のメソッドを使用します。
try {
Statement statement = conn.createStatement();
statement.executeUpdate("insert into table1(column1,column2) values(101,'xxx')");
} catch (SQLException e) {
e.printStackT\frace();
}
準備されたステートメント
上記の直接使用はStatement
、テーブルにデータを挿入するため、SQL
次の例のように、操作中に上記のテーブルから分離されたインジェクションが発生する危険性があります。
String id = "5";
String sql = "delete from tablename where id=" + id;
Statement st = conn.createStatement();
st.executeQuery(sql);//查询到表中将无数据
//如果用户传入的id为“5 or 1=1”,那么将删除表中的所有记录
この状況のSQL
インジェクションを防ぐには、インジェクションをPreparedStatement
効果的に防止します(ステートメントはプログラムの実行前にプリコンパイルされており、パラメータは実行時に動的に渡されます。データベースなどのパラメータに機密文字が含まれている場合でも、それらは命令としてではなく、処理されるパラメータ値のフィールド属性として使用されます)sql
SQL
PreprareStatement
or '1=1'
SQL
PreparedStatement
次のように使用します。
PreparedStatement statement = conn.prepareStatement("insert into table1(column1,column2) values(?,?)");//使用占位符来先占个位置
statement.setInt(1,101);//占位符顺序从1开始,根据数据库中字段相应的类型存入数据
statement.setString(2, "XXX");//也可以使用setObject
statement.executeUpdate();//每执行一个sql语句就需要执行该方法
テーブル内のデータをクエリする
Jdbc
プログラム内でステートメントの実行結果をResultSet
表すために使用されます。Sql
Resultset
実行結果をカプセル化するとき、メソッドはtableResultSet
に似ています。オブジェクトはテーブルのデータ行を指すカーソルを維持します。最初は、カーソルは最初の行の前にあります。カーソルがResultSet.next()
特定のデータを指すようにメソッドを呼び出します。行を選択し、この行のデータを取得するメソッドを呼び出します。
//编写查询sql语句
PreparedStatement statement = conn.prepareStatement("select * from table1");
ResultSet resultSet = statement.executeQuery();//将执行结果给ResultSet
while (resultSet.next()) {//循环判断表中是否还有数据
int id = resultSet.getInt(1);//通过列的索引查询
String name = resultSet.getString("column2");//通过列名查询
}
プログラミング要件
右側のエディターのコードを補足し、前の章で作成したデータベース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
ドライバーがデフォルトで使用する自動コミット モードを使用するのではなく、手動トランザクションサポートを有効にする必要があります。ブール値が に渡されると、自動コミットはオフになります。これは、オンにするのと同じです。ブール値を渡してオンに戻すこともできます。Connection
setAutoCommit()
false
setAutoCommit()
true
Connection conn = DriverManager.getConnection (url,"root","123123" );
conn.setAutoCommit(false);//关闭自动提交开启事务
コミットとロールバック
mysql
データベースではsql
、デフォルトではすべての文が自動的に送信されますが、手動トランザクション サポートに設定すると (つまり、トランザクションが手動で開かれている)、送信する必要があるときに手動で送信できます。
conn.commit();//提交事务
sql
複数のステートメントが一度に送信された場合、sql
それらが合法であるかどうか、また、そのうちの 1 つが違法である場合に他sql
のステートメントを変更する必要があるかどうかを検討する必要があります。トランザクションの基本要素を確保するには、手動で制御へのトランザクションのロールバックsql
: 以下の実行:
try{
Connection conn = DriverManager.getConnection (url,"root","123123" );
conn.setAutoCommit(false);//开启事务
PreparedStatement ps = conn.prepareStatement("insert into table1(column1,column2) values(1,'xx1')");
ps.executeUpdate();
ps = conn.prepareStatement("insert in table1(column1,column2) values(1,'xx1')");
ps.executeUpdate();
conn.commit();//提交事务
} catch (SQLException e) {
try {
conn.rollback();//回滚事务 回滚到你开始事务之前
} catch (SQLException e1) {
e1.printStackT\frace();
}
}
上記のコードが実行された後、データベース内のデータは更新されません。2 番目のステートメントの構文がinsert
間違っているため、トランザクションはロールバックされ、前のステートメントはinsert
無効になります。catch
通常、トランザクションのロールバックはキャプチャのために配置されます。
トランザクションを開始した後は、ロックされている可能性のあるデータを時間内に保持commit
または。rollback
これを使用しない場合でも、使用した場合と同じ効果がrollback()
ありますrollback()
が、使用しないと、rollback()
ロックされたデータが時間内に解放されない可能性があり (時間の経過とともに解放されるまで待つ必要があります)、次のトランザクション操作に影響します。
プログラミング要件
プロンプトに従って、右側のエディタのコードを補足し、新しいSQL
ステートメントと間違ったステートメントを作成して、トランザクションを送信します。最初の新しいSQL
ステートメントはデータベース内で変更する必要があり、後続の間違ったSQL
ステートメントは実行されません。 。
挿入ステートメントを追加するための具体的な要件は次のとおりです。 、Zhao Liu、女性、データのmysql_db
データベーステーブルにstudent
新しいエントリを追加します。id
4
name
sex
age
21
ヒント:トランザクションは各ステートメント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();
}
}
}
}