一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 詳解JDBC使用

詳解JDBC使用

2020-09-22 10:28五月的倉頡 Java教程

JDBC(Java Database Connectivity),即Java數據庫連接,是一種用于執行SQL語句的Java API,可以為多種關系數據庫提供同一訪問,它由一組用Java語言編寫的類和接口組成。

什么是JDBC

JDBC(Java Database Connectivity),即Java數據庫連接,是一種用于執行SQL語句的Java API,可以為多種關系數據庫提供同一訪問,它由一組用Java語言編寫的類和接口組成。JDBC提供了一種基準,根據這種基準可以構建更高級的工具和接口,使數據庫開發人員能夠編寫數據庫應用程序。總而言之,JDBC做了三件事:

1、與數據庫建立連接

2、發送操作數據庫的語句

3、處理結果

JDBC簡單示例

下面的代碼演示了如何利用JDBC從數據庫中查詢若干條符合要求的數據出來,使用的數據庫是MySql。

1、建立一個數據庫和一張表,我的習慣是在CLASSPATH底下建立一個.sql的文件用于存放sql語句

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
create database school;
 
use school;
 
create table student
(
  studentId      int         primary key  auto_increment  not null,
  studentName    varchar(10)                              not null,
  studentAge    int,
  studentPhone  varchar(15)
)
 
insert into student values(null,'Betty', '20', '00000000');
insert into student values(null,'Jerry', '18', '11111111');
insert into student values(null,'Betty', '21', '22222222');
insert into student values(null,'Steve', '27', '33333333');
insert into student values(null,'James', '22', '44444444');
commit;

2、建立一個.properties文件用于存儲MySql連接的幾個屬性。為什么要建立.properties而不在代碼里面寫死,由于這個并不是Java設計模式的分類,就不細講了,只需要記住:從設計的角度看,把內容寫在配置文件中永遠好過把內容寫死在代碼中

?
1
2
3
4
mysqlpackage=com.mysql.jdbc.Driver
mysqlurl=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf-8
mysqlname=root
mysqlpassword=root

3、根據表字段建立實體類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class Student
{
  private int    studentId;
  private String  studentName;
  private int    studentAge;
  private String  studentPhone;
  
  public Student(int studentId, String studentName, int studentAge,
      String studentPhone)
  {
    this.studentId = studentId;
    this.studentName = studentName;
    this.studentAge = studentAge;
    this.studentPhone = studentPhone;
  }
  
  public int getStudentId()
  {
    return studentId;
  }
 
  public String getStudentName()
  {
    return studentName;
  }
 
  public int getStudentAge()
  {
    return studentAge;
  }
 
  public String getStudentPhone()
  {
    return studentPhone;
  }
 
  public String toString()
  {
    return "studentId = " + studentId + ", studentName = " + studentName + ", studentAge = " +
        studentAge + ", studentPhone = " + studentPhone;
  }
}

4、寫一個DBConnection類專門用于向外提供數據庫連接。我這里用了MySql,所以只有一個mysqlConnection,如果還用到了Oracle,當然還可以向外提供一個oracleConnection。把這些連接設為全局的可能有人會想是否會有線程安全問題,這是一個很好的問題。那因為我們只從Connection里面讀取一個PreparedStatement出來,而不會去寫它,只讀不修改,是不會引發線程安全問題的。另外把Connection設置為static的保證了Connection在內存中只有一份,不會占多大資源,每次使用完不調用close()方法去關閉它也沒事。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class DBConnection
  private static Properties properties = new Properties();
  
  static
  {
    /** 要從CLASSPATH下取.properties文件,因此要加"/" */
    InputStream is = DBConnection.class.getResourceAsStream("/db.properties");
    try
    {
      properties.load(is);
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }
  
  /** 這個mysqlConnection只是為了用來從里面讀一個PreparedStatement,不會往里面寫數據,因此沒有線程安全問題,可以作為一個全局變量 */
  public static Connection mysqlConnection = getConnection();
  
  public static Connection getConnection()
  {
    Connection con = null;
    try
    {
      Class.forName((String)properties.getProperty("mysqlpackage"));
      con = DriverManager.getConnection((String)properties.getProperty("mysqlurl"),
          (String)properties.getProperty("mysqlname"),
          (String)properties.getProperty("mysqlpassword"));
    }
    catch (ClassNotFoundException e)
    {
      e.printStackTrace();
    }
    catch (SQLException e)
    {
      e.printStackTrace();
    }
    return con;
  }
}

5、建立一個工具類,用來寫各種方法,專門和數據庫進行交互。這種工具類最好搞成單例的,這樣就不用每次去new出來了(實際上new出來也沒看出來會有什么好處),節省資源

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.xrq.test11;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
 
public class StudentManager
{
  private static StudentManager instance = new StudentManager();
  
  private StudentManager()
  {
    
  }
  
  public static StudentManager getInstance()
  {
    return instance;
  }
  
  public List<Student> querySomeStudents(String studentName) throws Exception
  {
    List<Student> studentList = new ArrayList<Student>();
    Connection connection = DBConnection.mysqlConnection;
    PreparedStatement ps = connection.prepareStatement("select * from student where studentName = ?");
    ps.setString(1, studentName);
    ResultSet rs = ps.executeQuery();
    
    Student student = null;
    while (rs.next())
    {
      student = new Student(rs.getInt(1), rs.getString(2), rs.getInt(3), rs.getString(4));
      studentList.add(student);
    }
    
    ps.close();
    rs.close();
    return studentList;
  }
}

6、寫個main函數去調用一下

?
1
2
3
4
List<Student> studentList = new ArrayList<Student>();
    studentList = StudentManager.getInstance().querySomeStudents("Betty");
    for (Student student : studentList)
      System.out.println(student);

7、看一下運行結果,和數據庫里面的一樣,成功

?
1
2
studentId = 1, studentName = Betty, studentAge = 20, studentPhone = 00000000
studentId = 3, studentName = Betty, studentAge = 21, studentPhone = 22222222

為什么要使用占位符"?"

看一下第5點,大家一定注意到了,寫sql語句的時候用了"?"占位符,當然有美化代碼的因素,不用占位符就要在括號里寫"+"來拼接參數,如果要拼接的參數一多,代碼肯定不好看,可讀性不強。但是除了這個原因,還有另外一個重要的原因,就是避免一個安全問題。假設我們不用占位符寫sql語句,那"querySomeStudents(String name) throws Exception"方法就要這么寫:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public List<Student> querySomeStudents(String studentName) throws Exception
{
  List<Student> studentList = new ArrayList<Student>();
  Connection connection = DBConnection.mysqlConnection;
  PreparedStatement ps = connection.prepareStatement("select * from student where studentName = '" + studentName + "'");
  ResultSet rs = ps.executeQuery();
    
  Student student = null;
  while (rs.next())
  {
    student = new Student(rs.getInt(1), rs.getString(2), rs.getInt(3), rs.getString(4));
    studentList.add(student);
  }
    
  ps.close();
  rs.close();
  return studentList;
}

上面的main函數一樣可以獲取到兩條數據,但是問題來了,如果我這么調用呢:

?
1
2
3
4
5
6
7
public static void main(String[] args) throws Exception
  {
    List<Student> studentList = new ArrayList<Student>();
    studentList = StudentManager.getInstance().querySomeStudents("' or '1' = '1");
    for (Student student : studentList)
      System.out.println(student);
  }

看下運行結果:

?
1
2
3
4
5
studentId = 1, studentName = Betty, studentAge = 20, studentPhone = 00000000
studentId = 2, studentName = Jerry, studentAge = 18, studentPhone = 11111111
studentId = 3, studentName = Betty, studentAge = 21, studentPhone = 22222222
studentId = 4, studentName = Steve, studentAge = 27, studentPhone = 33333333
studentId = 5, studentName = James, studentAge = 22, studentPhone = 44444444

為什么?看下拼接之后的sql語句就知道了:

select * from student where studentName = '' or '1' = '1'

