Java数据库编程(JDBC)-入门笔记

数据库(DB)

简介:

• DB: Database = Data + Base
• 数据库:数据+库,存放数据的库(场所)
• 数据:规范、半规范、不规范数据
• 库
– 一个空间,一个场所
– 停车场、钱包、教室
– 文件

• DB:保存数据的地方
– 数据安全、安全、安全
– 存取效率
– 性价比高

DB分类

• DB(文件集合,类似.doc,.docx文件)
• DBMS: Database Management System(类似Office/WPS)
– 操纵和管理数据库的软件,可建立、使用和维护数据库

DB种类

– 文本文件/二进制文件
– Xls文件
– Access(包含在office里面,收费,只能运行在Windows上。32和64位,office 95/97/2000/2003/2007/2010/…)

DBMS种类

– Mysql /Postgresql/Berkely DB (免费, 但也有收费版。多平台, 32和64位区分。)
– SQL Server(收费,只能运行Windows,32位和64位,中文文档。SQL Server 2000/2005/2008/2012/…,也有免费版,但有CPU和内存限制)
– Oracle/DB2(收费,全平台,32和64位,英文文档,也有免费版,但有CPU和内存限制)
– SQLite (免费,手机上使用)

• 表:table, 实体
– 列:列、属性、字段
– 行:记录、元组tuple,数据
• 数据值域:数据的取值范围
• 字段类型
– int :整数 -2147483648~2147483647,4个字节
– double:小数,8个字节
– datetime :时间,7个字节
– varchar:字符串,可变字节
Oracle不建议使用 varchar,而是推荐 varchar2来存储可变字符串

SQL

• 结构化查询语言(Structured Query Language),简称SQL
– 是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。
• SQL标准
– SQL-86/SQL-89/SQL-92
– SQL:1999/ SQL:2003/ SQL:2008/ SQL:2011/ SQL:2016
– 基础的部分,所有标准都一样
– 标准仅仅是标准,每个厂商的数据库实现可能有一些不一致

SQL语句示例:

 create table t1(a int, b varchar(20));
 insert into t1(a,b) values(1,’abc’);
 select a from t1;
 select a,b from t1 where a > 1;
 delete from t1 where a = 10 and b=‘ab’;
 update t1 set a=2, b = ‘cd’ where a=1 and b=‘ab’;
 drop table t1;

第二节 JDBC基本操作

JDBC

目前常用的数据库连接技术有 ODBC(Open Database Connectivity,开发式数据库连接)和 JDBC 两种 API(Application Program Interface,应用程序接口)
ODBC 技术是由微软提供的访问数据库技术,可以使用 SQL(Structured Query Language,结构化查询语言)语句访问各种数据库。JDBC 技术是 Sun 公司推出的一种专门访问数据库的 API。
它是由一组用 Java 编程语言编写的类和接口组成,支持基本 SQL 语句,提供多样化的数据库连接方式,可连接不同的数据库。 由于 ODBC 是用 C 语言编写的接口,而 Java 对本地 C 语言代码的调用在安全性、实现性、健壮性以及可移植性方面存在很多的缺陷。加上 C 语言中含有复杂的数据类型(如,指针),从而束缚了 ODBC 技术在 Java 访问数据库中的应用JDBC 技术是一个用 Java 语言编写的用于访问数据库的标准接口。使用这样的 API编写的应用程序无论从安全性、健壮性、可移植性都是具有优势的。。遗憾的是Java8不再支持ODBC

ODBC, Open Database Connectivity开放数据库连接,是 Windows平台上为了解决异构数据库间的数据共享而产生的。

• Java和数据库是平行的两套系统
• Java和数据库的连接方法
– Native API (不能跨平台)
– ODBC/JDBC-ODBC (效率很差,也无法跨平台)
– JDBC (主流): Java Database Connectivity
• JDBC 1, JDK 1.1
• JDBC 2 JDK 1.3~JDK1.4
• JDBC 3 JDK 5
• JDBC 4 JDK 6, (JDK 7, JDBC4.1; JDK8, JDBC4.2)
Java数据库编程(JDBC)-入门笔记_第1张图片

