JDBC基础学习笔记

第一章:JDBC 概述

  第一节:JDBC 简介

    JDBC(Java Data Base Connectivity,java 数据库连接)是一种用于执行 SQL 语句的 JavaAPI,可以为多种关系 数据库提供统一访问,它由一组用 Java 语言编写的类和接口组成。JDBC 提供了一种基准,据此可以构建更高 级的工具和接口,使数据库开发人员能够编写数据库应用程序。

  第二节:JDBC 原理

    JDBC 原理:JDBC 是以前 SUN 公司定义的一套访问数据库的接口(没有具体实现),一套标准,具体的实现是由 各大数据库厂家去实现,每个数据库厂家都有自己的 JDBC 实现,也就是 JDBC 驱动实现类,Java 应用程序连接 指定数据库,需要使用厂家提供的 JDBC 驱动才能连接。(这里其实就是 java 多态的一种体现,一个接口可以有 很多具体的实现)

第二章:JDBC 连接数据库

  第一节:JDBC 连接数据库步骤

    第一步:加载驱动;

       第二步:连接数据库;

    第三步:使用语句操作数据库;

    第四步:关闭数据库连接,释放资源;

  第二节:在项目里配置数据库驱动

    右击项目 -> Build Path -> Configure Build Path -> Add Exteranl JARs..

  第三节:加载数据驱动

    Mysql 驱动名:com.mysql.jdbc.Driver

    加载方式: Class.forName(驱动名);即Class.forName("com.mysql.jdbc.Driver");

  第四节:连接及关闭数据库

    1,DriverManager 驱动管理类,主要负责获取一个数据库的连接;

static Connection getConnection(String url, String user, String password) 试图建立到给定数据库 URL 的连 接。

例如Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/db_book", "root", "123456");

     2,MySQL 数据库的连接地址格式

 jdbc:mysql://IP 地址:端口号/数据库名称
jdbc 协议:JDBC
URL 中的协议总是 jdbc ;
子协议:驱动程序名或数据库连接机制(这种机制可由一个或多个驱动程序支持)的名称,如 mysql; 子
名称:一种标识数据库的方法。必须遵循“//主机名端口/子协议”的标准 URL 命名约定,如 //localhost:3306/db_book

    3,Connection 接口 与特定数据库的连接(会话)。

 void close() 立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们被自动释放

第三章:使用 Statement 接口实现增,删,改操作

    作用:用于执行静态 SQL 语句并返回它所生成结果的对象。

    

利用Statement stmt=con.createStatement(); 获取Statement对象。
int executeUpdate(String sql) 执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或DELETE 语句,或 者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。
void close() 立即释放此 Statement 对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作。

    注:1.可以将Statemant与Connection的close写在一个方法中

      如:

public void close(Statement stmt,Connection con)throws Exception{
		if(stmt!=null){
			stmt.close();
			if(con!=null){
				con.close();
			}
		}
	}

      2.stmt.executeUpdate(sql);会返回一个int类型的result,可以用这个判断是否语句是否成功,成功的话会返回1。

第四章:使用 PreparedStatement 接口实现增,删,改操作

  PreparedStatement 是 Statement 的子接口,属于预处理操作,与直接使用 Statement 不同的是,PreparedStatement 在操作时,是先在数据表中准备好了一条 SQL 语句,但是此 SQL 语句的具体内容暂时不设置,而是之后再进 行设置。

(以后开发一般用 PreparedStatement,不用 Statement)

    写入数据时可以这么做

	private static int addBook(Book book)throws Exception{
		Connection con=dbUtil.getCon(); // 获取连接
		String sql="insert into t_book values(null,?,?,?,?)";
		PreparedStatement pstmt=con.prepareStatement(sql);
		pstmt.setString(1, book.getBookName());  // 给第一个坑设置值
		pstmt.setFloat(3, book.getPrice());  // 给第二个坑设置值
		pstmt.setString(2, book.getAuthor()); // 给第三个坑设置值
		pstmt.setInt(4, book.getBookTypeId());  // 给第四个坑设置值
		int result=pstmt.executeUpdate();
		dbUtil.close(pstmt, con);
		return result;
	}

    

 

