Java學習路線-43:JDBC數據庫開發入門

5-JDBC數據庫開發入門

課時1-2 1.什麼是JDBC

JDBC 數據庫訪問規範

應用程序 <-> JDBC <-> MySQL驅動 <-> MySQL
                 <-> Oracle驅動 <-> Oracle

導入jar包
加載驅動 Class.forName(‘類名’)
給出url、username、password
使用DriverManager類得到Connection類

maven導入依賴

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.18</version>
    </dependency>
</dependencies>

連接示例

import java.sql.Connection;
import java.sql.DriverManager;

class Demo {

    // MySQL >= 8.0 配置參數
    private static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    private static final String DB_URL = "jdbc:mysql://localhost:3306/data";
    private static final String USER = "root";
    private static final String PASSWORD = "123456";


    public static void main(String[] args) throws Exception {
        // 註冊 JDBC 驅動
        Class.forName(JDBC_DRIVER);

        // 等效於
        // com.mysql.cj.jdbc.Driver driver = new com.mysql.cj.jdbc.Driver();
        // DriverManager.registerDriver(driver);

        // 打開鏈接
        Connection conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
        
        // 關閉鏈接
        conn.close();

    }

}

所有的java.sql.Driver實現類,都提供了static代碼塊,
塊內代碼把自己註冊到DriverManager中

jdbc4.0之後 每個驅動jar包中,在META-INF/services目錄下提供了一個java.sql.Driver文件
內容就是該接口的實現類名稱

課時3 3.JDBC完成增、刪、改、查

1、增、刪、改

// 發送DML, DDL
int Statement.executeUpdate(String sql);

代碼示例

// 註冊 JDBC 驅動
Class.forName(JDBC_DRIVER);

// 打開鏈接
Connection conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
Statement statement = conn.createStatement();

// 增刪改
// String sql = "insert into student(sname) values('陸小鳳')";
// String sql = "update student set sname='花無缺' where sid=4";
String sql = "delete from student where sid=4";

int ret = statement.executeUpdate(sql);
System.out.println(ret);

// 關閉鏈接
conn.close();

2、查詢

ResultSet executeQuery(String querySql);
boolean ResultSet.next();

// 獲取列數據
ResultSet.getString()
ResultSet.getObject()
ResultSet.getInt()
ResultSet.getDouble()

行光標

beforeFirst <- 默認光標位置
first
last
AfterLast
// 打開鏈接
Connection conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
Statement statement = conn.createStatement();

// 查詢
String sql = "select * from student";

ResultSet ret = statement.executeQuery(sql);
while (ret.next()){
    // 通過列序號獲取
    int uid = ret.getInt(1);
    // 通過列名稱獲取
    String name = ret.getString("sname");
    System.out.println(uid + ", " + name);
}

// 關閉資源
ret.close();
statement.close();
conn.close();

課時4 4.JDBC之代碼規範化

// 定義
try{
    // 實例化
}
finally{
    // 關閉資源
}

課時5 5.結果集光標與元數據

JBDC主要的類

DriverManager

Connection conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);

Statement statement = conn.createStatement(); 
    int executeUpdate(String sql)    // 執行增、刪、改
    ResultSet executeQuery(String sql)  // 執行查詢
    boolean execute(String sql)         // 執行增、刪、改、查

ResultSet滾動結果集
一個二維表格,內部維護了一個行光標(遊標)

next() // 最常用

beforeFirst()
afterLast()
first()
last()
getRow()
absolute()
relative()

isBeforeFirst()
isAfterLast()
isFirst()
isLast()

元數據

// 元數據 
ResultSetMetaData ResultSet.getMetaData()

// 獲取結果集列數
int ResultSetMetaData.getColumnCount()

// 獲取指定列的列名
String ResultSetMetaData.getColumnName(int colIndex)

課時6 6.結果集的特性(是否可滾動、是否敏感、是否可更新)

確定結果集特性
1、是否可滾動
2、是否敏感
3、是否可更新

// 不滾動, 不敏感,不可更新
Statement createStatement()

// 滾動支持
Statement createStatement(int resultSetType, int resultSetConcurrency)        