Java SQL 操作类库

• java.sql., javax.sql.; 这2个包只是接口类
• 根据数据库版本和JDBC版本合理选择
• 一般数据库发行包都会提供jar包,同时也要注意区分32位和64位(数据库分32/64位, JDK也分32/64位)。
① Server2008 数据库驱动程序 sqljdbc4.jar(可以从微软官方网站上免费下载)。使用时,在当前工程文件夹里新建一个名为 lib 文件夹,然后 sqljdbc4.jar 文件拷贝到 lib 文件夹里。
在 NetBeans 界面里,在左边项目导航窗口的工程文件名上鼠标右键打开工程属性对话框单击左边导航菜单“库”,在右边选择“编译”选项卡,单击“添加 JAR/文件夹”按钮,
打开“添加 JAR/文件夹”对话框,浏览并选择 sqljdbc4.jar 文件,就将该数据库驱动程序成功添加到该工程里了。
② mysql的同理
• 连接字符串(样例)
– jdbc:oracle :thin:@127.0.0.1:1521:dbname
– jdbc:mysql://localhost:3306/mydb
– jdbcsqlserver://localhost:1433; DatabaseName=dbname

Java连接数据库操作步骤

连接思想1
• 构建连接(搭桥)
– 注册驱动,寻找材质, class.forName(“…”);
– 确定对岸目标(url,用户,密码), 建桥Connection
• 执行操作(派个人过桥, 提着篮子,去拿数据)
– Statement (执行者)
– ResultSet(结果集)
• 释放连接(拆桥) connection.close();
Java数据库编程(JDBC)-入门笔记_第2张图片
抽象化:
java
2:connection 桥 连接数据库并担任传送数据的任务
3:statement 人 执行sql语句
4:resultset 东西物品结果 保存statement执行后的结果
数据库

连接思想2
建议链接的五大步骤:
1加载(注册)数据库
2 建立链接
3 执行SQL语句(获取statement对象)
4 处理结果集
5 关闭数据库

DriverManager :此类用于加载和卸载各种驱动程序并建立与数据库的连接

简单:

import java.sql.*;
class AccessDatabase{
public static void main(String [] args) {
   try {
        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//加载驱动
        String url = "jdbc:odbc:test";
        Connection con = DriverManager.getConnection(url);//建立链接
        Statement s = con.createStatement();
        ResultSet rs = s.executeQuery("select * from friends");
        while (rs.next()) {
            System.out.print(rs.getString(1) + "\t");
            。。。
         }
        rs.close();
        s.close();
        con.close();
    } catch (Exception ex) {
        System.out.println(ex.getMessage());
    }
 }
}

复杂:

import java.sql.*;

public class SelectTest {
    public static void main(String[] args){
    	
    	//构建Java和数据库之间的桥梁介质
        try{            
            Class.forName("com.mysql.jdbc.Driver");
            System.out.println("注册驱动成功!");
        }catch(ClassNotFoundException e1){
            System.out.println("注册驱动失败!");
            e1.printStackTrace();
            return;
        }
        
        String url="jdbc:mysql://localhost:3306/test";        
        Connection conn = null;
        try {
        	//构建Java和数据库之间的桥梁:URL,用户名,密码
            conn = DriverManager.getConnection(url, "root", "123456");
            
            //构建数据库执行者
            Statement stmt = conn.createStatement(); 
            System.out.println("创建Statement成功!");      
            
            //执行SQL语句并返回结果到ResultSet
            ResultSet rs = stmt.executeQuery("select bookid, bookname, price from t_book order by bookid");
                        
            //开始遍历ResultSet数据
            while(rs.next())
            {
            	System.out.println(rs.getInt(1) + "," + rs.getString(2) + "," + rs.getInt("price"));
            }
            
            rs.close();
            stmt.close();
            
        } catch (SQLException e){
            e.printStackTrace();
        }
        finally
        {
        	try
        	{
        		if(null != conn)
        		{
            		conn.close();
            	}
        	}
        	catch (SQLException e){
                e.printStackTrace();
        	}        	
        }
    }
}

Statement