第五章: ResultSet 结果集

    第一节:ResultSet 结果集的引入

      当我们查询数据库时,返回的是一个二维的结果集,我们这时候需要使用 ResultSet 来遍历结果集,获取每一行 的数据。

    第二节:使用 ResultSet 遍历查询结果

boolean next() 将光标从当前位置向前移一行。 String getString(int columnIndex) 以 Java 编程语言中 String 的形式获取此 ResultSet 对象的当前行中指定列 的值。 String getString(String columnLabel) 以 Java 编程语言中 String 的形式获取此 ResultSet 对象的当前行中指 定列的值。

    读取数据时可以分别以这三种形式:利用index,关键字,或者直接获取一个对象。

private static void listBook() throws Exception {
        Connection con = dbUtil.getCon(); // 获取连接
        String sql = "select * from t_book";
        PreparedStatement pstmt = con.prepareStatement(sql);
        ResultSet rs = pstmt.executeQuery(); // 返回结果集ResultSet//默认在第0行
        while (rs.next()) {
            int id = rs.getInt(1); // 获取第一个列的值 编号id
            String bookName = rs.getString(2); // 获取第二个列的值 图书名称 bookName
            float price = rs.getFloat(4); // 获取第三列的值 图书价格 price
            String author = rs.getString(3); // 获取第四列的值 图书作者 author
            int bookTypeId = rs.getInt(5); // 获取第五列的值 图书类别id
            System.out.println("图书编号:" + id + " 图书名称:" + bookName + " 图书价格:"
                    + price + " 图书作者:" + author + " 图书类别id:" + bookTypeId);
            System.out
                    .println("=======================================================================");

        }
    }
private static void listBook2() throws Exception {
        Connection con = dbUtil.getCon(); // 获取连接
        String sql = "select * from t_book";
        PreparedStatement pstmt = con.prepareStatement(sql);
        ResultSet rs = pstmt.executeQuery(); // 返回结果集ResultSet
        while (rs.next()) {
            int id = rs.getInt("id"); // 获取第一个列的值 编号id
            String bookName = rs.getString("bookName"); // 获取第二个列的值 图书名称 bookName
            float price = rs.getFloat("price"); // 获取第三列的值 图书价格 price
            String author = rs.getString("author"); // 获取第四列的值 图书作者 author
            int bookTypeId = rs.getInt("bookTypeId"); // 获取第五列的值 图书类别id
            System.out.println("图书编号:" + id + " 图书名称:" + bookName + " 图书价格:"
                    + price + " 图书作者:" + author + " 图书类别id:" + bookTypeId);
            System.out
                    .println("=======================================================================");

        }
    }
private static List<Book> listBook3()throws Exception{
        List<Book> bookList=new ArrayList<Book>(); 
        Connection con = dbUtil.getCon(); // 获取连接
        String sql = "select * from t_book";
        PreparedStatement pstmt = con.prepareStatement(sql);
        ResultSet rs = pstmt.executeQuery(); // 返回结果集ResultSet
        while (rs.next()) {
            int id = rs.getInt("id"); // 获取第一个列的值 编号id
            String bookName = rs.getString("bookName"); // 获取第二个列的值 图书名称 bookName
            float price = rs.getFloat("price"); // 获取第三列的值 图书价格 price
            String author = rs.getString("author"); // 获取第四列的值 图书作者 author
            int bookTypeId = rs.getInt("bookTypeId"); // 获取第五列的值 图书类别id
            Book book=new Book(id, bookName, price, author, bookTypeId);
            bookList.add(book);
        }
        return bookList;
    }

第六章: 处理大数据对象

大数据对象处理主要有 CLOB(character large object)和 BLOB(binary large object)两种类型的字段;在 CLOB 中可以存储大字符数据对象,比如长篇小说;在 BLOB 中可以存放二进制大数据对象,比如图片,电影,音乐;

    第一节:处理 CLOB 数据

    

package com.java1234.jdbc.chap06.sec01;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import com.java1234.jdbc.model.Book;
import com.java1234.jdbc.util.DbUtil;

public class Demo1 {

private static DbUtil dbUtil=new DbUtil();
    