resultSetType:
ResultSet.TYPE_FORWARD_ONLY  // 不滾動
ResultSet.TYPE_SCROLL_INSENSITIVE // 滾動,不隨數據庫變化而變化
ResultSet.TYPE_SCROLL_SENSITIVE // 滾動,不隨數據庫變化而變化

resultSetConcurrency // 是否通過修改結果集二反向影響數據庫
ResultSet.CONCUR_READ_ONLY // 結果集只讀 
ResultSet.CONCUR_UPDATABLE // 結果集可更新

課時7 7.PreparedStatement的用法

PreparedStatement是Statement子接口
1、防止SQL注入攻擊
2、提高代碼可讀性,可維護性
3、提高效率

// 打開鏈接
Connection conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);

// 使用預處理查詢, 使用?佔位
String sql = "select * from student where sid = ?";
PreparedStatement statement = conn.prepareStatement(sql);

// 爲參數賦值
statement.setInt(1, 1);

// 獲取數據
ResultSet ret = statement.executeQuery();
while (ret.next()){
    String name = ret.getString("sname");
    System.out.println(name);
}

// 關閉資源
ret.close();
statement.close();
conn.close();

課時8 8.預處理的原理

服務器工作:
(1)校驗:sql語句的語法
(2)編譯:爲一個與函數相似的東西
(3)執行:調用函數

PreparedStatement
(1)先將sql發給數據庫,數據庫先進行校驗
(2)執行的時候只發送參數

課時9 9.mysql的預編譯功能默認是關閉的

prepare myfun from 'select * from student where sid = ?'
set @uid=1
execute myfun using @uid

設置連接參數:
useServerPrepStmts=true
cachePrepStmts=true

DB_URL = "jdbc:mysql://localhost:3306/data?useServerPrepStmts=true&cachePrepStmts=true";

課時10 10.JdbcUtils1.0小工具

JdbcUtils.java