• Statement 执行者类
① – 使用executeQuery()执行select语句,返回结果放在ResultSet
② – 使用executeUpdate()执行insert/update/delete,返回修改的行数
– 一个Statement对象一次只能执行一个命令
• ResultSet 结果对象
– next() 判断是否还有下一条记录
— getInt/getString/getDouble/……
可以按索引位置,可以按照列名
Statement此接口用于执行 SQL 语句,若是查询的 SQL 语句则将数据检索ResultSet 中,若是更新的 SQL 语句则将处理之后所影响的表中的行数返回给客户端 。

Statement 对象用于把 SQL 语句发送到 DBMS。你只须简单地创建一个 Statement 对象并且然后执行它,使用适当的方法执行你发送的 SQL 语句。对 SELECT 语句来说,可以使用 executeQuery。要创建或修改表的语句,使用的方法是 executeUpdate。

需要一个活跃的连接的来创建 Statement 对象的实例。在下面的例子中,我们使用我们的 Connection 对象 con 创建 Statement 对象 stmt:

Statement stmt = con.createStatement();

到此 stmt 已经存在了,但它还没有把 SQL 语句传递到 DBMS。我们需要提供 SQL 语句作为参数提供给我们使用的 Statement 的方法。例如,在下面的代码段里,我们使用上面例子中的 SQL 语句作为 executeUpdate 的参数:

stmt.executeUpdate("CREATE TABLE COFFEES " +
"(COF_NAME VARCHAR(32),SUP_ID INTEGER,PRICE FLOAT," +
"SALES INTEGER,TOTAL INTEGER)");

假如我们已经把 SQL 语句赋给了 createTableCoffees 变量,我们可以如下方式书写代码:

createTableCoffees="CREATE TABLE COFFEES " +
"(COF_NAME VARCHAR(32),SUP_ID INTEGER,PRICE FLOAT," +
"SALES INTEGER,TOTAL INTEGER)"
stmt.executeUpdate(createTableCoffees);

JDBC增删改

executeUpdate():返回的是受影响的行数(即更新的行数)(一般成功执行,结果大于0)
增:

import java.sql.*;
public static void main(String [] args) {
    try {
        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        String url = "jdbc:odbc:test";
        Connection con = DriverManager.getConnection(url);
        String sql = "INSERT INTO Student (id,name,address)+VALUES(001,‘朱八‘,’深圳 ‘)";
        Statement stmt = con.createStatement();
        int rowcount = stmt.executeUpdate(sql);
        stmt.close();
        con.close();
 } catch (SQLException ex) {
        System.out.println(ex.getMessage());
}
}

删改:

