JDBC使用+數據庫連接池+springJDBC


一、JDBC基本概念和下載

JDBC(Java DataBase Connectivity),通俗來講就是用java語言操作數據庫

  • 本質
    sun公司定義的一套操作所有關系型數據庫的規則,即接口。
    各個數據庫廠商去實現這套接口,提供數據庫驅動jar包。我們可以使用這套接口(JDBC)編程,真正執行的代碼是驅動jar包中的實現類。
下載

去mysql官網下載其他版本

點擊直接下載5.1.40
下載截圖:

二、詳細步驟

環境准備

在mysql中創建一個db3的數據庫,並創建一個user表插入幾條用戶信息的數據

-- 創建一個編碼為utf8 的數據庫db3
create database db3 character set utf8;
use db3;

-- 創建user表
create table user (
	id int primary key auto_increment, 
	name varchar(32), -- 用戶名
	password varchar(32) -- 密碼
);

-- 添加一條數據
insert into user ( name, password ) values ( 'zhangsan', 123456 );
工程導入驅動jar包
  • 1、下載之后解壓
  • 2、復制mysql的驅動包mysql-connector-java-5.1.40-bin.jar到工程上新建的lib目錄下
  • 3、右鍵.jar文件,選擇add As Library 添加成庫

1、加載數據庫驅動

//注冊驅動
Class.forName("com.mysql.jdbc.Driver");

2、建立連接

String url = "jdbc:mysql://localhost:3306/db3";			
String userName = "root";			
String password = "root";			
//獲取與數據庫的鏈接
Connection conn = DriverManager.getConnection(url, userName, password);

注意:如果是localhost:3306, mysql可以簡寫為jdbc:mysql:///db3

  • connection 對象常用方法:
方法 描述
createStatement() 創建可執行sql的statement對象(容易產生sql注入問題)
prepareStatement(sql) sql參數使用?作占位符,返回一個預編譯后的prepareStatement對象(解決了sql注入問題)
setAutoCommit(boolean autoCommit) 設置事務是否自動提交:在執行sql之前開啟事務
commit() 提交事務:當所有sql都執行完提交事務
rollback() 回滾事務:在catch中回滾事務

3、執行SQL語句

  • Statement 對象常用方法:
方法 描述
boolean execute(String sql) 可執行任意的sql語句,返回布爾值(一般不用)
int executeUpdate(String sql) 執行DML(insert、update、delete)語句、DDL(create,alter、drop)語句,返回影響的行數(常用)
ResultSet executeQuery(String sql) 執行DQL(select)語句,返回一個ResultSet對象(常用)
//使用statement 如:添加一條用戶數據
//1、定義sql語句
String sql = "insert into user ( name, password ) values ( 'lisi', 1234 )";
//2、獲取執行sql語句的對象
Statement st = conn.createStatement();
//3、定義sql語句並執行 如果count>0 則表示添加成功,否則添加失敗
int count = st.executeUpdate(sql);

//推薦使用prepareStatement,如:查詢登錄用戶是否匹配
//1、定義sql語句
String sql = "select * from user where name=? and password=?";
//2、獲取執行sql語句的對象,需要傳入sql,進行預編譯
PrepareStatement pst = conn.prepareStatement(sql);
//3、設置值setXxx, Xxx代表獲取字段的類型,如:setInt、setString
pst.setString(1, "lisi");
pst.setString(2, "1234");
//4、執行sql,不需要傳遞sql,直接返回結果對象
ResultSet rs = pst.executeQuery();

if(rs.next()){
  //登錄成功
}

4、獲取查詢的結果集

  • ResultSet常用方法
//1、獲取行,返回末尾是否有數據, 有則返回false,沒有返回true
boolean next() //游標向下移動一行

//2.獲取數據 Xxx 代表數據類型。 如:getInt(1) getString("name")
//根據列的編號獲取值 從1開始
getXxx(int index);
//根據列的名稱獲取值
getXxx(String columName);

5、釋放資源

1、需要釋放的對象:ResultSet 結果集,Statement 語句,Connection 連接。
2、釋放原則:先開的后關,后開的先關。ResultSet --> Statement --> Connection。
3、在finally中執行。

ResultSet rs = null;
Statement st = null;
Connection conn = null;
try{
  //JDBC操作數據庫代碼實現
}catch{
  //異常處理
}finally{
  if(rs != null){
    try {
      rs.close();
    } catch (SQLException throwables){
      throwables.printStackTrace();
    }
  }
  if(stm != null){
    try {
        stm.close();
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }
  }
  if(conn != null){
    try {
        conn.close();
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }
  }
}

三、JDBC實現工具類 jdbcUtils

