jdbc 订阅
Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。 展开全文
Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。
信息
简    称
JDBC
类    别
应用程序接口
中文名
Java数据库连接
外文名
Java Database Connectivity
Java数据库连接程序类型
JDBC驱动程序共分四种类型:JDBC-ODBC桥这种类型的驱动把所有JDBC的调用传递给ODBC,再让后者调用数据库本地驱动代码(也就是数据库厂商提供的数据库操作二进制代码库,例如Oracle中的oci.dll)。本地API驱动这种类型的驱动通过客户端加载数据库厂商提供的本地代码库(C/C++等)来访问数据库,而在驱动程序中则包含了Java代码。网络协议驱动这种类型的驱动给客户端提供了一个网络API,客户端上的JDBC驱动程序使用套接字(Socket)来调用服务器上的中间件程序,后者在将其请求转化为所需的具体API调用。本地协议驱动这种类型的驱动使用Socket,直接在客户端和数据库间通信。
收起全文
精华内容
参与话题
问答
  • JDBC详细介绍

    万次阅读 多人点赞 2018-07-30 09:25:43
    JDBC介绍 JDBC编程步骤 1.装载相应的数据库的JDBC驱动并进行初始化 2.建立JDBC和数据库之间的Connection连接 3.创建Statement或者PreparedStatement接口,执行SQL语句 4.处理和显示结果 5.释放资源 Statement...

    目录

    前言

    JDBC介绍

    JDBC编程步骤 

    1.装载相应的数据库的JDBC驱动并进行初始化

    2.建立JDBC和数据库之间的Connection连接

    3.创建Statement或者PreparedStatement接口,执行SQL语句

    4.处理和显示结果

    5.释放资源

    Statement和PreparedStatement的异同及优缺点

    execute和executeUpdate的区别



    前言

    笔者花了一整天的时间仔细研究了JDBC的使用,内容很充实,代码也都经过了验证。如果你能够仔细阅读完这篇文章,JDBC的相关知识我想你一定会有所掌握。在阅读的过程中,有任何不理解的地方都欢迎留言讨论。

    JDBC介绍

    JDBC(Java DataBase Connectivity)是Java和数据库之间的一个桥梁,是一个规范而不是一个实现,能够执行SQL语句。它由一组用Java语言编写的类和接口组成。各种不同类型的数据库都有相应的实现,本文中的代码都是针对MySQL数据库实现的。

    JDBC编程步骤 

    1.装载相应数据库的JDBC驱动并进行初始化

    • 导入专用的jar包(不同的数据库需要的jar包不同)

            访问MySQL数据库需要用到第三方的类,这些第三方的类,都被压缩在一个.Jar的文件里。mysql-connector-java-5.0.8-bin.jar包可以在网上下载,或者在MySQL的安装目录下找到。通常下载到该jar包之后将其放到在项目的lib目录下,在本例就会放在E:\project\j2se\lib 这个位置,然后在eclipse中导入这个jar包。

            导包步骤: 右键project->property->java build path->libaries->add external jars

    如果没有完成上述步骤的导包操作,后面会抛出ClassNotFoundException

    • 初始化驱动

          通过初始化驱动类com.mysql.jdbc.Driver,该类就在 mysql-connector-java-5.0.8-bin.jar中。如果你使用的是oracle数据库那么该驱动类将不同。

            注意:Class.forName需要捕获ClassNotFoundException.

    try {
            Class.forName("com.mysql.jdbc.Driver");		
            } catch (ClassNotFoundException e) { 				
                e.printStackTrace();
            }

    Class.forName是把这个类加载到JVM中,加载的时候,就会执行其中的静态初始化块,完成驱动的初始化的相关工作。 

    2.建立JDBC和数据库之间的Connection连接

    这里需要提供:数据库服务端的IP地址:127.0.0.1 (这是本机,如果连接其他电脑上的数据库,需填写相应的IP地址)
                             数据库的端口号: 3306 (mysql专用端口号)
                             数据库名称 exam(根据你自己数据库中的名称填写
                             编码方式 UTF-8
                             账号 root
                             密码 admin(如果你在创建数据库的时候没有使用默认的账号和密码,请填写自己设置的账号和密码

    Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/exam?characterEncoding=UTF-8", "root", "admin");

     Connection是与特定数据库连接回话的接口,使用的时候需要导包,而且必须在程序结束的时候将其关闭。getConnection方法也需要捕获SQLException异常。

    因为在进行数据库的增删改查的时候都需要与数据库建立连接,所以可以在项目中将建立连接写成一个工具方法,用的时候直接调用即可:

            /**
    	 * 取得数据库的连接
    	 * @return 一个数据库的连接
    	 */
    public static Connection getConnection(){
    		Connection conn = null;
    		 try {
    			 	//初始化驱动类com.mysql.jdbc.Driver
    	            Class.forName("com.mysql.jdbc.Driver");
    	            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/exam?characterEncoding=UTF-8","root", "admin");
    	            //该类就在 mysql-connector-java-5.0.8-bin.jar中,如果忘记了第一个步骤的导包,就会抛出ClassNotFoundException
    	        } catch (ClassNotFoundException e) { 				
    	            e.printStackTrace();
    	        }catch (SQLException e) {							
    	            e.printStackTrace();
    	        }
    		 return conn;
    	}

    3.创建Statement或者PreparedStatement接口,执行SQL语句

    • 使用Statement接口

    Statement接口创建之后,可以执行SQL语句,完成对数据库的增删改查。其中 ,增删改只需要改变SQL语句的内容就能完成,然而查询略显复杂。在Statement中使用字符串拼接的方式,该方式存在句法复杂,容易犯错等缺点,具体在下文中的对比中介绍。所以Statement在实际过程中使用的非常的少,所以具体的放到PreparedStatement那里给出详细代码。

    字符串拼接方式的SQL语句是非常繁琐的,中间有很多的单引号和双引号的混用,极易出错。

    Statement s = conn.createStatement();
    // 准备sql语句
    // 注意: 字符串要用单引号'
    String sql = "insert into t_courses values(null,"+"'数学')";
    //在statement中使用字符串拼接的方式,这种方式存在诸多问题
    s.execute(sql);
    System.out.println("执行插入语句成功");
    • 使用PreparedStatement接口

    与 Statement一样,PreparedStatement也是用来执行sql语句的与创建Statement不同的是,需要根据sql语句创建PreparedStatement。除此之外,还能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接。

    给数据库中添加课程: (以下代码中最后关闭资源的两个方法 DbUtil.close(pstmt);  DbUtil.close(conn);  和上面的建立连接的方法是一样的,是在工具类中定义了的关闭方法,下文会给出其代码

            /**
    	 * 添加课程
    	 * @param courseName 课程名称
    	 */
    	public void addCourse(String courseName){
    		String sql = "insert into t_course(course_name) values(?)";  
     //该语句为每个 IN 参数保留一个问号(“?”)作为占位符
    		Connection conn = null;				//和数据库取得连接
    		PreparedStatement pstmt = null;		//创建statement
    		try{
    			conn = DbUtil.getConnection();
    			pstmt = (PreparedStatement) conn.prepareStatement(sql);
    			pstmt.setString(1, courseName); //给占位符赋值
    			pstmt.executeUpdate();			//执行
    		}catch(SQLException e){
    			e.printStackTrace();
    		}
    		finally{
    			DbUtil.close(pstmt);
    			DbUtil.close(conn);		//必须关闭
    		}
    	}

    对数据库中的课程进行删除: 

            /**
    	 * 删除课程
    	 * @param courseId
    	 */
    	public void delCourse(int courseId){
    		String sql = "delete from t_course where course_id = ?";
    		Connection conn = null;
    		PreparedStatement pstmt = null;
    		try {
    			conn = DbUtil.getConnection();
    			pstmt = (PreparedStatement) conn.prepareStatement(sql);
    			pstmt.setInt(1, courseId);
    			pstmt.executeUpdate();
    		} catch (SQLException e) {
    			// TODO: handle exception
    			e.printStackTrace();
    		}finally{
    			DbUtil.close(pstmt);
    			DbUtil.close(conn);		//必须关闭
    		}
    	}

    对数据库中的课程进行修改:

            /**
    	 * 修改课程
    	 * @param courseId
    	 * @param courseName
    	 */
    	public void modifyCourse(int courseId,String courseName){
    		String sql = "update t_course set course_name =? where course_id=?";
    		Connection conn = null;
    		PreparedStatement pstmt = null;
    		try {
    			conn = DbUtil.getConnection();
    			pstmt = (PreparedStatement) conn.prepareStatement(sql);
    			pstmt.setString(1, courseName);  //利用Preparedstatement的set方法给占位符赋值
    			pstmt.setInt(2, courseId);
    			pstmt.executeUpdate();
    		} catch (SQLException e) {
    			// TODO: handle exception
    			e.printStackTrace();
    		}finally{
    			DbUtil.close(pstmt);
    			DbUtil.close(conn);		//必须关闭
    		}
    	}

     由上面的增删改程序可以看出,他们的代码都是大同小异的,主要是SQL语句存在差异,其他的地方几乎是完全相同的。其中有几个地方需要注意:

    1. 使用PreparedStatement时,他的SQL语句不再采用字符串拼接的方式,而是采用占位符的方式。“?”在这里就起到占位符的作用。这种方式除了避免了statement拼接字符串的繁琐之外,还能够提高性能。每次SQL语句都是一样的,java类就不会再次编译,这样能够显著提高性能。
      String sql = "update t_course set course_name =? where course_id=?";

      后面需要用到PreparedStatement接口创建的pstmt的set方法给占位符进行赋值。注意一点,这里的参数索引是从1开始的。

      pstmt = (PreparedStatement) conn.prepareStatement(sql);
      pstmt.setString(1, courseName);  //利用Preparedstatement的set方法给占位符赋值
      pstmt.setInt(2, courseId);
      pstmt.executeUpdate();

      增删改都使用pstmt.executeUpdate();语句进行SQL语句的提交 ,下文的查询会有所不同,请注意。

    2. 在添加的过程的,如果添加的数据量比较大的话,可以用批量添加。  PreparedStatement接口提供了相应的批量操作的方法。
    for(int i=1;i<100;i++){
         pstmt.setInt(1,8000+i);
         pstmt.setString(2,"赵_"+i);
         pstmt.addBatch();
    //批量更新
         if(i%10==0){
         pstmt.executeBatch();
        }
    }

    下面我们来看稍显麻烦一点的查询操作:

            /**
    	 * 查询课程
    	 * @return
    	 */
    	public List<Course> findCourseList(){
    		String sql = "select * from t_course order by course_id";
    		Connection conn = null;
    		PreparedStatement pstmt = null;
    		ResultSet rs = null;
    		//创建一个集合对象用来存放查询到的数据
    		List<Course> courseList = new ArrayList<>();
    		try {
    			conn = DbUtil.getConnection();
    			pstmt = (PreparedStatement) conn.prepareStatement(sql);
    			rs = (ResultSet) pstmt.executeQuery();
    			while (rs.next()){
    				int courseId = rs.getInt("course_id");
    				String courseName = rs.getString("course_name");
    				//每个记录对应一个对象
    				Course course = new Course();
    				course.setCourseId(courseId);
    				course.setCourseName(courseName);
    				//将对象放到集合中
    				courseList.add(course);
    			}
    		} catch (SQLException e) {
    			// TODO: handle exception
    			e.printStackTrace();
    		}finally{
    			DbUtil.close(pstmt);
    			DbUtil.close(conn);		//必须关闭
    		}
    		return courseList;
    	}

    查询操作使用executeQuery()进行更新。其他相关的问题放在第四步(处理和显示结果)中解释。

    4.处理和显示结果

     执行查询语句,并把结果集返回给集合ResultSet

    ResultSet rs = s.executeQuery(sql);

    利用While(ResultSet.next()){…}循环将集合ResultSet中的结果遍历出来。

    ResultSet.getXX();     这里的get方法的括号里面可以填属性值,如下图代码中的course_id,还可以填该属性在数据表中的列号,从1开始编码,例如:course_id在我的t-courses数据表中位于第一列,所以执行get方法的时候,我除了代码段中写法外,还可以这样写int courseId = rs.getInt(1);但是不推荐使用列号的这种方式,因为一段数据表中个属性值得顺序发生变化,就会导致这里出错,而使用属性名则不会出现这样的问题。

    while (rs.next()){
    		int courseId = rs.getInt("course_id");
    		String courseName = rs.getString("course_name");
    		//每个记录对应一个对象
    		Course course = new Course();
    //在我的项目中创建了course类,其中定义了set方法,所以这里将查询到的值传给了course,也可以直接打印到控制台
    		course.setCourseId(courseId);
    		course.setCourseName(courseName);
    		//将对象放到集合中
    		courseList.add(course);
    		}

    还有一点需要说明的是:

            因为在我的项目中创建了course类,其中定义了set方法,所以这里将查询到的值传给了course,你也可以直接用打印语句将CourseId和CourseName打印到控制台。

     course.setCourseId(courseId);
     course.setCourseName(courseName); 

    5.释放资源

    在JDBC编码的过程中我们创建了Connection、ResultSet等资源,这些资源在使用完毕之后是一定要进行关闭的。关闭的过程中遵循从里到外的原则。因为在增删改查的操作中都要用到这样的关闭操作,为了使代码简单,增加其复用性,这里我将这些关闭的操作写成一个方法和建立连接的方法一起放到一份工具类中。

    /**
    	 * 封装三个关闭方法
    	 * @param pstmt
    	 */
    	public static void close(PreparedStatement pstmt){
    		if(pstmt != null){						//避免出现空指针异常
    			try{
    				pstmt.close();
    			}catch(SQLException e){
    				e.printStackTrace();
    			}
    			
    		}
    	}
    	
    	public static void close(Connection conn){
    		if(conn != null){
    			try {
    				conn.close();
    			} catch (SQLException e) {
    				// TODO: handle exception
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	public static void close(ResultSet rs){
    		if (rs != null) {
    			try {
    				rs.close();
    			} catch (SQLException e) {
    				// TODO: handle exception
    				e.printStackTrace();
    			}
    		}
    	}

     JDBC编程的内容就这些了,如果你已经全部掌握,还有事务、获取自增、获取元数据、ORM、DAO、数据连接池等内容可以自行了解一下。

    另外,Statement和PreparedStatement的异同,execute和executeUpdate的区别等内容,这里做一些介绍。

    Statement和PreparedStatement的异同及优缺点

    同:两者都是用来执SQL语句的

    异:PreparedStatement需要根据SQL语句来创建,它能够通过设置参数,指定相应的值,不是像Statement那样使用字符串拼接的方式。

    PreparedStatement的优点:

    1、其使用参数设置,可读性好,不易记错。在statement中使用字符串拼接,可读性和维护性比较差。

    2、其具有预编译机制,性能比statement更快。

    3、其能够有效防止SQL注入攻击。

    execute和executeUpdate的区别

    相同点:二者都能够执行增加、删除、修改等操作。

    不同点:

    1、execute可以执行查询语句,然后通过getResult把结果取出来。executeUpdate不能执行查询语句。

    2、execute返回Boolean类型,true表示执行的是查询语句,false表示执行的insert、delete、update等。executeUpdate的返回值是int,表示有多少条数据受到了影响。

     

    关于JDBC的介绍就这么多了,欢迎评论区讨论。

    展开全文
  • JDBC,这一篇就够了

    千次阅读 多人点赞 2019-07-10 14:33:57
    第一章:JDBC入门 3.1.1 什么是 JDBC 使用 JDBC 的好处: 3.1.2 使用 JDBC 开发使用到的包: 3.2 JDBC 的核心 API 3.3 导入驱动 Jar 包 3.4 加载和注册驱动 第二章:DriverManager类 2.1 DriverManager 作用...

    目录

     第一章:JDBC入门

    3.1.1 什么是 JDBC

    使用 JDBC 的好处:

    3.1.2 使用 JDBC 开发使用到的包:

    3.2 JDBC 的核心 API

    3.3 导入驱动 Jar 包

    3.4 加载和注册驱动

    第二章:DriverManager类

    2.1 DriverManager 作用:

    2.2 类中的方法:

    2.3 使用 JDBC 连接数据库的四个参数:

    2.4 连接数据库的 URL 地址格式:

    协议名:子协议://服务器名或 IP 地址:端口号/数据库名?参数=参数值

    2.5 案例:得到 MySQL 的数据库连接对象

    第三章:Conection接口

    3.1 Connection 作用:

    3.2 Connection 方法:

    第四章:Statement接口

    4.1 JDBC 访问数据库的步骤

    4.2 Statement 作用:

    4.3 Statement 中的方法:

    4.4 释放资源

    4.5 执行 DDL 操作

    4.6 执行 DML 操作

    4.7 执行 DQL 操作

    第五章:数据库工具类JdbcUtils

    5.1 需求:

    第六章:PreparedStatement

    6.1 继承结构与作用:

    6.2 PreparedSatement 的执行原理

    6.3 Connection 创建 PreparedStatement 对象

    6.4 PreparedStatement 接口中的方法:

    6.5 PreparedSatement 的好处

    6.6 使用 PreparedStatement 的步骤:

    6.7 表与类的关系

    6.8 PreparedStatement 执行 DML 操作

    第七章:JDBC的事务处理

    7.1 准备数据

    7.2 API 介绍

    7.3 开发步骤


     第一章:JDBC入门

    客户端操作 MySQL 数据库的方式:

    1)使用第三方客户端来访问 MySQL:SQLyog、Navicat、SQLWave、MyDB Studio、EMS SQL Manager for MySQL

    2)使用 MySQL 自带的命令行方式

    3) 通过 Java 来访问 MySQL 数据库,今天要学习的内容\

    3.1.1 什么是 JDBC

    JDBC 规范定义接口,具体的实现由各大数据库厂商来实现。 

    JDBC Java 访问数据库的标准规范,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动。每个

    数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要会调用 JDBC 接口中的方法即

    可,数据库驱动由数据库厂商提供

    使用 JDBC 的好处:

    1) 程序员如果要开发访问数据库的程序,只需要会调用 JDBC 接口中的方法即可,不用关注类是如何实现的。

    2) 使用同一套 Java 代码,进行少量的修改就可以访问其他 JDBC 支持的数据库

    3.1.2 使用 JDBC 开发使用到的包:

    会使用到的包

    说明

    java.sql

    所有与 JDBC 访问数据库相关的接口和类

    javax.sql

    数据库扩展包,提供数据库额外的功能。如:连接池

    数据库的驱动

    由各大数据库厂商提供,需要额外去下载,是对 JDBC 接口实现的类

    3.2 JDBC 的核心 API

    接口或类

    作用

    DriverManager

    1) 管理和注册数据库驱动

    2) 得到数据库连接对象

    Connection 接口

    一个连接对象,可用于创建 Statement PreparedStatement 对象

    Statement 接口

    一个 SQL 语句对象,用于将 SQL 语句发送给数据库服务器。

    PreparedStatemen 接口

    一个 SQL 语句对象,是 Statement 的子接口

    ResultSet 接口

     

    3.3 导入驱动 Jar 包

       

    3.4 加载和注册驱动

    加载和注册驱动的方法

    描述

    Class.forName(数据库驱动实现类)

    加载和注册数据库驱动数据库驱动由 mysql 厂商 "com.mysql.jdbc.Driver"

    •  疑问:为什么这样可以注册驱动?
    package com.lqg;
    public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException {
    3 / 21//抛出类找不到的异常,注册数据库驱动
    Class.forName("com.mysql.jdbc.Driver");
        }
    }
     com.mysql.jdbc.Driver 源代码:
    // Driver 接口,所有数据库厂商必须实现的接口,表示这是一个驱动类。
    public class Driver implements java.sql.Driver {
    public Driver() throws SQLException {
        }
    static {
    try {
    DriverManager.registerDriver(new Driver()); //注册数据库驱动
    } catch (SQLException var1) {
    throw new RuntimeException("Can't register driver!");
            }
        }
    }
    • 注:从 JDBC3 开始,目前已经普遍使用的版本。可以不用注册驱动而直接使用。Class.forName 这句话可以省略。

    第二章:DriverManager类

    2.1 DriverManager 作用:

    1) 管理和注册驱动

    2) 创建数据库的连接

    2.2 类中的方法:

    DriverManager 类中的静态方法

    描述

    Connection getConnection (String url, String user, String password)

    通过连接字符串,用户名,密码来得到数据 库的连接对象

    Connection getConnection (String url, Properties info)

    通过连接字符串,属性对象来得到连接对象

    2.3 使用 JDBC 连接数据库的四个参数:

    JDBC 连接数据库的四个参数

    说明

    用户名

    登录的用户名

    密码

    登录的密码

    连接字符串 URL

    不同的数据库 URL 是不同的,mysql 的写法

    jdbc:mysql://localhost:3306/数据库[?参数名=参数值]

    驱动类的字符串名

    com.mysql.jdbc.Driver

     

    2.4 连接数据库的 URL 地址格式:

    协议名:子协议://服务器名或 IP 地址:端口号/数据库名?参数=参数值

    2.4.1 MySQL 写法:

    2.4.2 MySQL 中可以简写:

    前提:必须是本地服务器,端口号是 3306

    jdbc:mysql:///数据库名

    2.4.3 乱码的处理

    如果数据库出现乱码,可以指定参数: ?characterEncoding=utf8,表示让数据库以 UTF-8 编码来处理数据。

    jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8

    2.5 案例:得到 MySQL 的数据库连接对象

    1) 使用用户名、密码、URL 得到连接对象

    package com.lqg;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    /**
    * 得到连接对象
    */
    public class Demo2 {
    public static void main(String[] args) throws SQLException {
    String url = "jdbc:mysql://localhost:3306/day24";
    //1) 使用用户名、密码、URL 得到连接对象
    Connection connection = DriverManager.getConnection(url, "root", "root");
    //com.mysql.jdbc.JDBC4Connection@68de145
    System.out.println(connection);
        }
    }

    2) 使用属性文件和 url 得到连接对象

    package com.lqg;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Properties;
    public class Demo3 {
    public static void main(String[] args) throws SQLException {
    //url 连接字符串
    String url = "jdbc:mysql://localhost:3306/day24";
    //属性对象
    Properties info = new Properties();
    //把用户名和密码放在 info 对象中
    5 / 21info.setProperty("user","root");
    info.setProperty("password","root");
    Connection connection = DriverManager.getConnection(url, info);
    //com.mysql.jdbc.JDBC4Connection@68de145
    System.out.println(connection);
        }
    }

    第三章:Conection接口

    3.1 Connection 作用:

    Connection 接口,具体的实现类由数据库的厂商实现,代表一个连接对象。

    3.2 Connection 方法:

    Connection 接口中的方法

    描述

    Statement createStatement()

    创建一条 SQL 语句对象

    第四章:Statement接口

    4.1 JDBC 访问数据库的步骤

    1) 注册和加载驱动(可以省略)

    2) 获取连接

    3) Connection 获取 Statement 对象

    4) 使用 Statement 对象执行 SQL 语句

    5) 返回结果集

    6) 释放资源

    4.2 Statement 作用:

    代表一条语句对象,用于发送 SQL 语句给服务器,用于执行静态 SQL 语句并返回它所生成结果的对象。

    4.3 Statement 中的方法:

    Statement 接口中的方法

    描述

    int executeUpdate(String sql)

    用于发送 DML 语句,增删改的操作,insertupdate delete

    参数:SQL 语句

    返回值:返回对数据库影响的行数

    ResultSet executeQuery(String sql)

    用于发送 DQL 语句,执行查询的操作。select

    参数:SQL 语句

    返回值:查询的结果集

    4.4 释放资源

    1) 需要释放的对象:ResultSet 结果集,Statement 语句,Connection 连接

    2) 释放原则:先开的后关,后开的先关。ResultSet  Statement  Connection

    3) 放在哪个代码块中:finally 块

    4.5 执行 DDL 操作

    4.5.1 需求:使用 JDBC 在 MySQL 的数据库中创建一张学生表

    4.5.2 代码:

    package com.lqg;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    /**
    * 创建一张学生表
    */
    public class Demo4DDL {
    public static void main(String[] args) {
    //1. 创建连接
    Connection conn = null;
    Statement statement = null;
    try {
    conn = DriverManager.getConnection("jdbc:mysql:///day24", "root", "root");
    //2. 通过连接对象得到语句对象
    statement = conn.createStatement();
    //3. 通过语句对象发送 SQL 语句给服务器
    //4. 执行 SQL
    statement.executeUpdate("create table student (id int PRIMARY key auto_increment, " +
    "name varchar(20) not null, gender boolean, birthday date)");
    //5. 返回影响行数(DDL 没有返回值)
    System.out.println("创建表成功");
        } catch (SQLException e) {
    e.printStackTrace();
        }
    //6. 释放资源
    finally {
    //关闭之前要先判断
    if (statement != null) {
    try {
    statement.close();
    } catch (SQLException e) {
    e.printStackTrace();
        }
    7 / 21}
    if (conn != null) {
    try {
    conn.close();
    } catch (SQLException e) {
    e.printStackTrace();
              }
            }
          }
       }
    }

    4.6 执行 DML 操作

    • 需求:向学生表中添加 4 条记录,主键是自动增长

    • 步骤:

    1) 创建连接对象

    2) 创建 Statement 语句对象

    3) 执行 SQL 语句:executeUpdate(sql)

    4) 返回影响的行数

    5) 释放资源

    •  代码:
    package com.lqg;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    /**
    * 向学生表中添加 4 条记录,主键是自动增长
    */
    public class Demo5DML {
    public static void main(String[] args) throws SQLException {
    // 1) 创建连接对象
    Connection connection = DriverManager.getConnection("jdbc:mysql:///day24", "root",
    "root");
    // 2) 创建 Statement 语句对象
    Statement statement = connection.createStatement();
    // 3) 执行 SQL 语句:executeUpdate(sql)
    int count = 0;
    // 4) 返回影响的行数
    count += statement.executeUpdate("insert into student values(null, '孙悟空', 1, '1993-03-24')");
    count += statement.executeUpdate("insert into student values(null, '白骨精', 0, '1995-03-24')");
    count += statement.executeUpdate("insert into student values(null, '猪八戒', 1, '1903-03-8 / 2124')");
    count += statement.executeUpdate("insert into student values(null, '嫦娥', 0, '1993-03-11')");
    System.out.println("插入了" + count + "条记录");
    // 5) 释放资源
    statement.close();
    connection.close();
        }
    }

    4.7 执行 DQL 操作

    4.7.1 ResultSet 接口:

    •  作用:封装数据库查询的结果集,对结果集进行遍历,取出每一条记录。

    • 接口中的方法:

    ResultSet 接口中的方法

    描述

    boolean next()

    1) 游标向下移动 1

    2) 返回 boolean 类型,如果还有下一条记录,返回 true,否则返回 false

    数据类型 getXxx()

    1) 通过字段名,参数是 String 类型。返回不同的类型

    2) 通过列号,参数是整数,从 1 开始。返回不同的类型

                                   

    4.7.2 常用数据类型转换表

    SQL 类型

    Jdbc 对应方法 返回类型

    BIT(1) bit(n)

    getBoolean() boolean

    TINYINT

    getByte() byte

    SMALLINT

    getShort() short

    INT

    getInt() int

    BIGINT

    getLong() long

    CHAR,VARCHAR

    getString() String

    Text(Clob) Blob

    getClob getBlob() Clob Blob

    DATE

    getDate() java.sql.Date 只代表日期

    TIME

    getTime() java.sql.Time 只表示时间

    TIMESTAMP

    getTimestamp() java.sql.Timestamp 同时有日期和时间

    java.sql.DateTimeTimestamp(时间戳),三个共同父类是:java.util.Date

    4.7.3 需求:确保数据库中有 3 条以上的记录,查询所有的学员信息

    • 步骤:

    1) 得到连接对象

    2) 得到语句对象

    3) 执行 SQL 语句得到结果集 ResultSet 对象

    4) 循环遍历取出每一条记录

    5) 输出的控制台上

    6) 释放资源

    结果:

    package com.lqg;
    import java.sql.*;
    10 / 21/**
    * 查询所有的学生信息
    */
    public class Demo6DQL {
        public static void main(String[] args) throws SQLException {
        //1) 得到连接对象
        Connection connection =
        DriverManager.getConnection("jdbc:mysql://localhost:3306/day24","root","root");
        //2) 得到语句对象
        Statement statement = connection.createStatement();
        //3) 执行 SQL 语句得到结果集 ResultSet 对象
        ResultSet rs = statement.executeQuery("select * from student");
        //4) 循环遍历取出每一条记录
        while(rs.next()) {
            int id = rs.getInt("id");
            String name = rs.getString("name");
            boolean gender = rs.getBoolean("gender");
            Date birthday = rs.getDate("birthday");
        //5) 输出的控制台上
    System.out.println("编号:" + id + ", 姓名:" + name + ", 性别:" + gender + ", 生日:" +birthday);
    }
    //6) 释放资源
    rs.close();
    statement.close();
    connection.close();
        }
    }

    4.7.4 关于 ResultSet 接口中的注意事项: 

    1) 如果光标在第一行之前,使用 rs.getXX()获取列值,报错:Before start of result set

    2) 如果光标在最后一行之后,使用 rs.getXX()获取列值,报错:After end of result set

    3) 使用完毕以后要关闭结果集 ResultSet,再关闭 Statement,再关闭 Connection

    第五章:数据库工具类JdbcUtils

    • 什么时候自己创建工具类?

    如果一个功能经常要用到,我们建议把这个功能做成一个工具类,可以在不同的地方重用

    5.1 需求:

    5.3.1 需求

    1) 有一张用户表

    2) 添加几条用户记录

    create table user (
    id int primary key auto_increment,
    name varchar(20),
    password varchar(20)
    )
    insert into user values (null,'jack','123'),(null,'rose','456');
    -- 登录, SQL 中大小写不敏感
    select * from user where name='JACK' and password='123';
    -- 登录失败
    select * from user where name='JACK' and password='333';

    3) 使用 Statement 字符串拼接的方式实现用户的登录, 用户在控制台上输入用户名和密码。

    5.3.2 步骤:

    1) 得到用户从控制台上输入的用户名和密码来查询数据库

    2) 写一个登录的方法

    a) 通过工具类得到连接

    b) 创建语句对象,使用拼接字符串的方式生成 SQL 语句

    c) 查询数据库,如果有记录则表示登录成功,否则登录失

    d) 释放资源

    package com.lqg;
    import com.lqg.utils.JdbcUtils;
    import javax.xml.transform.Result;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Scanner;
    public class Demo7Login {
    //从控制台上输入的用户名和密码
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println("请输入用户名:");
    String name = sc.nextLine();
    System.out.println("请输入密码:");
    String password = sc.nextLine();
    login(name, password);
    13 / 21
        }
        /**
        * 登录的方法
        */
    public static void login(String name, String password) {
    //a) 通过工具类得到连接
    Connection connection = null;
    Statement statement = null;
    ResultSet rs = null;
    try {
    connection = JdbcUtils.getConnection();
    //b) 创建语句对象,使用拼接字符串的方式生成 SQL 语句
    statement = connection.createStatement();
    //c) 查询数据库,如果有记录则表示登录成功,否则登录失败
    String sql = "select * from user where name='" + name + "' and password='" + password
    + "'";
    System.out.println(sql);
    rs = statement.executeQuery(sql);
    if (rs.next()) {
    System.out.println("登录成功,欢迎您:" + name);
    } else {
    System.out.println("登录失败");
        }
        } catch (SQLException e) {
    e.printStackTrace();
    } finally {
    //d) 释放资源
    JdbcUtils.close(connection, statement, rs);
            } 
        }
    }

    5.3.3 SQL 注入问题

    • 当我们输入以下密码,我们发现我们账号和密码都不对竟然登录成功了
    请输入用户名:
    newboy
    请输入密码:
    a' or '1'='1
    select * from user where name='newboy' and password='a' or '1'='1'
    登录成功,欢迎您:newboy
    •  问题分析:
    select * from user where name='newboy' and password='a' or '1'='1'
    name='newboy' and password='a' 为假
    '1'='1' 真
    相当于
    select * from user where true; 查询了所有记录

    我们让用户输入的密码和 SQL 语句进行字符串拼接。用户输入的内容作为了 SQL 语句语法的一部分,改变了

    原有 SQL 真正的意义,以上问题称为 SQL 注入。要解决 SQL 注入就不能让用户输入的密码和我们的 SQL 语句进

    行简单的字符串拼接。

    第六章:PreparedStatement

    6.1 继承结构与作用:

    PreparedStatement Statement 接口的子接口,继承于父接口中所有的方法。它是一个预编译的 SQL 语句

    6.2 PreparedSatement 的执行原理

    1) 因为有预先编译的功能,提高 SQL 的执行效率。

    2) 可以有效的防止 SQL 注入的问题,安全性更高。

    6.3 Connection 创建 PreparedStatement 对象

    Connection 接口中的方法

    描述

    PreparedStatement prepareStatement(String sql)

    指定预编译的 SQL 语句,SQL 语句中使用占位符?

    创建一个语句对象

    6.4 PreparedStatement 接口中的方法:

    PreparedStatement 接口中的方法

    描述

    int executeUpdate()

    执行 DML,增删改的操作,返回影响的行数。

    ResultSet executeQuery()

    执行 DQL,查询的操作,返回结果集

    6.5 PreparedSatement 的好处

    1. prepareStatement()会先将 SQL 语句发送给数据库预编译。PreparedStatement 会引用着预编译后的结果。

    可以多次传入不同的参数给 PreparedStatement 对象并执行。减少 SQL 编译次数,提高效率。

    2. 安全性更高,没有 SQL 注入的隐患。

    3. 提高了程序的可读性

    6.6 使用 PreparedStatement 的步骤:

    1) 编写 SQL 语句,未知内容使用?占位:"SELECT * FROM user WHERE name=? AND password=?";

    2) 获得 PreparedStatement 对象

    3) 设置实际参数:setXxx(占位符的位置, 真实的值)

    4) 执行参数化 SQL 语句

    5) 关闭资源

    PreparedStatement 中设置参数的方法

    描述

    void setDouble(int parameterIndex, double x)

    将指定参数设置为给定 Java double 值。

    void setFloat(int parameterIndex, float x)

    将指定参数设置为给定 Java REAL 值。

    void setInt(int parameterIndex, int x)

    将指定参数设置为给定 Java int 值。

    void setLong(int parameterIndex, long x)

    将指定参数设置为给定 Java long 值。

    void setObject(int parameterIndex, Object x)

    使用给定对象设置指定参数的值。

    void setString(int parameterIndex, String x)

    将指定参数设置为给定 Java String 值。
    • 使用 PreparedStatement 改写上面的登录程序,看有没有 SQL 注入的情况
    package com.lqg;
    import com.itheima.utils.JdbcUtils;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Scanner;
    /**
    * 使用 PreparedStatement
    */
    public class Demo8Login {
        //从控制台上输入的用户名和密码
        public static void main(String[] args) throws SQLException {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名");
        String name = sc.nextLine();
        System.out.println("请输入密码:");
        String password = sc.nextLine();
        login(name, password);
    }
    /**
    * 登录的方法
    * @param name
    16 / 21
    * @param password
    */
    private static void login(String name, String password) throws SQLException {
        Connection connection = JdbcUtils.getConnection();
        //写成登录 SQL 语句,没有单引号
        String sql = "select * from user where name=? and password=?";
        //得到语句对象
        PreparedStatement ps = connection.prepareStatement(sql);
        //设置参数
        ps.setString(1, name);
        ps.setString(2,password);
        ResultSet resultSet = ps.executeQuery();
        if (resultSet.next()) {
        System.out.println("登录成功:" + name);
        }
        else {
        System.out.println("登录失败");
        }
        //释放资源,子接口直接给父接口
        JdbcUtils.close(connection,ps,resultSet);
        } 
    }

    6.7 表与类的关系

     

    6.7.1 案例:使用 PreparedStatement 查询一条数据,封装成一个学生 Student 对象

    package com.lqg;
    import com.lqg.entity.Student;
    import com.lqg.utils.JdbcUtils;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    public class Demo9Student {
    public static void main(String[] args) throws SQLException {
        //创建学生对象
        Student student = new Student();
        17 / 21
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement ps = connection.prepareStatement("select * from student where              id=?");
        //设置参数
        ps.setInt(1,2);
        ResultSet resultSet = ps.executeQuery();
        if (resultSet.next()) {
        //封装成一个学生对象
        student.setId(resultSet.getInt("id"));
        student.setName(resultSet.getString("name"));
        student.setGender(resultSet.getBoolean("gender"));
        student.setBirthday(resultSet.getDate("birthday"));
        }
        //释放资源
        JdbcUtils.close(connection,ps,resultSet);
        //可以数据
        System.out.println(student);
        } 
    }

    6.7.2 案例:将多条记录封装成集合 List<Student>,集合中每个元素是一个 JavaBean 实体类

    • 需求: 查询所有的学生类,封装成 List<Student>返回
    •  代码:

    package com.lqg;
    import com.lqg.entity.Student;
    import com.lqg.utils.JdbcUtils;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    public class Demo10List {
    public static void main(String[] args) throws SQLException {
        //创建一个集合
        List<Student> students = new ArrayList<>();
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement ps = connection.prepareStatement("select * from student");
        //没有参数替换
        ResultSet resultSet = ps.executeQuery();
        while(resultSet.next()) {
        //每次循环是一个学生对象
        Student student = new Student();
        //封装成一个学生对象
        student.setId(resultSet.getInt("id"));
        18 / 21
        student.setName(resultSet.getString("name"));
            student.setGender(resultSet.getBoolean("gender"));
        student.setBirthday(resultSet.getDate("birthday"));
        //把数据放到集合中
        students.add(student);
        }
        //关闭连接
        JdbcUtils.close(connection,ps,resultSet);
        //使用数据
        for (Student stu: students) {
        System.out.println(stu);
            } 
        }
     }

    6.8 PreparedStatement 执行 DML 操作

    package com.lqg;
    import com.lqg.utils.JdbcUtils;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    public class Demo11DML {
    public static void main(String[] args) throws SQLException {
        //insert();
        //update();
        delete();
        }
        //插入记录
        private static void insert() throws SQLException {
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement ps = connection.prepareStatement("insert into student
        values(null,?,?,?)");
        ps.setString(1,"小白龙");
        ps.setBoolean(2, true);
        ps.setDate(3,java.sql.Date.valueOf("1999-11-11"));
        int row = ps.executeUpdate();
        System.out.println("插入了" + row + "条记录");
        JdbcUtils.close(connection,ps);
        }
        //更新记录: 换名字和生日
        private static void update() throws SQLException {
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement ps = connection.prepareStatement("update student set name=?,         birthday=?
        where id=?");
        ps.setString(1,"黑熊怪");
        ps.setDate(2,java.sql.Date.valueOf("1999-03-23"));
        ps.setInt(3,5);
        int row = ps.executeUpdate();
        System.out.println("更新" + row + "条记录");
        JdbcUtils.close(connection,ps);
        }
        19 / 21
        //删除记录: 删除第 5 条记录
        private static void delete() throws SQLException {
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement ps = connection.prepareStatement("delete from student where id=?");
        ps.setInt(1,5);
        int row = ps.executeUpdate();
        System.out.println("删除了" + row + "条记录");
        JdbcUtils.close(connection,ps);
        } 
    }

    第七章:JDBC的事务处理

    之前我们是使用 MySQL 的命令来操作事务。接下来我们使用 JDBC 来操作银行转账的事务。

    7.1 准备数据

    CREATE TABLE account (
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(10),
    balance DOUBLE
    );
    -- 添加数据
    INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000);

     

    7.2 API 介绍

    Connection 接口中与事务有关的方法

    说明

    void setAutoCommit(boolean autoCommit)

    参数是 true false
     

    如果设置为 false,表示关闭自动提交,相当于开启事务

    void commit()

    提交事务

    void rollback()

    回滚事务

    7.3 开发步骤

    1) 获取连接

    2) 开启事务

    3) 获取到 PreparedStatement

    4) 使用 PreparedStatement 执行两次更新操作

    5) 正常情况下提交事务

    6) 出现异常回滚事务

    7) 最后关闭资源

    • 案例代码
    package com.lqg;
    import com.lqg.utils.JdbcUtils;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    public class Demo12Transaction {
        //没有异常,提交事务,出现异常回滚事务
        public static void main(String[] args) {
        20 / 21
        //1) 注册驱动
        Connection connection = null;
        PreparedStatement ps = null;
        try {
        //2) 获取连接
        connection = JdbcUtils.getConnection();
        //3) 开启事务
        connection.setAutoCommit(false);
        //4) 获取到 PreparedStatement
        //从 jack 扣钱
        ps = connection.prepareStatement("update account set balance = balance - ? where
        name=?");
        ps.setInt(1, 500);
        ps.setString(2,"Jack");
        ps.executeUpdate();
        //出现异常
        System.out.println(100 / 0);
        //给 rose 加钱
        ps = connection.prepareStatement("update account set balance = balance + ? where
        name=?");
        ps.setInt(1, 500);
        ps.setString(2,"Rose");
        ps.executeUpdate();
        //提交事务
        connection.commit();
        System.out.println("转账成功");
        } catch (Exception e) {
        e.printStackTrace();
        try {
        //事务的回滚
        connection.rollback();
        } catch (SQLException e1) {
        e1.printStackTrace();
        }
        System.out.println("转账失败");
        }
        finally {
        //7) 关闭资源
        JdbcUtils.close(connection,ps);
            } 
        }
    }

                                                           觉得文章对自己有用,想要继续学下去的可以

                                                                             可以长按下方二维码        

                                                                    

                                                                               关注【javalingfeng】哦

                                                              公众号正在更新vue.js和springboot的详细教程

                                                              还有超多免费Java,Python,Android等系列教程

                                                                                        等你来领

     

     

     

     

    展开全文
  • Java JDBC的基本知识

    万次阅读 多人点赞 2016-07-19 17:16:27
    JDBC   Java数据库连接,提供了一种与平台无关的用于执行SQL语句的标准javaAPI,可以方便实现多种关系型数据库的统一操作 JDBC驱动分类 JDBC-ODBC桥驱动 ODBC是由微软提供的编程接口,JDBC也是模仿了ODBC...

    JDBC

     

    • Java数据库连接,提供了一种与平台无关的用于执行SQL语句的标准javaAPI,可以方便实现多种关系型数据库的统一操作
    • JDBC驱动分类
      • JDBC-ODBC桥驱动
        • ODBC是由微软提供的编程接口,JDBC也是模仿了ODBC的设计
      • JDBC-本地驱动
        • 直接使用各个数据库生产商提供的JDBC驱动程序,因为只能应用在特定的数据库上,会丧失程序的可移植性,不过性能很高。
      • JDBC-网络驱动
        • 将JDBC转换为与DBMS无关的网络协议,之后又被某个服务器转换为一种DBMS协议,所用的具体协议取决于提供者,最为灵活
      • 本地协议纯JDBC驱动
        • 将JDBC转换为DBMS所使用的网络协议。
      • 主要操作类及接口
        • 常用的类与接口就是DriverManager、Connection、Statement、Result、PreparedStatement

       

    • MySQl数据库
      • 常用命令
        • 创建数据库:create database 数据库名称 ;
        • 删除数据库:drop database  数据库名称 ;       
        • 使用数据库:use 数据库名称 ;
        • 创建数据库表:create table 表名( 字段名称1 字段类型[default 默认值] [约束], ...) ;
        • 删除数据库表:drop table 表名 ;
        • 查看表结构: desc  表名称 ;   
        • 查看全部数据库:show databases ;
        • 查看一个数据库全部表: show tables ;

     

    • SQL语法基础(Structured Query Language,结构查询语句)强大的数据库语言
        • DML-数据操作语言:检索或修改数据
        • DDL-数据定义语言:定义数据的结构,创建、修改、删除
        • DCL-数据控制语言:定义 数据库用户的权限
      • 数据类型
        • 整型数据
        • 时间日期类
        •  
        • 字符串类型
      • 插入数据:insert into 表名称( 字段 )   values(值...);
      • 删除数据:delete from 表名称 [删除条件] ;  若无条件则清空表,条件如 “where id =1"
      • 更新数据:update 表名称 set 字段1 =值 1 ...  [where 更新条件]
      • 查询数据:select {*|colum alias} from 表名 [where ];  
        • 模糊搜索:select * from table where name like '%m%' or password like '%m%' ;搜索姓名或密码含有m 的用户
        • 加入limit 限制语句,limit 0,5 ; 限制从第1-5行的记录

     

    •  JDBC操作步骤
      • 连接数据库
        • 配置MySQL数据库的驱动程序
          • 下载 mysql-connector-java-5.1.39.zip,复制到jdk的所在处
          • public class jdbc {
            public static final String DRIVER="org.gjt.mm.mysql.Driver";
            public static void main(String[] args){
            try{
            System.out.println(Class.forName(DRIVER)) ;
            }catch(ClassNotFoundException e){
            e.printStackTrace() ;
            }
            }
            }    
                  
          • 若能输出Class名,则已配置好了
          • 为什么调用Class.forName(),却没有newInstance(); 
            • Class.forName() 加载了指定类后,若类中有静态初始化器,JVM必然会执行该类的静态代码段,而JDBC的Driver类都是会有static代码块  

     

        • DriverManager
          • getConnection(String url, String user ,String password) :通过连接地址链接数据库,同时输入用户名和密码
          • url:  jdbc:mysql://  ip地址 : 端口号/ 数据库名称             
            • jdbc协议:JDBC URL中的协议总是jdbc
            • 子协议:驱动程序名或数据库连接机制(这种机制可由一个或多个驱动程序支持)的名称,如mysql
            • 子名称:一种标识数据库的方法,必须遵循”//主机名 : 端口/子协议"  的标准URL命名    约定
          • Connection接口

     

        • 执行数据库的更新操作
          • Statement接口,通过Connection接口的createStatement()方法实例化,来操作数据
          • public static final String DRIVER="org.gjt.mm.mysql.Driver";
            public static final String URL="jdbc:mysql://localhost:3306/newsql";
            public static final String USERNAME="root";
            public static void main(String[] args)throws Exception{
            Connection conn=null;
            Statement statement=null;
            String sql="insert into newtable(name) values('ccw')";
            try{
            Class.forName(DRIVER); //加载驱动
            }catch(ClassNotFoundException e){
            e.printStackTrace() ;
            }
            conn=DriverManager.getConnection(URL,USERNAME,USERNAME);
            statement=conn.createStatement();
            statement.executeUpdate(sql);
            try{
            statement.close();     //先开后关闭,可以只关闭connection
            conn.close();
            }catch(Exception e){
            e.printStackTrace();
            }
            }

             

    • ResultSet接口
      • 接受所查询的记录,并显示内容,开发中要限制查询数量
      • Statement接口的executeQuery() 方法,返回一个ResultSet对象

      • ResultSet rSet=statement.executeQuery(sql);
        while(rSet.next()){
        int id=rSet.getInt("id"); //int id=rSet.getInt(1);
        String name=rSet.getString("name"); //String name=rSet.getString(2);
        String sex=rSet.getString("sex"); //....
        System.out.println(id+name+sex);
        }

         

      • ResultSet的所有数据都可以通过getString()方法获得

     

    • PreparedStatement接口
      • 是Statement的子接口,属于预处理操作,与直接使用Statement不同的是,是先在数据表中准备好了一条SQL语句,但是此SQL语句的具体内容暂时不设置,而是之后在进行设置,即占住此位置等待用户设置
      • String sql="insert into newtable(name,sex) values(?,?)";
        pStatement=conn.prepareStatement(sql); //实例化
        pStatement.setString(1, name);
        pStatement.setString(2, sex);
        pStatement.executeUpdate();

         

      • 注意:开发中不建议使用Statement来操作数据库,而是使用PreparedStatement,因为Statement是完整的SQL语句

     

    • 处理大数据对象——必须使用PreparedStatement
      • CLOB:存储海量文字
      • BLOB    存储二进制数据
      • 写入大对象数据——IO流的模式
      • 读取大对象数据
        • 处理CLOB
          • 使用Clob操作比InputStream更加方便
          • String sql="select name,note from bigtable where id =?";
            pStatement=conn.prepareStatement(sql);
            pStatement.setInt(1, 1);
            ResultSet rs=pStatement.executeQuery();
            while(rs.next()){
            String name=rs.getString(1);
            Clob clob=rs.getClob(2);
            String note=clob.getSubString(1, (int)clob.length());
            System.out.println(name+" "+note);
            }

             

        • 处理BLOB
          • 创建表:create table userBlob(id int auto_increment primary key,name char(30), photo longblob) ;
            • 存储图片
            • String sql="insert into userblob(name, photo) values(?,?)";
              pStatement=conn.prepareStatement(sql);
              File file=new File("d:"+File.separator+"my.jpg");
              InputStream input=new FileInputStream(file);
              pStatement.setString(1, name);
              pStatement.setBinaryStream(2, input);
              pStatement.executeUpdate();

               

          • 使用BLOB方法更加方便
            • if(rSet.next()){
              String name=rSet.getString(1);
              Blob blob=rSet.getBlob(2);
              FileOutputStream output=new FileOutputStream(newFile("d:"+File.separator+"you.jpg"));
              output.write(blob.getBytes(1,(int)blob.length()));
              output.close();
              }

     

    • CallableStatement接口——主要调用数据库中的存储过程
      • 即为一种方法,可以调用, 传递参数  
      • delimiter // //这里是改变执行操作语句的分隔符,也就是将SQL语句的";"结尾符号改为"//"
        drop procedure myproc //
        create procedure myproc(IN p1 int, INOUT p2 int ,OUT p3 int)
        begin
        select p1,p2,p3 ;
        set p1=10;
        set p2=20;
        set p3=30;
        end
        //

         

      • 3个类型
        • IN(默认的类型):表示只是将值传进来
        • INOUT:表示把值传递到过程中,可以保留过程对此值得修改值
        • OUT:可以不传递内容进来,过程中对此值得操作可以返回
        • String sql="{call myproc(?,?,?)}";
          CallableStatement cstmt=conn.prepareCall(sql);
          cstmt.setInt(1,70);
          cstmt.setInt(2,80);
          cstmt.registerOutParameter(2,Types.INTEGER);     //设置返回值类型
          cstmt.registerOutParameter(3,Types.INTEGER);
          cstmt.execute();

           

     

    • JDBC2.0
      • ResultSet的更新
        • 设置ResultSet的类型:TYPER_XXX设置类型,表示是否可以滚动以及是否可以修改数据表的内容
        • 设置CONCUR_XXX设置的都是并发性,并发性主要表示结果集是否是只读还是可以进行数据库更新
      • 可滚动的结果集——现在想取结果集中任意位置的数据
      • PreparedStatement pstmt=conn.prepareStatement(sql,ResultSet.TYPE_SCROLL SENSITIVE,ResultSet.CONCUR_READ_ONLY); 
                          
        • 使用结果集插入数据
          • rs.insertRow(); //插入数据
            ...
            rs.updateString("name","李华");
            rs.movetoInsertRow(); //移动到可插入的行
            ResultSet rs=pstmt.executeQuery();
            PreparedStatement pstmt=conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATE);

             

      • 批处理
      • for(int i=0;i<10;i++){
        ps.setString(1,"ccw"+i );
        ps.setString(2, "nan"+i);
        ps.addBatch();
        }
        ps.executeBatch();  
        

         

    • 事务处理
      • 原子性:最小的单元,如果一个是失败了,则一切的操作将全部失败。
      • 一致性:如果事务出现错误,则回到最原始的状态
      • 隔离性:多个事务之间无法访问,只有当事务完成后才可以看到结果
      • 持久性:当一个系统崩溃时,一个事务依然可以提交,当事务完成后,操作结果保存在磁盘中,不会被回滚
        • 数据库把每一个连接到此数据库上的用户都称为一个session,如下是步骤
          • 取消自动提交, set autocommit=0 ,所有更新指令并不会立刻发送到数据表中,只存于当前的session
          • 开启事务:      start transaction 或者 begin
          • 编写数据库更新语句(增加、删除、修改),可以记录事务的保存点,使用savepoint
          • 提交事务:  commit 
          • 事务回滚:  rollback 或者  rollback to savepoint     如果执行的sql语句有错误,则回滚

     

    • 使用元数据分析数据库
      • DatabaseMetaDate
        • 得到数据库的名称、版本、表的信息
        • 实例化   DatabaseMetaDate dmd=connection.getMetData(); 
      • ResultSetMetaData
        • 可获取关于ResultSet对象中列的类型和属性信息的对象
        • 实例化: ResultSetMetaData rsmd =preparedStatement.getMetaData();
    • 使用JDBC链接Oracle数据库
      • 对于每一种驱动的改动都不是很大,所以我这里也就不简单讲了,具体的呢就可以去查查吧。

     

     

     图片来源:菜鸟教程、《Java开发实战经典》。

     

    展开全文
  • 使用JDBC操作MySql数据库

    千人学习 2017-03-13 16:06:46
    系统的简介了如何使用JDBC来操作MySql数据库,结合使用控制台应用程序来完成一个小型系统。
  • Java中JDBC的使用详解

    万次阅读 多人点赞 2018-07-28 22:31:11
    打个广告,帮朋友卖点东西,东西超便宜的哟【衣服鞋子等】,厂家直接出货,绝对低于市场价!!!一般都比市场价便宜3—7... 新建一个Java工程jdbc,并导入数据驱动。 二、详细步骤 1、加载数据库驱动 //1.加载...

     

    打个广告,帮朋友卖点东西,东西超便宜的哟【衣服鞋子等】,厂家直接出货,绝对低于市场价!!! 一般都比市场价便宜3—7折【都是牌子货】,如果您感兴趣,可以扫描屏幕下方的二维码,感谢关注!!!

    微信

    一、环境介绍

    • 在mysql中创建一个库shen,并创建user表和插入表的数据。
    • 新建一个Java工程jdbc,并导入数据驱动。

     

    二、详细步骤

    1、加载数据库驱动

    //1.加载驱动(开发推荐的方式)
    Class.forName("com.mysql.jdbc.Driver");

    注意:如果连接的是SQL server

    //1.加载驱动
    Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

    2、建立连接

    1、数据库URL

         URL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库,URL的写法为:

     jdbc:mysql:[]//localhost:3306/shen ?参数名:参数值

    常用数据库URL地址的写法:

    Oracle:jdbc:oracle:thin:@localhost:1521:shen

    SqlServer:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=shen

    MySql:jdbc:mysql://localhost:3306/shen

     

    注意:如果是localhost:3306,mysql可以简写为jdbc:mysql:///sid(尽量不这样)

    2、Connection

         Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,创建方法为:

    Connection conn = DriverManager.getConnection(url,user,pass); 

    这个对象的常用方法:

                               方法                                              描述
    createStatement() 创建向数据库发送sql的statement对象。
    prepareStatement(sql) 创建向数据库发送预编译sql的PrepareSatement对象。
    prepareCall(sql) 创建执行存储过程的callableStatement对象。
    setAutoCommit(boolean autoCommit) 设置事务是否自动提交。
    commit() 在链接上提交事务。
    rollback() 在此链接上回滚事务。
    String url = "jdbc:mysql://localhost:3306/shen";
    String username = "shen";
    String password = "Anxin062039";
    Connection conn = null;
    			
    //2.获取与数据库的链接
    conn = DriverManager.getConnection(url, username, password);

     

    3、执行SQL语句

    1、Statement

         Jdbc程序中的Statement对象用于向数据库发送SQL语句,创建方法为:

                     Statement st = conn.createStatement();

     Statement对象常用方法:

                      方法                                     含义
    executeQuery(String sql)  用于向数据发送查询语句。
    executeUpdate(String sql) 用于向数据库发送insert、update或delete语句
    execute(String sql) 用于向数据库发送任意sql语句
    addBatch(String sql) 把多条sql语句放到一个批处理中。
    executeBatch() 向数据库发送一批sql语句执行。
    Statement st = null;
    //3.获取用于向数据库发送sql语句的statement
    st = conn.createStatement();
    //4.向数据库发sql
    String sql = "select id,name,password,email,birthday from users";
    st.executeQuery(sql);

     

    2、PreperedStatement

         PreperedStatement是Statement的孩子,它的实例对象可以通过调用:

                     PreperedStatement st =  conn.preparedStatement()

    PreperedStatement st = null;
    String sql = "select * from users where name=? and password=?";
    
    //3.获取用于向数据库发送sql语句的Preperedstatement
    st = conn.preparedStatement(sql);//在此次传入,进行预编译
    st.setString(1, username);
    st.setString(2, password);
    //4.向数据库发sql
    st.executeQuery();//在这里不需要传入sql

    比较:相对于Statement对象而言

    • PreperedStatement可以避免SQL注入的问题。

            如:String sql="select * from admin where loginname='"+loginName+"' and loginpwd='"+loginPwd+"'";

            在应用中:

                -》请输入账号:

                     333

                -》请输入密码:

                      wer'or'1'='1

     

            实际上发送:select * from admin where loginname='333' and loginpwd='wer'or'1'='1',登录成功!

     

    • Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。
    • 并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。

     

    4、获取结果

         Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式,ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。

    1、获取行

    ResultSet提供了对结果集进行滚动的方法:

    • next():移动到下一行
    • Previous():移动到前一行
    • absolute(int row):移动到指定行
    • beforeFirst():移动resultSet的最前面。
    • afterLast() :移动到resultSet的最后面。

    2、获取值

    ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:

    • 获取任意类型的数据

    getObject(int index)

    getObject(string columnName)

    • 获取指定类型的数据,例如:

    getString(int index)

    getString(String columnName)

     

    附加:

    常用数据类型转换:

    SQL类型 Jdbc对应方法 返回类型
    bit(1),bit(n) getBoolean,getBytes() Boolean,byte[]
    tinyint getByte() Byte
    smallint getShort() Short
    int getInt Int
    bigint getLong() Long
    char,varchar,longvarchar getString String
    text(clob) blob getClob(),getblob() Clob,blob
    date getDate() java.sql.Date
    time getTime() java.sql.Time
    timestamp getTimestamp java.sql.Timestamp
    ResultSet rs = null;
    //4.向数据库发sql,并获取代表结果集的resultset
    String sql = "select id,name,password,email,birthday from users";
    rs = st.executeQuery(sql);
    			
    //5.取出结果集的数据
    rs.afterLast();
    rs.previous();
    System.out.println("id=" + rs.getObject("id"));
    System.out.println("name=" + rs.getObject("name"));
    System.out.println("password=" + rs.getObject("password"));
    System.out.println("email=" + rs.getObject("email"));
    System.out.println("birthday=" + rs.getObject("birthday"));

    或者:

    //循环取出(id)
    while(rs.next())
    {
    	String id=rs.getString(1);//1代表数据库中表的列数,id在第一列也可以("id")!!!
    	System.out.println(id+" ");
    }

    5、释放资源

          Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。

    注意:为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。

    //6.关闭链接,释放资源
    	if(rs!=null){
    		try{
    			rs.close();
    		}catch (Exception e) {
    			e.printStackTrace();
    		}
    		rs = null;
    	
    	}
    	if(st!=null){
    		try{
    			st.close();
    		}catch (Exception e) {
    			e.printStackTrace();
    		}
    				
    	}	
    	if(conn!=null){
    		try{
    			conn.close();
    		}catch (Exception e) {
    			e.printStackTrace();
    		}
    }

    三、基本操作

    1、DDL

    /**
     * 在java中使用ddl语句(credate,drop,backup...)
     */
    package com.shen.study2;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    public class Test1 {
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Test1 test=new Test1();
    	}
    	
    	public Test1()
    	{
    		this.lianjie();
    	}
    	public void lianjie()
    	{
    		//定义需要的对象
    		PreparedStatement ps=null;
    		Connection ct=null;
    		ResultSet rs=null;
    		try {
    			//初始化对象
    			//1.加载驱动
    			Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
    			//2.得到连接(1433表示sql server的默认端口)
    			ct=DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433;databaseName=shen","sa","Anxin062039");
    			//3.创建Preparestatement,创建数据
    			ps=ct.prepareStatement("create database vvv");
    //			ps=ct.prepareStatement("create table xxx");//创建表
    //			ps=ct.prepareStatement("backup database shen to disk='F:/123.bak'");//备份数据库
    			
    			//如果执行的是ddl语句
    			boolean b=ps.execute();
    			if(b)
    			{
    				System.out.println("创建成功!");
    			}else {
    				System.out.println("失败");
    			}
    		} catch (Exception e) {
    			// TODO: handle exception
    		}finally {
    			//关闭资源
    			try {
    				//为了程序健壮
    				if(ps!=null)
    					ps.close();
    				if(ct!=null)
    					ct.close();
    			} catch (Exception e2) {
    				// TODO: handle exception
    			}
    		}
    				
    	}
    }

    2、CRUD

    实例:user

    public class User {
    	private int id;
    	private String name;
    	private String password;
    	private String email;
    	private Date birthday;
            
            //相关的get和set
    }

    连接工具:JdbcUtils

    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Properties;
    
    public class JdbcUtils {
    
    	private static String driver = null;
    	private static String url = null;
    	private static String username = null;
    	private static String password = null;
    	
    	static{
    		try{
    			InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
    			Properties prop = new Properties();
    			prop.load(in);
    			
    			driver = prop.getProperty("driver");
    			url = prop.getProperty("url");
    			username = prop.getProperty("username");
    			password = prop.getProperty("password");
    			
    			Class.forName(driver);
    			
    		}catch (Exception e) {
    			throw new ExceptionInInitializerError(e);
    		}
    	}
    	
    	
    	public static Connection getConnection() throws SQLException{
    		
    		return DriverManager.getConnection(url, username,password);
    	}
    	
    	public static void release(Connection conn,Statement st,ResultSet rs){
    		
    		if(rs!=null){
    			try{
    				rs.close();
    			}catch (Exception e) {
    				e.printStackTrace();
    			}
    			rs = null;
    
    		}
    		if(st!=null){
    			try{
    				st.close();
    			}catch (Exception e) {
    				e.printStackTrace();
    			}
    			
    		}
    		
    		if(conn!=null){
    			try{
    				conn.close();
    			}catch (Exception e) {
    				e.printStackTrace();
    			}
    			
    		}
    		
    	}
    }

    资源文件:db.properties

    #driver=com.mysql.jdbc.Driver
    #url=jdbc:mysql://localhost:3306/shen
    #username=shen
    #password=Anxin062039

    注意:前面添加#,表示注释。如果改成SQL server直接更改这里即可

    功能实现:Demo

    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.Statement;
    
    import org.junit.Test;
    
    import cn.itcast.utils.JdbcUtils;
    
    //使用jdbc对数据库增删改查
    public class Demo {
    
    	@Test
    	public void insert(){
    		Connection conn = null;
    		Statement st = null;
    		ResultSet rs = null;
    		try{
    			conn = JdbcUtils.getConnection();
    			st = conn.createStatement();
    			String sql = "insert into users(id,name,password,email,birthday) values(4,'xxx','123','xx@sina.com',to_date('1980-09-09','YYYY-MM-DD'))";
    			int num = st.executeUpdate(sql);  //update
    			if(num>0){
    				System.out.println("插入成功!!");
    			}
    			
    		}catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    	}
    	
    	@Test
    	public void delete(){
    		Connection conn = null;
    		Statement st = null;
    		ResultSet rs = null;
    		try{
    			conn = JdbcUtils.getConnection();
    			String sql = "delete from users where id=4";
    			st = conn.createStatement();
    			int num = st.executeUpdate(sql);
    			if(num>0){
    				System.out.println("删除成功!!");
    			}
    		}catch (Exception e) {
    			
    			
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    	}
    	
    	@Test
    	public void update(){
    		Connection conn = null;
    		Statement st = null;
    		ResultSet rs = null;
    		try{
    			conn = JdbcUtils.getConnection();
    			String sql = "update users set name='wuwang',email='wuwang@sina.com' where id=3";
    			st = conn.createStatement();
    			int num = st.executeUpdate(sql);
    			if(num>0){
    				System.out.println("更新成功!!");
    			}
    		}catch (Exception e) {
    			
    			
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    	}
    	
    	@Test
    	public void find(){
    		Connection conn = null;
    		Statement st = null;
    		ResultSet rs = null;
    		try{
    			conn = JdbcUtils.getConnection();
    			String sql = "select * from users where id=1";
    			st = conn.createStatement();
    			rs = st.executeQuery(sql);
    			if(rs.next()){
    				System.out.println(rs.getString("name"));
    			}
    		}catch (Exception e) {
    			
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    	}
    	
    }

    四、常见操作

    1、处理大数据

         如下内容都借助CRUD中的内容

    1.存取文本文件(.txt文件)

         clob用于存储大文本(mysql中无clob,存储大文本采用的是Text)

    数据库为:

    	 create table testclob
    	 (
    	 	id int primary key auto_increment,
    	 	resume text
    	 );
    public class Demo1 {
    	@Test
    	public void add() {
    		Connection conn = null;
    		PreparedStatement st = null;
    		ResultSet rs = null;
    		
    		try{
    			conn = JdbcUtils.getConnection();
    			String sql = "insert into testclob(resume) values(?)";
    			st = conn.prepareStatement(sql);
    			
    			//Reader reader = new InputStreamReader(Demo1.class.getClassLoader().getResourceAsStream("1.txt"));
    			String path  = Demo1.class.getClassLoader().getResource("1.txt").getPath();//1.txt文件在src下
    			File file = new File(path);
    			st.setCharacterStream(1, new FileReader(file), (int) file.length());//将该文件添加
    			int num = st.executeUpdate();
    			if(num>0){
    				System.out.println("插入成功!!");
    			}
    		}catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    	}
    	
    	@Test
    	public void read(){
    		Connection conn = null;
    		PreparedStatement st = null;
    		ResultSet rs = null;
    		
    		try{
    			conn = JdbcUtils.getConnection();
    			String sql = "select resume from testclob where id=1";
    			st = conn.prepareStatement(sql);
    			rs = st.executeQuery();
    			if(rs.next()){
    				System.out.println("haha");
    				Reader reader = rs.getCharacterStream("resume");
    				char buffer[] = new char[1024];
    				int len = 0;
    				FileWriter out = new FileWriter("c:\\1.txt");
    				while((len=reader.read(buffer))>0){
    					out.write(buffer, 0, len);
    				}
    				out.close();
    				reader.close();
    			}
    			
    		}catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    	}
    }

    2.存取二进制文件(图片,视频)

    数据库:

    	 create table testblob
    	 (
    	 	id int primary key auto_increment,
    	 	image longblob
    	 );
    public class Demo2 {
    	@Test
    	public void add(){
    		Connection conn = null;
    		PreparedStatement st = null;
    		ResultSet rs = null;
    		
    		try{
    			conn = JdbcUtils.getConnection();
    			String sql = "insert into testblob(image) values(?)";
    			st = conn.prepareStatement(sql);
    			String path = Demo2.class.getClassLoader().getResource("01.jpg").getPath();
    			st.setBinaryStream(1, new FileInputStream(path), (int) new File(path).length());
    			int num = st.executeUpdate();
    			if(num>0){
    				System.out.println("插入成功!!");
    			}
    		}catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    	}
    	
    	@Test
    	public void read(){
    		Connection conn = null;
    		PreparedStatement st = null;
    		ResultSet rs = null;
    		
    		try{
    			conn = JdbcUtils.getConnection();
    			String sql = "select image from testblob where id=?";
    			st = conn.prepareStatement(sql);
    			st.setInt(1, 1);
    			rs = st.executeQuery();
    			if(rs.next()){
    				InputStream in = rs.getBinaryStream("image");
    				int len = 0;
    				byte buffer[] = new byte[1024];
    				
    				FileOutputStream out = new FileOutputStream("c:\\1.jpg");
    				while((len=in.read(buffer))>0){
    					out.write(buffer,0, len);
    				}
    				in.close();
    				out.close();
    			}
    		}catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    	}
    }

    2、批量处理SQL

    数据库:

    	 create table testbatch
    	 (
    	 	id int primary key,
    	 	name varchar2(20)
    	 );

    1.通过Statement

    	@Test
    	public void testbatch1(){
    		
    		Connection conn = null;
    		Statement st = null;
    		ResultSet rs = null;
    		
    		try{
    			conn = JdbcUtils.getConnection();
    			String sql1 = "insert into testbatch(id,name) values(1,'aaa')";
    			String sql2 = "insert into testbatch(id,name) values(2,'bbb')";
    			String sql3 = "delete from testbatch where id=1";
    			
    			st = conn.createStatement();
    			st.addBatch(sql1);
    			st.addBatch(sql2);
    			st.addBatch(sql3);
    			
    			st.executeBatch(); 
    			st.clearBatch();
    		}catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    	}

    2.通过preparedstatement

    	@Test
    	public void testbatch2(){
    		
    		long starttime = System.currentTimeMillis();
    		Connection conn = null;
    		PreparedStatement st = null;
    		ResultSet rs = null;
    		
    		try{
    			conn = JdbcUtils.getConnection();
    			String sql = "insert into testbatch(id,name) values(?,?)";
    			st = conn.prepareStatement(sql);
    			
    			for(int i=1;i<10000008;i++){  //i=1000  2000
    				st.setInt(1, i);
    				st.setString(2, "aa" + i);
    				st.addBatch();
    				
    				if(i%1000==0){
    					st.executeBatch();
    					st.clearBatch();
    				}
    			}
    			st.executeBatch();
    			
    		}catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    		
    		long endtime = System.currentTimeMillis();
    		
    		System.out.println("程序花费时间:" + (endtime-starttime)/1000 + "秒!!");
    	}

    3、获取自动生成的主键

    数据库:

    	 create table test1
    	 (
    	 	id int primary key auto_increment,//id自动生成
    	 	name varchar(20)
    	 );
    public class Demo4 {
    
    	/**
    	 * 获取自动生成的主键
    
    	 */
    	public static void main(String[] args) {
    		
    		Connection conn = null;
    		PreparedStatement st = null;
    		ResultSet rs = null;
    		
    		try{
    			conn = JdbcUtils.getConnection();
    			String sql = "insert into test1(name) values(?)";
    			st = conn.prepareStatement(sql);
    			st.setString(1, "aaa");//在插入name时数据库会自动生成id
    			st.executeUpdate();
    			
    			rs = st.getGeneratedKeys();//获取生成的主键
    			if(rs.next()){
    				System.out.println(rs.getInt(1));
    			}
    		}catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    
    	}
    }

    4、调用存储过程

    public class Demo5 {
    
    	/*
    	 *jdbc调用存储过程 
    	 
     create procedure p_course_insert
    @c_no nvarchar(50),
    @c_name nvarchar(50),
    @t_name nvarchar(50)
    as
    insert into t_course(c_no,c_name,t_name)
    values(@c_no,@c_name,@t_name)
    	 */
    	public static void main(String[] args) {
    		
    		
    		Connection conn = null;
    		CallableStatement cs = null;
    		ResultSet rs = null;
    		
    		try{
    			conn = JdbcUtils.getConnection();
    			cs = conn.prepareCall("{call p_course_inser(?,?,?)}");
    			cs.setString(1, "xxxxx");
    			cs.registerOutParameter(2, Types.VARCHAR);
    			
    			cs.execute();
    			String result = cs.getString(2);
    			System.out.println(result);
    			
    		}catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			JdbcUtils.release(conn, cs, rs);
    		}
    
    	}
    
    }

    5、使用事务

    1.普通事务的操作

    	/**
    	 * 模似转帐
    	  
    create table account(
    	id int primary key auto_increment,
    	name varchar(40),
    	money float
    )character set utf8 collate utf8_general_ci;
    
    insert into account(name,money) values('aaa',1000);
    insert into account(name,money) values('bbb',1000);
    insert into account(name,money) values('ccc',1000);
    	 
    	 */
    	public static void main(String[] args) {
    		
    		Connection conn = null;
    		PreparedStatement st = null;
    		ResultSet rs = null;
    		
    		try{
    			conn = JdbcUtils.getConnection();
    			conn.setAutoCommit(false);   //start transaction,开启事务
    			
    			String sql1 = "update account set money=money-100 where name='aaa'";
    			st = conn.prepareStatement(sql1);
    			st.executeUpdate();
    			
    			
    			String sql2 = "update account set money=money+100 where name='bbb'";
    			st = conn.prepareStatement(sql2);
    			st.executeUpdate();
    			
    			
    			conn.commit();//提交
    			
    			System.out.println("成功!!!");  //log4j
    			
    		}catch (Exception e) {
    			e.printStackTrace();//如果程序出错手动回滚
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    		
    	}

    2.设置事务回滚点

    	public static void main(String[] args) {
    		
    		Connection conn = null;
    		PreparedStatement st = null;
    		ResultSet rs = null;
    		Savepoint sp = null;
    		
    		try{
    			conn = JdbcUtils.getConnection();
    			conn.setAutoCommit(false);   //start transaction
    			
    			String sql1 = "update account set money=money-100 where name='aaa'";
    			st = conn.prepareStatement(sql1);
    			st.executeUpdate();
    			
    			sp = conn.setSavepoint();//在这里设置事务回滚点
    			
    			String sql2 = "update account set money=money+100 where name='bbb'";
    			st = conn.prepareStatement(sql2);
    			st.executeUpdate();
    			
    			int x = 1/0;
    			
    			String sql3 = "update account set money=money+100 where name='ccc'"; 
    			st = conn.prepareStatement(sql3);
    			st.executeUpdate();
    			
    			conn.commit();
    			
    		}catch (Exception e) {
    			try {
    				conn.rollback(sp);//回滚到该事务点,即该点之前的会正常执行(sql1)
    				conn.commit();  //回滚了要记得提交,如果没有提交sql1将会自动回滚
    			} catch (SQLException e1) {
    				// TODO Auto-generated catch block
    				e1.printStackTrace();
    			}
    			e.printStackTrace();
    		}finally{
    			JdbcUtils.release(conn, st, rs);
    		}
    		
    	}

    3.设置事务隔离级别

    conn = JdbcUtils.getConnection();
    conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//避免脏读
    conn.setAutoCommit(false);
    /*
    Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)
    Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读)
    Read committed:可避免脏读情况发生(读已提交)。
    Read uncommitted:最低级别,以上情况均无法保证。(读未提交)
    */

    五、使用数据库连接池

    1、原因

    1.传统连接方法

    缺点:

         用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。

    2.数据库连接池

     

     2、开源连接池 

    1.DBCP 数据库连接池 

    工具类如下:JdbcUtils_DBCP

    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.apache.commons.dbcp.BasicDataSourceFactory;
    
    
    public class JdbcUtils_DBCP {
    	
    	private static DataSource ds = null;
    	static{
    		try{
    			InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
    			Properties prop = new Properties();
    			prop.load(in);
    			
    			BasicDataSourceFactory factory = new BasicDataSourceFactory();
    			
    			ds = factory.createDataSource(prop);
    			System.out.println(ds);
    		}catch (Exception e) {
    			throw new ExceptionInInitializerError(e);
    		}
    	}
    	
    	public static Connection getConnection() throws SQLException{
    		
    		return ds.getConnection();
    	}
    	
    	public static void release(Connection conn,Statement st,ResultSet rs){
    		
    		
    		if(rs!=null){
    			try{
    				rs.close();
    			}catch (Exception e) {
    				e.printStackTrace();
    			}
    			rs = null;
    
    		}
    		if(st!=null){
    			try{
    				st.close();
    			}catch (Exception e) {
    				e.printStackTrace();
    			}
    			
    		}
    		
    		if(conn!=null){
    			try{
    				conn.close();
    			}catch (Exception e) {
    				e.printStackTrace();
    			}
    			
    		}
    	}
    	
    }

    2.C3P0 数据库连接池

    连接工具类:JdbcUtils_C3p0(自己在这里更改)

    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.apache.commons.dbcp.BasicDataSourceFactory;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    
    public class JdbcUtils_C3P0 {
    	
    	private static ComboPooledDataSource ds = null;
    	static{
    		try{
    			ds = new ComboPooledDataSource();
    			ds.setDriverClass("com.mysql.jdbc.Driver");
    			ds.setJdbcUrl("jdbc:mysql://localhost:3306/day16");
    			ds.setUser("root");
    			ds.setPassword("root");
    			
    			ds.setInitialPoolSize(10);//最初连接数
    			ds.setMinPoolSize(5);//最小连接数
    			ds.setMaxPoolSize(20);//最大连接数
    			
    		}catch (Exception e) {
    			throw new ExceptionInInitializerError(e);
    		}
    	}
    	
    	public static Connection getConnection() throws SQLException{
    		
    		return ds.getConnection();
    	}
    	
    	public static void release(Connection conn,Statement st,ResultSet rs){
    		
    		
    		if(rs!=null){
    			try{
    				rs.close();
    			}catch (Exception e) {
    				e.printStackTrace();
    			}
    			rs = null;
    
    		}
    		if(st!=null){
    			try{
    				st.close();
    			}catch (Exception e) {
    				e.printStackTrace();
    			}
    			
    		}
    		
    		if(conn!=null){
    			try{
    				conn.close();
    			}catch (Exception e) {
    				e.printStackTrace();
    			}
    			
    		}
    	}
    	
    }

    也可以将配置信息放在xml文件中(src下):c3p0-config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
    	<default-config>
    		<property name="driverClass">com.mysql.jdbc.Driver</property>
    		<property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property>
    		<property name="user">root</property>
    		<property name="password">root</property>
    	
    		<property name="acquireIncrement">5</property>
    		<property name="initialPoolSize">10</property>
    		<property name="minPoolSize">5</property>
    		<property name="maxPoolSize">20</property>
    	</default-config>
    	
    	<named-config name="mysql">
    		<property name="driverClass">com.mysql.jdbc.Driver</property>
    		<property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property>
    		<property name="user">root</property>
    		<property name="password">root</property>
    	
    		<property name="acquireIncrement">5</property>
    		<property name="initialPoolSize">10</property>
    		<property name="minPoolSize">5</property>
    		<property name="maxPoolSize">20</property>
    	</named-config>
    	
    	
    	<named-config name="oracle">
    		<property name="driverClass">com.mysql.jdbc.Driver</property>
    		<property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property>
    		<property name="user">root</property>
    		<property name="password">root</property>
    	
    		<property name="acquireIncrement">5</property>
    		<property name="initialPoolSize">10</property>
    		<property name="minPoolSize">5</property>
    		<property name="maxPoolSize">20</property>
    	</named-config>
    </c3p0-config>

    这样JdbcUtils_C3p0可以改为:

    			/*
                ds = new ComboPooledDataSource();
    			ds.setDriverClass("com.mysql.jdbc.Driver");
    			ds.setJdbcUrl("jdbc:mysql://localhost:3306/day16");
    			ds.setUser("root");
    			ds.setPassword("root");
    			
    			ds.setInitialPoolSize(10);//最初连接数
    			ds.setMinPoolSize(5);//最小连接数
    			ds.setMaxPoolSize(20);//最大连接数
                */
                 ds = new ComboPooledDataSource(""mysql"");//如果默认()

     


    展开全文
  • eclipse使用JDBC 链接sql SEVER数据库时用到的代码 package sqlsqverceshi; import java.sql.*; public class ceshi { public static void main(String[] args) { PreparedStatement ps = null; Connection ct...
  • 利用 jdbc 操作数据库有一下缺点: 1、数据库链接使用的时候就创建,不使用的时候就释放,造成了数据库的资源浪费,不利于系统的维护 解决方法:使用数据库连接池管理数据库链接 2、将 sql 语句硬编码到 java ...
  • 学习jdbcTemplate连接jdbc遇到的一些问题汇总 问题一:Cannot load driver class: com.mysql.jdbc.Driver 首先在连接数据库时,日志中报错 Cannot load driver class: com.mysql.jdbc.Driver 称无法连接driver,后来...
  • 一、 JDBC 1.1 概念: Java DataBase Connectivity Java 数据库连接, Java语言操作数据库 1.2 JDBC本质: 其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口...
  • 欢迎点击「算法与编程之美」↑关注我们!本文首发于微信公众号:"算法与编程之美",欢迎关注,及时了解更多此系列博客。我们在使用idea编写javaweb时难免会使用到MyS...
  • JDBC与数据库连接池

    万次阅读 2018-10-24 23:58:23
    JDBC简介,driver类型,JDBC连接,使用技巧; 连接,短连接,长连接,连接池; 池化思想; 配置,基本配置,关键配置,性能配置; 连接池工具; druid; HikariCP; flexy-pool;
  • JDBC的概述

    千次阅读 2018-06-15 23:24:06
    --------------------------------------------------JDBC的概述------------------------------------------------------------1 JDBC概述1 什么是JDBC JDBC(JavaDataBase Connectivity)就是Java数据库连接,...
  • Java+MySQL + jdbc +学生信息管理系统源码,适合初学者下载使用,欢迎大家下载,交流!
  • 本文存在视频版本,请知悉 项目简介 ... 这次分享一个学生管理系统,我...本系统基于JSP+Servlet+Jdbc学生信息管理系统。涉及技术少,易于理解,适合JavaWeb初学者学习使用。 难度等级:简单 技术栈 编辑器 Eclips...
  • 一个基于JSP+Servlet+Jdbc学生成绩管理系统。涉及技术少,易于理解,适合JavaWeb初学者学习使用。 难度等级:入门 技术栈 编辑器 Eclipse Version: 2019-12 (4.14.0) 前端技术 基础:html+css+JavaScript 框架:...
  • com.mysql.jdbc.Driver 是 mysql-connector-java 5中的, com.mysql.cj.jdbc.Driver 是 mysql-connector-java 6中的1,JDBC连接Mysql5 ...url=jdbc:mysql://localho
  • 情人节快乐呀,有了对象还是一个人过得情人节,终于跟着视频搞出来了一个像模像样的小系统,撒花 山东的冬天可真冷,家里穷没开地暖,所以打这些字的时候我的手都快冻僵了,所以系统的内容明天写,晚安 转载于:...
  • Java Web学生成绩管理系统(JSP+Servlet+JDBC+Dao)

    万次阅读 多人点赞 2019-01-24 23:08:42
    学完java web后,期末期间用所学知识写了一个简单的学生管理系统,现在有空整理分享下。 注意:本文章仅供参考和学习,源码和数据库设计在文章的底部,点击展开然后往下翻就可以找到,其实数据库就六张表,很简单,...
  • 实现功能: ... 2.管理员用户注册,登录 3.管理员对普通用户的查询,...6.所有用户信息都存储于Oracle数据库 流程图: 部分效果图:  源码githab地址: https://github.com/cainiaolibiao/inspiration01/t...
  • 在使用MySQL驱动进行JDBC时候出现了以下异常 Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. at sun....
  • 具体错误信息 Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet successfully received from the server was 1,548,635,756,564 milliseconds ...
  • JDBC连接ORACLE的三种URL格式

    万次阅读 多人点赞 2016-09-05 19:17:51
    使用jdbc连接oracle时url有三种格式格式一: Oracle JDBC Thin using an SID: jdbc:oracle:thin:@host:port:SID Example: jdbc:oracle:thin:@localhost:1521:orcl 这种格式是最简单也是用得最多的 你的oracle的...
  • JDBC执行过程

    千次阅读 多人点赞 2017-10-16 22:25:58
    JDBC
  • jsp+servlet+jdbc实现新闻管理系统

    千人学习 2017-09-04 10:45:05
    本课程主要采用JSP+Servlet+JDBC进行单个表的数据库常用操作,为了让初学者能够更快的掌握三个技术的整合使用。演示示例中,功能包括分页展示新闻、添加新闻(并实现网页编辑器)、删除新闻、批量删除新闻、批量审核...
  • 处理:提示信息表明数据库驱动com.mysql.jdbc.Driver'已经被弃用了、应当使用新的驱动com.mysql.cj.jdbc.Driver' 所以,按照提示更改jdbc.properties配置 .com.mysql.jdbc.Driver 改为 com.mysql.cj.jdbc.Driver...
  • springboot + mybatis多数据库 + druid连接池配置成功。正常运行后,访问第一个数据库后访问第二个数据库,再... Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure Th...
  • JDBC的 驱动包 ojdbc14.jar 程序文件

    万次下载 热门讨论 2007-07-09 23:02:52
    JDBC的 驱动包 ojdbc14.jar 程序文件 ----oracle jdbc driver for jdk1.5
  • 分库分表适用场景分库分表用于应对当前互联网常见的两个场景——大数据量和高并发。通常分为垂直拆分和水平拆分两种。垂直拆分是根据业务将一个库(表)拆分为多个库(表)。如:将经常和不常访问的字段拆分至不同的...
  • 在上一篇文章介绍了如何使用Sharding-jdbc进行分库+读写分离,这篇文章将讲述如何使用Sharding-jdbc进行分库分表+读写分离。 架构回顾 在数据量不是很多的情况下,我们可以将数据库进行读写分离,以应对高并发的需求...
  • Spring JDBC详解

    万次阅读 多人点赞 2015-02-27 20:41:35
    《Spring JDBC详解》本文旨在讲述Spring JDBC模块的用法。Spring JDBC模块是Spring框架的基础模块之一。作者:chszs,转载需注明。博客主页:http://blog.csdn.net/chszs一、概述在Spring JDBC模块中,所有的类可以...

空空如也

1 2 3 4 5 ... 20
收藏数 917,218
精华内容 366,887
关键字:

jdbc