public static void main(String [ ] args) {
    try {
         Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
         url = "jdbc:odbc:test";
         Connection con = DriverManager.getConnection(url);
         String sql = "Delete from Student where name like ‘%张三%‘ ";
         Statement stmt = con.createStatement();
         stmt = con.createStatement();
         stmt.executeUpdate(sql);
         System.out.println("张三 的记录已删除“);
         stmt.close();
         con.close();
    } catch (SQLException ex) {
         System.out.println(ex.getMessage());
    }
}

JDBC查询数据实现

一:返回结果集

String sql = "SELECT id, name,address FROM Student";
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(sql);

ResultSet 对象完全依赖于 Statement 对象和 Connection 对象
每次执行 SQL 语句时,都会用新的结果重写结果集
当相关的 Statement 关闭时,ResultSet 对象会自动关闭
Next( ) 此方法将光标从当前位置下移一行
get( ) 从 ResultSet
对象返回数据
二:
它演示对当前行的处理
使用 next() 方法时,记录是按顺序处理的
必须按照数据返回的顺序处理每行中的数据
rset.getString(1):得到第一列的数据

…
ResultSet rset = stmt.getResultSet();
	
while(rset.next( ) ) {
    String dept_name = rset.getString(1);
}

演示对当前列的处理
使用 get()方法可以直接访问列

…
Statement stmt = con.createStatement();
Stmt.executeQuery("Select id, name  from Student") ;
ResultSet rs = stmt.getResultSet();
while(rs.next()) 
{
   String name = rset.getString ("name");
   System.out.println ( name) ;
}


以下代码显示值 1 被作为参数传递给 getString() 方法,这实际上指列 id 的索引
(可以当返回的是int型getint(2),当返回的是data型可以用getDate(3))

…
Statement stmt = con.createStatement();
stmt.executeQuery("Select id, name  from Student");
ResultSet rs = stmt.getResultSet();
while(rs.next()) {
    String employeeid = rs.getString (1);
}

注意事项

• ResultSet不能多个做笛卡尔积连接
• ResultSet最好不要超过百条,否则极其影响性能
• ResultSet也不是一口气加载所有的select结果数据
• Connection 很昂贵,需要及时close
• Connection所用的jar包和数据库要匹配
记得抛异常:
try
{
if(null != conn)
{
conn.close();
}
}
catch (SQLException e){
e.printStackTrace();
}

conn 为 null 的时候,conn.close() 会报空指针异常

查询的时候表和关键字一样可用`符号
String sql1 = "select order_id orderId,order_name orderName fromorder";

原理

为什么需要加载驱动Class.forName("sun.jdbc.odbc.JdbcOdbcDriver")
DriverManager由管理Driver
执行语句的时候生成Driver对象,注册到DriverManager同一管理

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
        	//1. 新建一个mysql的driver对象
        	//2. 将这个对象注册到DriverManager中
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

第三节 JDBC高级操作

事务

• 数据库事务,Database Transaction。
• 作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
• 事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。
• 事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。

关闭自动提交,实现多语句同一事务connection.setAutoCommit(false);
• connection.commit(); 提交事务 commit,就是以上的所有的语句,请帮我执行
• connection.rollback(); 回滚事务 rollback,就是以上的语句,全部不帮忙执行
• 保存点机制
– connection.setSavepoint()
– connection.rollback(Savepoint) 回滚到Savepoint时候的保存点
– connection.rollback();//回滚到异常之前

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;

public class TransactionTest {

	public static void main(String[] args) throws Exception {
		// 构建Java和数据库之间的桥梁介质
		try {
			Class.forName("com.mysql.jdbc.Driver");
			System.out.println("注册驱动成功!");
		} catch (ClassNotFoundException e1) {
			System.out.println("注册驱动失败!");
			e1.printStackTrace();
		}

		String url = "jdbc:mysql://localhost:3306/test";
		Connection conn = null;
		try {
			// 构建Java和数据库之间的桥梁:URL,用户名,密码
			conn = DriverManager.getConnection(url, "root", "123456");
			conn.setAutoCommit(false);/1.设置为不自动提交数据

			insertBook(conn, "insert into t_book values(101, 'aaaa', 10)");
			insertBook(conn, "insert into t_book values(102, 'bbbb', 10)");
			insertBook(conn, "insert into t_book values(103, 'cccc', 10)");
			Savepoint phase1 = conn.setSavepoint(); //设置一个保存点
			insertBook(conn, "insert into t_book values(104, 'cccc', 10)");
			insertBook(conn, "insert into t_book values(105, 'cccc', 10)");
			conn.rollback(phase1);  //回滚到phase1保存点,即上面2行无效
			conn.commit();//2.提交数据

			System.out.println("操作成功");

		} catch (SQLException e) {
			e.printStackTrace();
			conn.rollback();//回滚到异常之前
		} finally {
			if (null != conn) {
				conn.close();
			}
		}
	}

	public static void insertBook(Connection conn, String sql) {
		try {
			// 构建数据库执行者
			Statement stmt = conn.createStatement();
			//System.out.print("创建Statement成功!");

			// 执行SQL语句
			int result = stmt.executeUpdate(sql);

			stmt.close();

		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

隔离级别一共四级,自己百度

//获取当前连接的隔离级别
System.out.println(conn.getTransactionIsolation());
//设置数据库的隔离级别:
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

预编译(PreparedStatement)

PreparedStatement接口 预编译:
PreparedStatement此接口用于执行预编译的 SQL 语句
DriverManager此类用于加载和卸载各种驱动程序并建立与数据库的连接
PreparedStatement用于提高运行时效率
执行 PreparedStatement对象比执行 Statement 对象快

PreparedStatement接口
基于条件的 SQL 查询中使用 PreparedStatement,其中条件在参数中给出

拼接SQL字符串很危险

• Java提供PreparedStatement,更为安全执行SQL
• 和Statement区别是使用“?” 代替字符串拼接
• 使用setXXX(int,Object)的函数来实现对于?的替换
可以是setString,setint,setobject
– 注:不需要考虑字符串的两侧单引号
– 参数赋值,清晰明了,拒绝拼接错误
• Select语句一样用ResultSet接收结果**

• 使用PreparedStatement的好处:
– 防止注入攻击
– 防止繁琐的字符串拼接和错误
– 直接设置对象而不需要转换为字符串
– PreparedStatement使用预编译速度相对Statement快很多

避免sql注入攻击:
• Select count(*) from User
where name=‘aaa’ and pwd=‘bbb’
 如果有人将口令输入 ‘ or 1=1; delete from table ccc; –
 则上面的语句变为:
 where name=‘aaa’ and pwd=‘’ or 1=1; delete from table ccc; --’

PreparedStatement vs Statement

  1. 代码的可读性和可维护性。
2.PreparedStatement 能最大可能提高性能:
  • DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。
  • 在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。
  • (语法检查,语义检查,翻译成二进制命令,缓存)
  1. PreparedStatement 可以防止 SQL 注入

(通俗易懂:PreparedStatement一条语句,对参数赋值就可以,Statement要创建很多sql语句)

PreparedStatement 的 execute方法和executeUpdate方法区别

方法executeUpdate

用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整数(int),指示受影响的行数(即更新计数)。 对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。

方法execute
可用于执行任何SQL语句, 返回一个boolean值, 表明执行该SQL语句是否返回了ResultSet。如果执行后第一个结果是ResultSet,则返回true,否则返回false。但它执行SQL语句时比较麻烦 ,==通常我们没有必要使用execute方法来执行SQL语句,而是使用executeQuery或executeUpdate更适合,但如果在不清楚SQL语句的类型时则只能使用execute方法来执行该SQL语句了 ==
显然方法execute多了判断是否有结果集返回

预编译增删改

PreparedStatement pstmt = conn.prepareStatement(
          "insert into Student values(?,?,?,?)");
      //对?参数进行赋值(填充占位符)
      pstmt.setString(1, stu.stuID);
      pstmt.setString(2, stu.stuName);
      pstmt.setString(3, stu.sex);
      pstmt.setString(4, stu.birth);
      //执行插入,返回受影响的行数
      int r = pstmt.executeUpdate();

预编译查询

@Test
public void test_queryNameById() throws Exception {

    // 1. 获取数据库连接, 自动提交事务
    Connection connection = DbConnUtil.getConnection();

    String sql = "select id, name, password pwd from t_user where id = ?";

    // 2. 获取PreparedStatement
    PreparedStatement preparedStatement = connection.prepareStatement(sql);

    // 3. 设置查询参数
    preparedStatement.setInt(1, 1005);

    // 4. 执行查询sql
    ResultSet resultSet = preparedStatement.executeQuery();

    // 5.结果集解析
    if (resultSet.next()) {
        String name = resultSet.getString("name");
        System.out.println(name);
    }

    // 6.释放资源
    DbConnUtil.release(resultSet, preparedStatement, connection);
}

批量操作

当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率

JDBC的批量处理语句包括下面三个方法:
  • addBatch(String):添加需要批量处理的SQL语句或是参数;
  • executeBatch():执行批量处理语句;
  • clearBatch():清空缓存的数据

如果有大量的sq语句,它们结构相同,仅仅差别在具体数值上那么可以通过 addBatch方法进行批量操作。这样会提高性能,减少数据库负担。
• 提供addBatch批量更新功能 然后再加上execteBatch();

//1.“攒”sql
pstmt.addBatch()
//2.执行
pstmt.executeBatch();
//3.清空
pstmt.clearBatch();
Java数据库编程(JDBC)-入门笔记_第3张图片

ResultSetMetaData

获取结果集的元数据

• ResultSet可以用来承载所有的select语句返回的结果集
ResultSetMetaData来获取ResultSet返回的属性(如,每一行的名字类型等)
– getColumnCount(),返回结果的列数 (1开始的)
– getColumnClassName(i),返回第i列的数据的Java类名
– getColumnTypeName(i),返回第i列的数据库类型名称
– getColumnType(i),返回第i列的SQL类型

• 使用ResultSetMetaData解析ResultSet

  1. 如何获取 ResultSetMetaData: 调用 ResultSet 的 getMetaData() 方法即可

  2. 获取 ResultSet 中有多少列:调用 ResultSetMetaData 的 getColumnCount() 方法

  3. 获取 ResultSet 每一列的列的别名是什么:调用 ResultSetMetaData 的getColumnLabel() 方法

 try {
        	//构建Java和数据库之间的桥梁:URL,用户名,密码
            conn = DriverManager.getConnection(url, "root", "123456");
            
            //构建数据库执行者
            Statement stmt = conn.createStatement(); 
            System.out.println("创建Statement成功!");      
            
            //执行SQL语句并返回结果到ResultSet
            ResultSet rs = stmt.executeQuery("select bookid, bookname, price from t_book order by bookid");
                        
            //获取结果集的元数据
            ResultSetMetaData meta = rs.getMetaData(); 
            int cols = meta.getColumnCount(); //得到返回结果的列数 (1开始的)
            for(int i=1;i<=cols;i++)
            {
            	System.out.println(meta.getColumnName(i) + "," + meta.getColumnTypeName(i));
            }
            
            rs.close();
            stmt.close();
            
        } catch (SQLException e){
            e.printStackTrace();
 Statement stmt = con.createStatement();
stmt.executeQuery("Select id, name  from Student");
ResultSet rs = stmt.getResultSet();//得到返回结果集
ResultsetMetaData meta =rs.getMetaData()//得到返回结果集的属性

ORM思想(流程)

两种思想

  1. 面向接口编程的思想

  2. ORM思想(object relational mapping)

  • 一个数据表对应一个java类
  • 表中的一条记录对应java类的一个对象
  • 表中的一个字段对应java类的一个属性

sql是需要结合列名和表的属性名来写。注意起别名。

两种技术

  1. JDBC结果集的元数据:ResultSetMetaData
  • 获取列数:getColumnCount()
  • 获取列的别名:getColumnLabel()
  1. 通过反射,创建指定类的对象,获取指定的属性并赋值

Java数据库编程(JDBC)-入门笔记_第4张图片

操作BLOB类型字段

MySQL BLOB类型

  • MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
  • 插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。
  • MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)
    Java数据库编程(JDBC)-入门笔记_第5张图片
  • 实际使用中根据需要存入的数据大小定义不同的BLOB类型。
  • 需要注意的是:如果存储的文件过大,数据库的性能会下降。

向数据表中插入大数据类型

//获取连接
Connection conn = JDBCUtils.getConnection();
String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)"; PreparedStatement ps = conn.prepareStatement(sql);
// 填充占位符
ps.setString(1, "徐海强");
ps.setString(2, "[email protected]");
ps.setDate(3, new Date(new java.util.Date().getTime()));
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("xhq.png");
ps.setBlob(4, fis);
//执行
ps.execute();
fis.close();
JDBCUtils.closeResource(conn, ps);

修改数据表中的Blob类型字段

Connection conn = JDBCUtils.getConnection();
String sql = "update customers set photo = ? where id = ?"; PreparedStatement ps = conn.prepareStatement(sql);
// 填充占位符
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("coffee.png"); ps.setBlob(1, fis);
ps.setInt(2, 25);
ps.execute();
fis.close();
JDBCUtils.closeResource(conn, ps);

从数据表中读取大数据类型

String sql = "SELECT id, name, email, birth, photo FROM customer WHERE id = ?";
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, 8);
rs = ps.executeQuery();

if(rs.next()){
 Integer id = rs.getInt(1);
 String name = rs.getString(2);
 String email = rs.getString(3);
 Date birth = rs.getDate(4);
 Customer cust = new Customer(id, name, email, birth);  System.out.println(cust); 
 
 //读取Blob类型的字段
 Blob photo = rs.getBlob(5);
 InputStream is = photo.getBinaryStream(); 
  OutputStream os = new FileOutputStream("c.jpg");  
  byte [] buffer = new byte[1024];
 int len = 0;
 
 while((len = is.read(buffer)) != -1){
 os.write(buffer, 0, len);
 }
 
 JDBCUtils.closeResource(conn, ps, rs);
 if(is != null){
  is.close();
 }
 if(os !=  null){
   os.close();
}
}

注意事项

如果在指定了相关的Blob类型以后,还报错:xxx too large,那么在mysql的安装目录下,找my.ini文件加上如下的配置参数: max_allowed_packet=16M。同时注意:修改了my.ini文件之后,需要重新启动mysql服务。

创建和调用存储过程

在SQLServer数据库中创建存储过程:

create procedure insertData 
	@stuID varchar(10),
	@stuName varchar(20),
	@sex char(2),
	@birthday datetime
as 
	insert into student    
            values(@stuID,@stuName,@sex,@birthday)

在程序中调用存储过程

  //**在连接对象的基础上创建CallableStatement对象**
    CallableStatement cst = conn.prepareCall("
			{call insertData(?,?,?,?)}");
    //给参数设置值
    cst.setString(1, stuID);
    cst.setString(2, stuName);
    cst.setString(3, sex);
    cst.setString(4, birth);
    int r=cst.executeUpdate();
    cst.close();

DAO

DAO(Data Access Object) 数据访问对象是一个面向对象的数据库接口,它显露了 Microsoft Jet 数据库引擎(由 Microsoft Access 所使用),并允许 Visual Basic 开发者通过 ODBC 像直接连接到其他数据库一样,直接连接到 Access 表。DAO 最适用于单系统应用程序或小范围本地分布使用。

DAO层一般有接口和该接口的实现类,接口用于规范实现类,实现类一般用于用于操作数据库! 一般操作修改,添加,删除数据库操作的步骤很相似,就写了一个公共类DAO类 ,修改,添加,删除数据库操作时直接调用公共类DAO类。

dao层:dao层叫数据访问层,全称为data access object,属于一种比较底层,比较基础的操作,具体到对于某个表、某个实体的增删改查

Java数据库编程(JDBC)-入门笔记_第6张图片

第四节数据库连接池

知道一下就好

享元模式

• Connection是Java和数据库两个平行系统的桥梁
• 桥梁构建不易,成本很高,单次使用成本昂贵
• 运用共享技术来实现数据库连接池(享元模式)
– 降低系统中数据库连接Connection对象的数量
– 降低数据库服务器的连接响应消耗
– 提高Connection获取的响应速度

• 享元模式, Flyweight Pattern
– 经典23个设计模式的一种,属于结构型模式。
– 一个系统中存在大量的相同的对象,
由于这类对象的大量使用,会造成系统内存的耗费,
可以使用享元模式来减少系统中对象的数量。

理解池Pool的概念

– 初始数、最大数、增量、超时时间等参数。
• 常用的数据库连接池
– DBCP (Apache, http://commons.apache.org/,性能较差)
– C3P0 (https://www.mchange.com/projects/c3p0/)
– Druid (Alibaba, https://github.com/alibaba/druid)
– ……

C3P0连接池

<default-config> 
<property
name="driverClass">com.mysql.jdbc.Driverproperty>
<property
name="jdbcUrl">jdbc:mysql://localhost:3306/testproperty>
<property name="user">rootproperty>
<property name="password">123456property>
<property name="initialPoolSize">5property>
<property name="maxPoolSize">20property>
default-config>

• driverClass 驱动class,这里为mysql的驱动
• jdbcUrl jdbc链接
• user password数据库用户名密码
• initialPoolSize 初始数量:一开始创建多少条链接
• maxPoolSize 最大数:最多有多少条链接
• acquireIncrement 增量:用完每次增加多少个
• maxIdleTime最大空闲时间:超出的链接会被抛弃

你可能感兴趣的:(javase基础,jdbc,Statement,PreparedStateme,预编译,事务)