《Tomcat與Java Web開發技術詳解》閱讀梳理 第八章 訪問資料庫

安小然U發表於2020-11-17

JDBC

JDBC(java DataBase Connectivity)是java與資料庫連線的紐帶。JDBC封裝了java與資料庫通訊的細節。程式設計師只需要通過JDBC API就可以與資料庫伺服器通訊。
優點:
1.簡化程式碼
2.使java程式碼不依賴具體資料庫伺服器。
JDBC API位於java.sql(大部分)和javax.sql(高階特性)包中。
在這裡插入圖片描述

JDBC的實現

JDBC的實現包括三個部分
1.JDBC驅動管理器:java.sql.DriverManger類,由Oracle公司實現,負責註冊特定JDBC驅動器,以及根據特定驅動器建立與資料庫的連線。
2.JDBC驅動器API:由Oracle公司制定,其中最主要的介面是java.sql.Driver介面。
3.JDBC驅動器,由資料庫供應商,或者其他第三方工具提供商建立,也成為JDBC驅動程式。JDBC驅動器實現了JDBC驅動器API負責與與特定資料庫連線。
在這裡插入圖片描述
JDBC API:java程式通過它來訪問各種資料庫。
JDBC驅動器 API:具體的JDBC驅動器需要實現它(java.sql.Driver)
因此實際上java程式與資料庫伺服器的連線是由JDBC驅動器完成的。

橋樑設計模式

DriverManager類運用橋樑設計模式,是java程式與各種JDBC驅動器連線的橋樑。
應用程式只和JDBC API打交道,JDBC API依賴DriverManager類來管理JDBC驅動器。
在這裡插入圖片描述

java.sql包中的介面和類

JDBC API主要在java.sql包中,主要有
1.Driver介面:驅動器
2.DriverManager類:驅動管理器
3.Connection介面:表示資料庫連線
4.Statement介面:負責執行SQL語句
5.PreparedStatement介面:負責執行預準備的SQL語句
6.CallableStatement介面:負責執行SQL儲存過程。
7.ResultSet介面:表示SQL查詢語句返回的結果集。
在這裡插入圖片描述

DRiverManager類方法

在這裡插入圖片描述
在這裡插入圖片描述

Connection介面方法

在這裡插入圖片描述

Statement介面

在這裡插入圖片描述

PrepareStatement介面方法

PrepareStatement是statement的子介面,statement執行的sql語句引數都是固定的。而prepareStatement的引數可以動態修改。每次通過statement執行sql語句都要重新編譯。而prepareStatement只需編譯一次,然後可以多次執行。
例子
PreparedStatement

PreparedStatement preparedStatement = connection.prepareStatement("select id,username,? from user where id = ?");
        //第一個?是password
        preparedStatement.setString(1,"password");
        //第二個?是10
        preparedStatement.setInt(2,2);

Statement

 Statement statement = connection.createStatement();
        statement.execute("select * from user where id = 10");

ResultSet介面的方法

ResultSet介面表示select查詢語句得到的結果集。
d
在這裡插入圖片描述

  while (resultSet.next()){
            //根據索引
            System.out.println(resultSet.getString(1));
            //根據欄位名
            System.out.println(resultSet.getString("username"));
        }

訪問資料庫程式的步驟

1.載入JDBC驅動器

Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");

2.註冊資料庫驅動器

DriverManager.registerDriver((Driver) aClass.newInstance());

這一步實際上並不是必須的
因為在com.mysql.cj.jdbc.Driver內部有這麼一段靜態程式碼

static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }

他實際上會在載入的時候就自己把自己註冊了
3.與資料庫建立連線

 String url = "jdbc:mysql://localhost:3306/db1";
        Connection connection = DriverManager.getConnection(url,"root","root");

url的格式
jdbc:[資料庫名]:[資料庫伺服器IP]:[埠號]/[資料庫名]?[預設配置]

完整例子