package util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class JdbcUtils {
    // 配置文件路徑
    private static String dbconfig = "dbconfig.properties";

    private static Properties prop = null;

    // 靜態代碼塊只執行一次
    static {
        // 初始化數據庫配置參數
        try {
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream(dbconfig);
            prop = new Properties();
            prop.load(in);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 加載驅動
        try{
            Class.forName(prop.getProperty("driver"));
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(
                prop.getProperty("url"),
                prop.getProperty("username"),
                prop.getProperty("password")
        );
    }

    public static void main(String[] args) throws SQLException {
        Connection conn = getConnection();
        System.out.println(conn);
    }

}

dbconfig.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/data
username=root
password=123456

課時11 11.面向接口編程

DAO模式
data access object
寫一個類,把訪問數據庫的代碼封裝起來
DAO在數據庫與業務邏輯(service)之間
實體域,即操作的對象

DAO模式步驟
(1)提供一個DAO接口
(2)提供一個DAO接口的實現類
(3)在編寫一個DAO工廠,Service通過工廠來獲取DAO實現

daoconfig.properties

UserDaoClassName=UserDaoImpl

UserDao.java

public interface UserDao {
}

UserDaoImpl.java

public class UserDaoImpl implements UserDao{

}

DaoFactory.java

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class DaoFactory {
    // 配置文件路徑
    private static String dbconfig = "daoconfig.properties";

    private static Properties prop = null;

    // 靜態代碼塊只執行一次
    static {
        // 初始化數據庫配置參數
        try {
            InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream(dbconfig);
            prop = new Properties();
            prop.load(in);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 返回一個UserDao的具體實現類
     */
    public static UserDao getUserDao() {
        String daoClassName = prop.getProperty("UserDaoClassName");

        // 通過反射創建實現類的對象
        try {
            Class Clazz = Class.forName(daoClassName);
            return (UserDao) Clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

課時12 12.修改案例,其中dao層爲jdbc

User.java

public class User {
    private String username;
    private int age;

    public String getUsername() {
        return username;
    }

    public int getAge() {
        return age;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
    }
}

daoconfig.properties

UserDaoClassName=UserDaoImpl

UserDao.java

public interface UserDao {
    public void addUser(User user);
    public User getUserByUsername(String username);
}

UserDaoImpl.java

import util.JdbcUtils;

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

/**
 * create table user(
 * id int primary key auto_increment,
 * username varchar(50),
 * age int
 * )
 */
public class UserDaoImpl implements UserDao {

    /**
     * ORM 對象關係映射
     * @param user
     */
    @Override
    public void addUser(User user) {
        Connection conn = null;
        PreparedStatement statement = null;

        try {
            // 得到連接
            conn = JdbcUtils.getConnection();
            String sql = "insert into user(username, age) values(?, ?)";

            // 準備模板
            statement = conn.prepareStatement(sql);

            // 賦值
            statement.setString(1, user.getUsername());
            statement.setInt(2, user.getAge());

            // 執行
            statement.executeUpdate();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (statement != null) {
                    statement.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {

            }
        }
    }

    @Override
    public User getUserByUsername(String username) {

        Connection conn = null;
        PreparedStatement statement = null;

        try {
            // 得到連接
            conn = JdbcUtils.getConnection();
            String sql = "select * from user where username = ? limit 1";

            // 準備模板
            statement = conn.prepareStatement(sql);

            // 賦值
            statement.setString(1, username);

            // 執行
            ResultSet resultSet = statement.executeQuery();
            if(resultSet.next()){
                User user = new User();
                user.setUsername(resultSet.getString("username"));
                user.setAge(resultSet.getInt("age"));
                return user;
            }
            else{
                return null;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (statement != null) {
                    statement.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {

            }
        }
    }
}


DaoFactory.java

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class DaoFactory {
    // 配置文件路徑
    private static String dbconfig = "daoconfig.properties";

    private static Properties prop = null;

    // 靜態代碼塊只執行一次
    static {
        // 初始化數據庫配置參數
        try {
            InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream(dbconfig);
            prop = new Properties();
            prop.load(in);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 返回一個UserDao的具體實現類
     */
    public static UserDao getUserDao() {
        String daoClassName = prop.getProperty("UserDaoClassName");

        // 通過反射創建實現類的對象
        try {
            Class Clazz = Class.forName(daoClassName);
            return (UserDao) Clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

Service.java

// 添加測試
UserDao userDao = DaoFactory.getUserDao();

User user = new User();
user.setUsername("小明");
user.setAge(23);
userDao.addUser(user);

// 查詢測試
User user1 = userDao.getUserByUsername("小明");
System.out.println(user1);

課時13 13.util包下的Date與sql包下的時間類型之間的轉換

Data -> java.sql.Data
Time -> java.sql.Time
Timestamp -> java.sql.Timestamp

領域對象中所有屬性不能出現java.sql包內容
繼承關係

java.util.Date
    -java.sql.Date

父類轉子類:util.Data -> sql.Date、Time、Timestamp

java.util.Date UtilDate = new java.util.Date();
long longDate = UtilDate.getTime();
java.sql.Date sqlData = new java.sql.Date(longDate);

子類轉父類:sql.Date、Time、Timestamp -> util.Data

java.util.Date UtilDate = new java.sql.Date(System.currentTimeMillis());

課時14 14.大數據

可以將文件存入MySQL
my.ini配置
max_allowed_packet=10485760

課時15 15.批處理

批處理只針對更新(增,刪,改)
一次向服務器發送多條sql語句
開啓批處理參數
rewriteBatchedStatements=true

dbconfig.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/data?rewriteBatchedStatements=true
username=root
password=123456
import util.JdbcUtils;

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

class Demo {
    public static void main(String[] args) throws SQLException {
        Connection conn = JdbcUtils.getConnection();
        String sql = "insert into user(username)values(?)";
        PreparedStatement statement = conn.prepareStatement(sql);

        for(int i=0; i<10000; i++){
            statement.setString(1, "name" + i);
            statement.addBatch(); // 裝箱
        }

        long start = System.currentTimeMillis();
        statement.executeBatch(); // 提交數據
        long end = System.currentTimeMillis();
        System.out.println(end - start); // 107
    }
}
發佈了1418 篇原創文章 · 獲贊 370 · 訪問量 130萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章