    /**
     * 添加图书
     * @param book
     * @return
     * @throws Exception
     */
    private static int addBook(Book book)throws Exception{
        Connection con=dbUtil.getCon(); // 获取连接
        String sql="insert into t_book values(null,?,?,?,?,?)";
        PreparedStatement pstmt=con.prepareStatement(sql);
        pstmt.setString(1, book.getBookName());  // 给第一个坑设置值
        pstmt.setFloat(3, book.getPrice());  // 给第二个坑设置值
        pstmt.setString(2, book.getAuthor()); // 给第三个坑设置值
        pstmt.setInt(4, book.getBookTypeId());  // 给第四个坑设置值
        File context=book.getContext(); // 获取文件
        InputStream inputStream=new FileInputStream(context);

        pstmt.setAsciiStream(5, inputStream,(int)context.length());  // 给第五个坑设置值
        int result=pstmt.executeUpdate();
        dbUtil.close(pstmt, con);
        return result;
    }
    
    public static void getBook(int id)throws Exception{
        Connection con=dbUtil.getCon();
        String sql="select * from t_book where id=?";
        PreparedStatement pstmt=con.prepareStatement(sql);
        pstmt.setInt(1, id);
        ResultSet rs=pstmt.executeQuery();
        if(rs.next()){
            String bookName=rs.getString("bookName");
            float price=rs.getFloat("price");
            String author=rs.getString("author");
            int bookTypeId=rs.getInt("bookTypeId");
            Clob c=rs.getClob("context");
            String context=c.getSubString(1, (int) c.length());
            System.out.println("图书名称:"+bookName);
            System.out.println("图书价格:"+price);
            System.out.println("图书作者:"+author);
            System.out.println("图书类型ID:"+bookTypeId);
            System.out.println("图书内容:"+context);
        }
        
        dbUtil.close(pstmt, con);
    }
    
    public static void main(String[] args)throws Exception {
//        String str="C:\152.txt";  
//        String location=str.replace("\\", "/");  
//        File context=new File(location);
//        System.out.println(location);
//        Book book=new Book("helloWorld", 100, "小锋", 1,context);
//        int result=addBook(book);
//        if(result==1){
//            System.out.println("添加成功!");
//        }else{
//            System.out.println("添加失败!");
//        }
        getBook(6);
    }
}

       第二节:处理 BLOG 数据

    

package com.java1234.jdbc.chap06.sec02;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import com.java1234.jdbc.model.Book;
import com.java1234.jdbc.util.DbUtil;

public class Demo1 {

private static DbUtil dbUtil=new DbUtil();
    
    /**
     * 添加图书
     * @param book
     * @return
     * @throws Exception
     */
    private static int addBook(Book book)throws Exception{
        Connection con=dbUtil.getCon(); // 获取连接
        String sql="insert into t_book values(null,?,?,?,?,?,?)";
        PreparedStatement pstmt=con.prepareStatement(sql);
        pstmt.setString(1, book.getBookName());  // 给第一个坑设置值
        pstmt.setFloat(3, book.getPrice());  // 给第二个坑设置值
        pstmt.setString(2, book.getAuthor()); // 给第三个坑设置值
        pstmt.setInt(4, book.getBookTypeId());  // 给第四个坑设置值
        File context=book.getContext(); // 获取文件
        InputStream inputStream=new FileInputStream(context);
        pstmt.setAsciiStream(5, inputStream,(int)context.length());  // 给第五个坑设置值
        
        File pic=book.getPic(); // 获取图片文件
        InputStream inputStream2=new FileInputStream(pic);
        pstmt.setBinaryStream(6, inputStream2, (int)pic.length()); // 给第六个坑设置值
        int result=pstmt.executeUpdate();
        dbUtil.close(pstmt, con);
        return result;
    }
    