//1.載入並註冊驅動
        Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");
        //DriverManager.registerDriver((Driver) aClass.newInstance());
        //2.與資料庫建立連線
        String url = "jdbc:mysql://localhost:3306/db1";
        Connection connection = DriverManager.getConnection(url,"root","root");
        //3.用PreparedStatement
        PreparedStatement preparedStatement = connection.prepareStatement("select id,username,? from user where id = ?");
        //第一個?是password
        preparedStatement.setString(1,"password");
        //第二個?是10
        preparedStatement.setInt(2,2);
        preparedStatement.execute();
        //獲取ResultSet物件
        ResultSet resultSet1 = preparedStatement.getResultSet();
        while (resultSet1.next()){
            //根據索引
            System.out.println(resultSet1.getInt(1));
            //根據欄位名
            System.out.println(resultSet1.getString("username"));
            //根據索引
            System.out.println(resultSet1.getString(3));
        }

        //3.用statement
        Statement statement = connection.createStatement();
        statement.execute("select id,username,password from user where id = 9");
        //獲取ResultSet物件
        ResultSet resultSet = statement.getResultSet();
        while (resultSet.next()){
            //根據索引
            System.out.println(resultSet.getInt(1));
            //根據欄位名
            System.out.println(resultSet.getString("username"));
            //根據索引
            System.out.println(resultSet.getString(3));
        }

事務處理

所謂事務,就是多條SQL語句組合而成的。這些SQL語句要麼都成功完成,要麼都失敗。也就是說即使有一個SQL語句執行出現錯誤,這個事務中的所有SQL都將失效
在Connection介面中提供了三個控制事務的方法
1.serAutoCommit(boolean autoCommit);設定是否自動提交事務。預設情況下為true。也就是說每條SQL語句執行成功後自動提交,失敗則自動回滾。
2.commit();提交事務
3.rollback():回滾事務
例子

 //1.載入並註冊驅動
        Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");
        //DriverManager.registerDriver((Driver) aClass.newInstance());
        //2.與資料庫建立連線
        String url = "jdbc:mysql://localhost:3306/db1";
        Connection connection = DriverManager.getConnection(url,"root","root");
        //禁止自動提交事務
        connection.setAutoCommit(false);
        Statement statement1 = connection.createStatement();
        try{
            statement1.executeUpdate("update user set password = 'heh213e1' where id = 2");
            statement1.executeUpdate("update user set password = heh213e1 where id = 2");
            connection.commit();
        }catch (SQLException e){
            //事務回滾
            connection.rollback();
        }

配置資料來源

context.xml

<?xml version="1.0" encode="UTF-8" ?>
<Context>
    <!--    T9.0 將resource複製到tomcat/config/context的Context中-->
    <Resource
            driverClassName="com.mysql.jdbc.Driver"
            url="jdbc:mysql://localhost:3306/db1"
            username="root"
            password="root"
            maxActive="50"
            maxIdle="20"
            name="ds"
            auth="Container"
            maxWait="10000"
            type="javax.sql.DataSource"/>
</Context>


web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">


  <resource-ref>
    <description>DB Connection</description>
    <res-ref-name>ds</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
  </resource-ref>

</web-app>



@WebServlet("/test3")
public class Test3 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Connection connection =null;
        try {
            InitialContext context = new InitialContext();
            DataSource ds = (DataSource) context.lookup("java:comp/env/ds");
            connection = ds.getConnection();
            Statement statement = connection.createStatement();
            statement.execute("select id,username.password from user ");
            ResultSet resultSet = statement.getResultSet();
            while(resultSet.next()){
                System.out.println(resultSet.getInt(1));
                System.out.println(resultSet.getString(2));
                System.out.println(resultSet.getString(3));
            }
        } catch (NamingException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

可滾動的結果級

//建立一個可以生成可以滾動的結果集的statemen
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);

在這裡插入圖片描述
在這裡插入圖片描述

相關文章