1、在src問件下創建一個jdbc.properties文件,用於修改配置文件,而不用修改代碼

加上?characterEncoding=utf8 可以解決中文亂碼問題

url=jdbc:mysql://localhost:3306/db3?characterEncoding=utf8
username=root
password=root
driver=com.mysql.jdbc.Driver
2、創建一個utils包,在包下創建一個JdbcUtils類

主要實現的方法:

  • 1、得到數據庫的連接對象 getConnection()
    • 使用配置文件代替傳遞的參數
  • 2、關閉所有打開的資源
    • close(PreparedStatement pst, Connection conn)、
    • close(ResultSet rs, PreparedStatement pst, Connection conn)
package com.yj.utils;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {
    private static String url = null;
    private static String username = null;
    private static String password = null;
    private static String driver = null;

    //文件的讀取,只需要讀取一次即可拿到這些值。使用靜態代碼塊
    static {
        try {
            //1、創建properties集合類
            Properties pro = new Properties();
            //2、獲取src路徑下的jdbc.properties文件的方式--->ClassLoader 類加載器
            InputStream rs = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //3、加載文件
            pro.load(rs);
            //4、獲取值並賦值
            url = pro.getProperty("url");
            username = pro.getProperty("username");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //5、注冊驅動
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 得到數據庫連接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,username,password);
    }

    //關閉所有打開的資源
    public static void close(PreparedStatement pst, Connection conn){
        if(pst != null){
            try {
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close(ResultSet rs, PreparedStatement pst, Connection conn){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(pst != null){
            try {
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
3、使用工具類對db3數據庫進行CRUD
package com.yj.jdbc;

import com.yj.utils.JdbcUtils;
import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Demo02 {
    //向數據庫新增一條用戶數據
    @Test
    public void insert(){
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "insert into user (name, password) values (?, ?)";
            pst = conn.prepareStatement(sql);
            pst.setString(1,"王五");
            pst.setString(2,"123");
            int count = pst.executeUpdate();
            if(count > 0){
                System.out.println("添加成功");
            }else{
                System.out.println("添加失敗");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(pst, conn);
        }
    }

    //修改數據 (修改id=2這條數據的密碼為123456)
    @Test
    public void update (){
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "update user set password = ? where id = 2";
            pst = conn.prepareStatement(sql);
            pst.setString(1,"123456");
            int count = pst.executeUpdate();
            if(count > 0){
                System.out.println("修改成功");
            }else{
                System.out.println("修改失敗");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(pst, conn);
        }
    }

    //刪除數據 (刪掉id=2這條數據)
    @Test
    public void delete(){
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "delete from user where id = 2";
            pst = conn.prepareStatement(sql);
            int count = pst.executeUpdate();
            if(count > 0){
                System.out.println("刪除成功");
            }else{
                System.out.println("刪除失敗");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(pst, conn);
        }
    }

    //查詢 (查詢id=1這條數據並打印所有字段)
    @Test
    public void retrieve(){
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "select * from user where id = ?";
            pst = conn.prepareStatement(sql);
            pst.setInt(1,1);
            rs = pst.executeQuery();
            if(rs.next()){
                System.out.println("id=" + rs.getInt("id"));
                System.out.println("name=" + rs.getString("name"));
                System.out.println("password=" + rs.getString("password"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(rs, pst, conn);
        }
    }
}

四、使用數據庫連接池

概念

其實就是一個容器(集合),存放數據庫連接的容器。

好處
  • 1、節約資源。
  • 2、用戶訪問高效。
如何實現
  • 1、接口:DataSource 下:
    • 獲取連接:getConnection()
    • 歸還連接:close()
  • 2、一般我們不去實現它,由數據庫廠商來實現,常用的有:

1、C3P0的使用

  • 1、導入jar包(兩個)c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar,不要忘記導入數據庫驅動的jar包
  • 2、定義配置文件
    • 名稱:c3p0.properties 或者 c3p0-config.xml
    • 位置:src文件目錄下
<c3p0-config>
  <!-- 使用默認的配置讀取連接池對象 -->
  <default-config>
  	<!--  連接參數 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db3?characterEncoding=utf8</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 連接池參數 -->
    <!--初始化申請的連接數量-->
    <property name="initialPoolSize">5</property>
    <!--最大的連接數量-->
    <property name="maxPoolSize">10</property>
    <!--超時時間-->
    <property name="checkoutTimeout">3000</property>
  </default-config>

  <!-- 使用name參數讀取連接池對象 -->
  <named-config name="otherc3p0"> 
    <!--  連接參數 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db3?characterEncoding=utf8</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 連接池參數 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">8</property>
    <property name="checkoutTimeout">1000</property>
  </named-config>
</c3p0-config>
  • 3、創建數據庫連接對象:comboPooleDataSource
//ComboPooledDataSource(String name)傳入參數代表上面帶有name屬性的配置
//不傳為默認
DataSource ds = new ComboPooledDataSource(); 
  • 4、獲取連接
Connection conn = ds.getConnection();

2、Druid的使用

  • 1、導入jar包 druid-1.0.9.jar

  • 2、定義配置文件,properties形式,任意名稱,任意目錄
    如:druid.properties

url=jdbc:mysql://localhost:3306/db3?characterEncoding=utf8
username=root
password=root
driver=com.mysql.jdbc.Driver
# 初始化連接數量
initialSize=5
# 最大連接數
maxActive=10
# 最大等待時間
maxWait=3000
  • 3、加載配置文件
Properties pro = new Properties();
InputStrean is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
  • 4、獲取數據庫連接池對象:DruidDataSourceFactory
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
  • 5、獲取連接
Connection conn = ds.getConnection();
  • 6、也可以定義工具類來提高代碼的復用性:只要實現獲取連接,歸還連接

五、Spring JDBC

提供了一個JDBCTemplate對象簡化JDBC的開發

1、使用步驟

//ds為數據庫連接對象
JdbcTemplate template = new JdbcTemplate(ds);
  • 3、調用JdbcTemplate的方法來完成CRUD的操作,不需要調用close方法
方法 描述
update() 執行DML語句。增、刪、改語句
queryForMap() 將查詢1條結果集封裝為map集合,將列名作為key,將值作為value
queryForList() 查詢結果將結果集封裝為list集合(注意:將每一條記錄封裝為一個Map集合,再將Map集合裝載到List集合中)
query() 查詢結果,將結果封裝為JavaBean對象(參數RowMapper,一般我們使用BeanPropertyRowMapper實現類。可以完成數據到JavaBean的自動封裝)
queryForObject() 將結果封裝為對象,一般用於聚合函數的查詢

2、代碼實現一個簡單的例子

准備表的數據
-- 刪除表的內容
truncate table user; 

-- 添加一些數據
insert into user values (null, "張三", "abcd"), (null, "李四", "bbb"), (null, "王五", "ccc");
代碼實現例子
    1. 修改1號數據的 password 為 aaa
    1. 添加一條記錄
    1. 刪除剛才添加的記錄
    1. 查詢id為1的記錄,將其封裝為Map集合
    1. 查詢所有記錄,將其封裝為List
    1. 查詢所有記錄,將其封裝為Emp對象的List集合
    1. 查詢總記錄數
public class Demo04 {
  //使用c3p0來創建數據庫連接對象
  private JdbcTemplate template = new JdbcTemplate(new ComboPooledDataSource());

  //1. 修改1號數據的 password 為 aaa
  @Test
  public void test1(){
      String sql = "update user set password = 'aaa' where id = 1";
      int count = template.update(sql);
      if(count>0){
          System.out.println("修改成功");
      }
  }
  //2. 添加一條記錄
  @Test
  public void test2(){
      String sql = "insert into user values (null, ?, ?)";
      int count = template.update(sql, "小明", "ddd");
      if(count>0){
          System.out.println("添加成功");
      }
  }
  // 3. 刪除剛才添加的記錄
  @Test
  public void test3(){
      String sql = "delete from user where id = ?";
      int count = template.update(sql, 4);
      if(count>0){
          System.out.println("刪除成功");
      }
  }
  // 4. 查詢id為1的記錄,將其封裝為Map集合
  @Test
  public void test4(){
      String sql = "select * from user where id = 1";
      Map<String, Object> map = template.queryForMap(sql);
      System.out.println(map); //{id=1, name=張三, password=aaa}
  }
  // 5. 查詢所有記錄,將其封裝為List
  @Test
  public void test5(){
      String sql = "select * from user";
      List<Map<String, Object>> list = template.queryForList(sql);
      System.out.println(list);
      //[{id=1, name=張三, password=aaa}, {id=2, name=李四, password=bbb}, {id=3, name=王五, password=ccc}]
  }
  // 6. 查詢所有記錄,將其封裝為Emp對象的List集合
  @Test
  public void test6(){
      String sql = "select * from user";
      List<User> list = template.query(sql, new BeanPropertyRowMapper<User>(User.class));
      System.out.println(list);
      //[User{id=1, name='張三', password='aaa'}, User{id=2, name='李四', password='bbb'}, User{id=3, name='王五', password='ccc'}]
  }
  // 7. 查詢總記錄數
  @Test
  public void test7(){
      String sql = "select count(id) from user";
      Long total = template.queryForObject(sql, Long.class);
      System.out.println(total); //3
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM