最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解JDBC使用

 更新時(shí)間:2017年05月02日 14:57:33   作者:五月的倉(cāng)頡  
JDBC(Java Database Connectivity),即Java數(shù)據(jù)庫(kù)連接,是一種用于執(zhí)行SQL語(yǔ)句的Java API,可以為多種關(guān)系數(shù)據(jù)庫(kù)提供同一訪(fǎng)問(wèn),它由一組用Java語(yǔ)言編寫(xiě)的類(lèi)和接口組成。

什么是JDBC

JDBC(Java Database Connectivity),即Java數(shù)據(jù)庫(kù)連接,是一種用于執(zhí)行SQL語(yǔ)句的Java API,可以為多種關(guān)系數(shù)據(jù)庫(kù)提供同一訪(fǎng)問(wèn),它由一組用Java語(yǔ)言編寫(xiě)的類(lèi)和接口組成。JDBC提供了一種基準(zhǔn),根據(jù)這種基準(zhǔn)可以構(gòu)建更高級(jí)的工具和接口,使數(shù)據(jù)庫(kù)開(kāi)發(fā)人員能夠編寫(xiě)數(shù)據(jù)庫(kù)應(yīng)用程序??偠灾琂DBC做了三件事:

1、與數(shù)據(jù)庫(kù)建立連接

2、發(fā)送操作數(shù)據(jù)庫(kù)的語(yǔ)句

3、處理結(jié)果

JDBC簡(jiǎn)單示例

下面的代碼演示了如何利用JDBC從數(shù)據(jù)庫(kù)中查詢(xún)?nèi)舾蓷l符合要求的數(shù)據(jù)出來(lái),使用的數(shù)據(jù)庫(kù)是MySql。

1、建立一個(gè)數(shù)據(jù)庫(kù)和一張表,我的習(xí)慣是在CLASSPATH底下建立一個(gè).sql的文件用于存放sql語(yǔ)句

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、建立一個(gè).properties文件用于存儲(chǔ)MySql連接的幾個(gè)屬性。為什么要建立.properties而不在代碼里面寫(xiě)死,由于這個(gè)并不是Java設(shè)計(jì)模式的分類(lèi),就不細(xì)講了,只需要記?。?strong>從設(shè)計(jì)的角度看,把內(nèi)容寫(xiě)在配置文件中永遠(yuǎn)好過(guò)把內(nèi)容寫(xiě)死在代碼中

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

3、根據(jù)表字段建立實(shí)體類(lèi)

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、寫(xiě)一個(gè)DBConnection類(lèi)專(zhuān)門(mén)用于向外提供數(shù)據(jù)庫(kù)連接。我這里用了MySql,所以只有一個(gè)mysqlConnection,如果還用到了Oracle,當(dāng)然還可以向外提供一個(gè)oracleConnection。把這些連接設(shè)為全局的可能有人會(huì)想是否會(huì)有線(xiàn)程安全問(wèn)題,這是一個(gè)很好的問(wèn)題。那因?yàn)槲覀冎粡腃onnection里面讀取一個(gè)PreparedStatement出來(lái),而不會(huì)去寫(xiě)它,只讀不修改,是不會(huì)引發(fā)線(xiàn)程安全問(wèn)題的。另外把Connection設(shè)置為static的保證了Connection在內(nèi)存中只有一份,不會(huì)占多大資源,每次使用完不調(diào)用close()方法去關(guān)閉它也沒(méi)事。

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();
    }
  }
  
  /** 這個(gè)mysqlConnection只是為了用來(lái)從里面讀一個(gè)PreparedStatement,不會(huì)往里面寫(xiě)數(shù)據(jù),因此沒(méi)有線(xiàn)程安全問(wèn)題,可以作為一個(gè)全局變量 */
  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、建立一個(gè)工具類(lèi),用來(lái)寫(xiě)各種方法,專(zhuān)門(mén)和數(shù)據(jù)庫(kù)進(jìn)行交互。這種工具類(lèi)最好搞成單例的,這樣就不用每次去new出來(lái)了(實(shí)際上new出來(lái)也沒(méi)看出來(lái)會(huì)有什么好處),節(jié)省資源

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、寫(xiě)個(gè)main函數(shù)去調(diào)用一下

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