    public static void getBook(int id)throws Exception{
        Connection con=dbUtil.getCon();
        String sql="select * from t_book where id=?";
        PreparedStatement pstmt=con.prepareStatement(sql);
        pstmt.setInt(1, id);
        ResultSet rs=pstmt.executeQuery();
        if(rs.next()){
            String bookName=rs.getString("bookName");
            float price=rs.getFloat("price");
            String author=rs.getString("author");
            int bookTypeId=rs.getInt("bookTypeId");
            Clob c=rs.getClob("context");
            String context=c.getSubString(1, (int)c.length());
            Blob b=rs.getBlob("pic");
            FileOutputStream out=new FileOutputStream(new File("d:/pic2.jpg"));
            out.write(b.getBytes(1, (int)b.length()));
            out.close();
            System.out.println("图书名称:"+bookName);
            System.out.println("图书价格:"+price);
            System.out.println("图书作者:"+author);
            System.out.println("图书类型ID:"+bookTypeId);
            System.out.println("图书内容:"+context);
        }
        dbUtil.close(pstmt, con);
    }
    
    public static void main(String[] args)throws Exception {
//        String str="C:\152.txt";  
//        String location=str.replace("\\", "/");  
//        File context=new File(location);
//        String str1="C:\123.jpg";
//        String str2=str1.replace("\\", "/");  
//        File pic=new File(str2);
//        Book book=new Book("helloWorld", 100, "小锋", 1,context,pic);
//        int result=addBook(book);
//        if(result==1){
//            System.out.println("添加成功!");
//        }else{
//            System.out.println("添加失败!");
//        }
        getBook(11);
    }
}

    注意:1.利用下面这种方式对文件进行读取,防止目录出现问题,一般出现问题,除了是文件名错误外,还有就是复制会带来额外的东西,我们需要手打。

String str="C:\152.txt";  
String location=str.replace("\\", "/");  
File context=new File(location);

       2.写入数据时,注意第三行的第三个值要强转成int类型,而且对于CLOG数据,使用setAsciiStream,对于BLOG 数据,要使用setBinaryStream进行写入

File context=book.getContext(); // 获取文件
InputStream inputStream=new FileInputStream(context);
pstmt.setAsciiStream(5, inputStream,(int)context.length()); 

      

File context=book.getContext(); // 获取文件
InputStream inputStream=new FileInputStream(context);
pstmt.setAsciiStream(5, inputStream,(int)context.length());  // 给第五个坑设置值
		
File pic=book.getPic(); // 获取图片文件
InputStream inputStream2=new FileInputStream(pic);
pstmt.setBinaryStream(6, inputStream2, (int)pic.length()); // 给第六个坑设置值

      3.读取数据时,对于CLOG数据,用下面这种方法。

Clob c=rs.getClob("context");
String context=c.getSubString(1, (int) c.length());

            对于BLOG 数据,用接下来这种方法,也就是直接写成多媒体格式。    

Blob b=rs.getBlob("pic");
FileOutputStream out=new FileOutputStream(new File("d:/pic2.jpg"));
out.write(b.getBytes(1, (int)b.length()));
out.close();

  

第七章: 使用 CallableStatement 接口调用存储过程

    CallableStatement 主要是调用数据库中的存储过程,CallableStatement 也是 PreparedStatement 接口的子接口。在使用 CallableStatement 时可以接收存储过程的返回值

    void registerOutParameter(int parameterIndex, int sqlType) 按顺序位置 parameterIndex 将 OUT 参数注册为 JDBC 类型 sqlType。

    

private static String getBookNameById(int id)throws Exception{
		Connection con=dbUtil.getCon();  // 获取数据库连接
		String sql="{CALL pro_getBookNameById1(?,?)}";
		CallableStatement cstmt=con.prepareCall(sql);
		cstmt.setInt(1, id); // 设置第一个参数
		cstmt.registerOutParameter(2, Types.VARCHAR);  // 设置返回类型
		cstmt.execute();
		String bookName=cstmt.getString(1);  // 获取返回值//这里不仅可以利用index,利用关键字也可以。
		dbUtil.close(cstmt, con);
		return bookName;
	}
	

  注意:sql语句外的大括号。

第八章: 使用元数据分析数据库

    第一节:使用 DatabaseMetaData 获取数据库基本信息

      DatabaseMetaData 可以得到数据库的一些基本信息,包括数据库的名称、版本,以及得到表的信息。

      String getDatabaseProductName() 获取此数据库产品的名称。 int getDriverMajorVersion() 获取此 JDBC 驱动程序的主版本号。

      int getDriverMinorVersion() 获取此 JDBC 驱动程序的次版本号。

