一、JDBC基本概念和下載
JDBC(Java DataBase Connectivity),通俗來講就是用java語言操作數據庫
- 本質
sun公司定義的一套操作所有關系型數據庫的規則,即接口。
各個數據庫廠商去實現這套接口,提供數據庫驅動jar包。我們可以使用這套接口(JDBC)編程,真正執行的代碼是驅動jar包中的實現類。
下載
點擊直接下載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、一般我們不去實現它,由數據庫廠商來實現,常用的有:
- C3P0: 數據庫連接池技術
- Druid:數據庫連接池實現技術,由阿里巴巴提供的
- 點擊直接下載C3P0-0.9.5.2 和 Druid-1.0.9 jar包
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、使用步驟
- 1、導入jar包(5個)
- 2、創建JdbcTemplate對象。依賴於數據源DataSource
//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號數據的 password 為 aaa
-
- 添加一條記錄
-
- 刪除剛才添加的記錄
-
- 查詢id為1的記錄,將其封裝為Map集合
-
- 查詢所有記錄,將其封裝為List
-
- 查詢所有記錄,將其封裝為Emp對象的List集合
-
- 查詢總記錄數
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
}
}