'1'='1'永遠成立,所以前面的查詢條件是什么都沒用。這種問題是有應用場景的,不是隨便寫一下。Java越來越多的用在Web上,既然是Web,那么查詢的時候有一種情況就是用戶輸入一個條件,后臺獲取到查詢條件,拼接sql語句查數據庫,有經驗的用戶完全可以輸入一個"‘'' or '1' = '1",這樣就拿到了庫里面的所有數據了。

JDBC事物

談數據庫必然離不開事物,事物簡單說就是"要么一起成功,要么一起失敗"。那簡單往前面的StudentManager里面寫一個插入學生信息的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
public void addStudent(String studentName, int studentAge, String studentPhone) throws Exception
{
  Connection connection = DBConnection.mysqlConnection;
  PreparedStatement ps = connection.prepareStatement("insert into student values(null,?,?,?)");
  ps.setString(1, studentName);
  ps.setInt(2, studentAge);
  ps.setString(3, studentPhone);
  if (ps.executeUpdate() > 0)
    System.out.println("添加學生信息成功");
  else
    System.out.println("添加學生信息失敗"); 
}
?
1
2
3
4
public static void main(String[] args) throws Exception
{
  StudentManager.getInstance().addStudent("Betty", 17, "55555555");
}

運行就不運行了,反正最后結果是"添加學生信息成功",數據庫里面多了一條數據。注意一下:

1、增刪改用的是executeUpdate()方法,因為增刪改認為都是對數據庫的更新

2、查詢用的是executeQuery()方法,看名字就知道了"Query",查詢嘛

可能有人注意到一個問題,就是Java代碼在insert后并沒有對事物進行commit,數據就添加進數據庫了,也能查出來,這是為什么呢?因為JDK的Connection設置了事物的自動提交。如果在addStudent(...)方法里面這么寫:

?
1
2
Connection connection = DBConnection.mysqlConnection;
connection.setAutoCommit(false);

autoCommit這個屬性原來是true,JDK自然會幫助開發者自動提交事物了。OK,如果要改成手動提交事物的代碼,那么應該這么寫addStudent(...)方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void addStudent(String studentName, int studentAge, String studentPhone) throws Exception
{
  Connection connection = DBConnection.mysqlConnection;
  connection.setAutoCommit(false);
  PreparedStatement ps = connection.prepareStatement("insert into student values(null,?,?,?)");
  ps.setString(1, studentName);
  ps.setInt(2, studentAge);
  ps.setString(3, studentPhone);
  try
  {
    ps.executeUpdate();
    connection.commit();
  }
  catch (Exception e)
  {
    e.printStackTrace();
    connection.rollback();
  }
}

要記得拋異常的時候利用rollback()方法回滾掉事物。

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持服務器之家!

原文鏈接:http://www.cnblogs.com/xrq730/p/4851648.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产免费小视频 | 色屁屁www | 欧美乱码视频 | 99精品久久99久久久久久 | 91天堂国产在线 在线播放 | 国内在线播放 | 农村老妇1乱69系列小说 | 校花被拖到野外伦小说 | 女人被男人躁得好爽免费视频 | 精品亚洲综合在线第一区 | 国产欧美日韩一区二区三区在线 | yjsp妖精视频在线观看免费 | 韩国女主播在线大尺无遮挡 | 日韩影院在线 | 免费久久久久 | 色爱导航 | 天天综合色天天综合色sb | 国产草逼视频 | 全黄h全肉细节修仙玄幻文 全彩调教侵犯h本子全彩妖气he | 欧美日韩国产在线一区 | 调教麻麻成贱m | 红杏劫| 精品91一区二区三区 | 亚洲高清中文字幕 | 97就去干 | 福利片福利一区二区三区 | 国产精品美女福利视频免费专区 | 国产精品一二区 | 男女车车好快的车车免费网站 | 99久久精品免费看国产情侣 | 免费观看成年人视频 | 国产精品露脸国语对白手机视频 | 1024国产基地永久免费 | 热辣小秘书办公室 | 东北老妇露脸xxxxx | 欧美1| 久久精品无码人妻无码AV蜜臀 | 秒播影视 午夜福利毛片 | 超级乱淫伦短篇在车上 | 日韩成人在线影院 | 国产精品第2页 |