public static void main(String[] args)throws Exception {
		DbUtil dbUtil=new DbUtil();
		Connection con=dbUtil.getCon();
		DatabaseMetaData dmd=con.getMetaData(); // 获取元数据
		System.out.println("数据库名称:"+dmd.getDatabaseProductName());
		System.out.println("数据库版本:"+dmd.getDriverMajorVersion()+"."+dmd.getDriverMinorVersion());
		
	}

  

    第二节:使用 ResultSetMetaData 获取 ResultSet

      ResultSetMetaData 可获取关于 ResultSet 对象中列的基本信息;

      int getColumnCount() 返回此 ResultSet 对象中的列数。

      String getColumnName(int column) 获取指定列的名称。

      int getColumnTypeName(int column) 获取指定列的 SQL 类型名称。

	public static void main(String[] args) throws Exception{
		DbUtil dbUtil=new DbUtil();
		Connection con=dbUtil.getCon();
		String sql="select * from t_book";
		PreparedStatement pstmt=con.prepareStatement(sql);
		ResultSetMetaData rsmd=pstmt.getMetaData();
		int num=rsmd.getColumnCount(); // 获取元数据列的总数
		for(int i=1;i<=num;i++){
			System.out.println(rsmd.getColumnName(i)+","+rsmd.getColumnTypeName(i));
		}
	}

  

第九章: JDBC 事务处理

    第一节:事务的概念

      事务处理在数据库开发中有着非常重要的作用,所谓事务就是所有的操作要么一起成功,要么一起失败,事务 本身具有原子性(Atomicity)、一致性(Consistency)、隔离性或独立性(Isolation)、持久性(Durability)4 个特 性,这 4 个特性也被称为 ACID 特征。

原子性:原子性是事务最小的单元,是不可再分隔的单元,相当于一个个小的数据库操作,这些操作必须同时 成功,如果一个失败了,则一切的操作将全部失败。

一致性:指的是在数据库操作的前后是完全一致的,保证数据的有效性,如果事务正常操作则系统会维持有效 性,如果事务出现了错误,则回到最原始状态,也要维持其有效性,这样保证事务开始时和结束时系统处于一 致状态。

隔离性:多个事务可以同时进行且彼此之间无法访问,只有当事务完成最终操作时,才可以看到结果;

持久性:事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。

package com.java1234.jdbc.chap09.sec04;

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

import com.java1234.jdbc.util.DbUtil;

public class Demo1 {
    
    private static DbUtil dbUtil=new DbUtil();

    /**
     * 转出
     * @param con
     * @param accountName
     * @param account
     * @throws Exception
     */
    private static void outCount(Connection con,String accountName,int account)throws Exception{
        String sql="update t_account set accountBalance=accountBalance-? where accountName=?";
        PreparedStatement pstmt=con.prepareStatement(sql);
        pstmt.setInt(1, account);
        pstmt.setString(2, accountName);
        pstmt.executeUpdate();
    }
    
    /**
     * 转入
     * @param con
     * @param accountName
     * @param account
     * @throws Exception
     */
    private static void inCount(Connection con,String accountName,int account)throws Exception{
        String sql="update t_account set account=accountBalance+? where accountName=?";
        PreparedStatement pstmt=con.prepareStatement(sql);
        pstmt.setInt(1, account);
        pstmt.setString(2, accountName);
        pstmt.executeUpdate();
    }
    
    
    public static void main(String[] args) {
        Connection con=null;
        Savepoint sp=null;
        try {
            con=dbUtil.getCon(); 
            con.setAutoCommit(false); // 取消自动提交
            System.out.println("张三开始向李四转账!");
            int account=500;
            outCount(con, "张三", account);
            //sp=con.setSavepoint(); // 设置一个保存点
            inCount(con, "李四", account);
            System.out.println("转账成功!");
        } catch (Exception e) {
            try {
                con.rollback(); // 回滚到sp保存点
            } catch (SQLException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            try {
                con.commit();  // 提交事务
                con.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

    第二节:MySQL 对事务的支持

      

只待江流汲海,万木朝东
原文地址:https://www.cnblogs.com/wanmudong/p/8127890.html