7、看一下運(yùn)行結(jié)果,和數(shù)據(jù)庫(kù)里面的一樣,成功

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

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

看一下第5點(diǎn),大家一定注意到了,寫(xiě)sql語(yǔ)句的時(shí)候用了"?"占位符,當(dāng)然有美化代碼的因素,不用占位符就要在括號(hào)里寫(xiě)"+"來(lái)拼接參數(shù),如果要拼接的參數(shù)一多,代碼肯定不好看,可讀性不強(qiáng)。但是除了這個(gè)原因,還有另外一個(gè)重要的原因,就是避免一個(gè)安全問(wèn)題。假設(shè)我們不用占位符寫(xiě)sql語(yǔ)句,那"querySomeStudents(String name) throws Exception"方法就要這么寫(xiě):

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函數(shù)一樣可以獲取到兩條數(shù)據(jù),但是問(wèn)題來(lái)了,如果我這么調(diào)用呢:

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);
  }

看下運(yùn)行結(jié)果:

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語(yǔ)句就知道了:

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

'1'='1'永遠(yuǎn)成立,所以前面的查詢(xún)條件是什么都沒(méi)用。這種問(wèn)題是有應(yīng)用場(chǎng)景的,不是隨便寫(xiě)一下。Java越來(lái)越多的用在Web上,既然是Web,那么查詢(xún)的時(shí)候有一種情況就是用戶(hù)輸入一個(gè)條件,后臺(tái)獲取到查詢(xún)條件,拼接sql語(yǔ)句查數(shù)據(jù)庫(kù),有經(jīng)驗(yàn)的用戶(hù)完全可以輸入一個(gè)"‘'' or '1' = '1",這樣就拿到了庫(kù)里面的所有數(shù)據(jù)了。

JDBC事物

談數(shù)據(jù)庫(kù)必然離不開(kāi)事物,事物簡(jiǎn)單說(shuō)就是"要么一起成功,要么一起失敗"。那簡(jiǎn)單往前面的StudentManager里面寫(xiě)一個(gè)插入學(xué)生信息的方法:

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("添加學(xué)生信息成功");
  else
    System.out.println("添加學(xué)生信息失敗");  
}
public static void main(String[] args) throws Exception
{
  StudentManager.getInstance().addStudent("Betty", 17, "55555555");
}

運(yùn)行就不運(yùn)行了,反正最后結(jié)果是"添加學(xué)生信息成功",數(shù)據(jù)庫(kù)里面多了一條數(shù)據(jù)。注意一下:

1、增刪改用的是executeUpdate()方法,因?yàn)樵鰟h改認(rèn)為都是對(duì)數(shù)據(jù)庫(kù)的更新

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

可能有人注意到一個(gè)問(wèn)題,就是Java代碼在insert后并沒(méi)有對(duì)事物進(jìn)行commit,數(shù)據(jù)就添加進(jìn)數(shù)據(jù)庫(kù)了,也能查出來(lái),這是為什么呢?因?yàn)镴DK的Connection設(shè)置了事物的自動(dòng)提交。如果在addStudent(...)方法里面這么寫(xiě):

Connection connection = DBConnection.mysqlConnection;
connection.setAutoCommit(false);

autoCommit這個(gè)屬性原來(lái)是true,JDK自然會(huì)幫助開(kāi)發(fā)者自動(dòng)提交事物了。OK,如果要改成手動(dòng)提交事物的代碼,那么應(yīng)該這么寫(xiě)addStudent(...)方法:

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();
  }
}

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

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!

相關(guān)文章

  • Spring?Security中自定義cors配置及原理解析

    Spring?Security中自定義cors配置及原理解析

    在Spring框架中,通過(guò)自定義CORS配置可根據(jù)實(shí)際情況調(diào)整URL的協(xié)議、主機(jī)、端口等,以適應(yīng)"同源安全策略",配置原理涉及CorsConfigurer和CorsFilter,自定義配置需要注意@Configuration注解、方法名以及可能的@Autowired注解
    2024-10-10
  • Java發(fā)展史之Java由來(lái)

    Java發(fā)展史之Java由來(lái)

    本文主要給大家簡(jiǎn)單講解了一下java的發(fā)展史,詳細(xì)說(shuō)明了java的由來(lái)以及如何一步步發(fā)展起來(lái)的,想了解的小伙伴可以來(lái)參考下
    2016-10-10
  • springboot全局字符編碼設(shè)置解決亂碼問(wèn)題

    springboot全局字符編碼設(shè)置解決亂碼問(wèn)題

    這篇文章主要介紹了springboot全局字符編碼設(shè)置解決亂碼問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Spring Boot 簡(jiǎn)單使用EhCache緩存框架的方法

    Spring Boot 簡(jiǎn)單使用EhCache緩存框架的方法

    本篇文章主要介紹了Spring Boot 簡(jiǎn)單使用EhCache緩存框架的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • Java的stream流多個(gè)字段排序的實(shí)現(xiàn)

    Java的stream流多個(gè)字段排序的實(shí)現(xiàn)

    本文主要介紹了Java的stream流多個(gè)字段排序的實(shí)現(xiàn),主要是兩種方法,第一種是固定多個(gè)字段排序和第二種動(dòng)態(tài)字段進(jìn)行排序,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • Java中的位運(yùn)算符、移位運(yùn)算詳細(xì)介紹

    Java中的位運(yùn)算符、移位運(yùn)算詳細(xì)介紹

    這篇文章主要介紹了Java中的位運(yùn)算符、移位運(yùn)算,有需要的朋友可以參考一下
    2013-12-12
  • Spring整合Mybatis框架方法剖析

    Spring整合Mybatis框架方法剖析

    這篇文章主要為大家介紹了Spring整合Mybatis框架方法剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • SpringCloud Alibaba使用Seata處理分布式事務(wù)的技巧

    SpringCloud Alibaba使用Seata處理分布式事務(wù)的技巧

    在傳統(tǒng)的單體項(xiàng)目中,我們使用@Transactional注解就能實(shí)現(xiàn)基本的ACID事務(wù)了,隨著微服務(wù)架構(gòu)的引入,需要對(duì)數(shù)據(jù)庫(kù)進(jìn)行分庫(kù)分表,每個(gè)服務(wù)擁有自己的數(shù)據(jù)庫(kù),這樣傳統(tǒng)的事務(wù)就不起作用了,那么我們?nèi)绾伪WC多個(gè)服務(wù)中數(shù)據(jù)的一致性呢?跟隨小編一起通過(guò)本文了解下吧
    2021-06-06
  • 如何把本地jar包導(dǎo)入maven并pom添加依賴(lài)

    如何把本地jar包導(dǎo)入maven并pom添加依賴(lài)

    這篇文章主要介紹了如何把本地jar包導(dǎo)入maven并pom添加依賴(lài),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 使用springboot配置和占位符獲取配置文件中的值

    使用springboot配置和占位符獲取配置文件中的值

    這篇文章主要介紹了使用springboot配置和占位符獲取配置文件中的值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02

最新評(píng)論

浪卡子县| 嘉峪关市| 海林市| 金阳县| 绥中县| 建湖县| 舒城县| 寿宁县| 阿鲁科尔沁旗| 樟树市| 嘉黎县| 武清区| 阿合奇县| 兴化市| 赞皇县| 儋州市| 梨树县| 浮山县| 西畴县| 遂溪县| 东丰县| 湛江市| 交口县| 全州县| 英超| 郧西县| 睢宁县| 寻甸| 丹江口市| 玛多县| 二手房| 四川省| 十堰市| 涿州市| 旌德县| 噶尔县| 会同县| 余庆县| 大石桥市| 巢湖市| 漯河市|