JDBC学习

JDBC就是用了让JAVA代码能更好的与数据库连接而由sun公司推出的一套java应用程序访问数据库的技术规范。,使用JDBC需要几个步骤,同时对于增删改查也分为两种不同的操作,为了避免设置拼串时可能出现异常,使用preparedStatement进行预处理,为了减少代码量,可以将相同的代码封装到一个工具类内。

一、概述:

JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范

JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

DBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。

二、原理:

Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动。

JDBC是接口,驱动是接口的实现类,没有驱动将无法完成数据库连接,从而不能操作数据库!每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。

三、开发步骤:

​ 1、导入驱动包

​ 新建java项目,在项目中新建libs文件夹并向其中添加mysql驱动包并右键build path

2、注册驱动.

3、获得连接.

4、获得语句执行平台

5、执行sql语句

6、处理结果

7、释放资源.

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

public class Demo01 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.注册驱动(包名+类名)
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接对象(导包都导sql里面的,不导jdbc里的;多态!报异常是因为用户输入的串可能写错)后面设置下数据格式
        String url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8";
        String user="root";
        String password="root";
        Connection conn=DriverManager.getConnection(url,user,password);
        //System.out.println(conn);报地址为正确sql服务关了可能报错
        //3.获取语句执行平台:
        Statement sta=conn.createStatement();
        //4.执行SQL语句:增-----一套语句执行一句sql语句 返回的是一个Int值,是指执行了几行
        String sql="insert into sort(sname) values('小红')";
        int row=sta.executeUpdate(sql);
        System.out.println(row);
        //6.释放资源(先开后关)
        sta.close();
        conn.close();
    }
}

1、导入驱动JAR包:

创建lib目录,用于存放当前项目需要的所有jar包

选择jar包,右键执行build path / Add to Build Path

2、注册驱动:Class.forName(“com.mysql.jdbc.Driver”);

3、获得链接:

jdbc:mysql://localhost:3306/test

JDBC规定url的格式由三部分组成,每个部分中间使用冒号分隔。

第一部分是jdbc,这是固定的;

第二部分是数据库名称;

第三部分是由数据库厂商规定的,我们需要了解每个数据库厂商的要求,mysql的第三部分分别由数据库服务器的IP地址(localhost==127.0.0.1)、端口号(3306),以及数据库名称(test)组成。

4、获得语句执行平台:

常用方法:

① int executeUpdate(String sql); --执行insert 、update、 delete语句.返回执行的行数int值。所有的增删改都执行这个语句

② ResultSet executeQuery(String sql); --执行select语句.返回ResultSet的结果集对象(二维表格)

③ boolean execute(String sql); --执行select返回true 执行其他的语句返回false.(不推荐使用)

5、处理结果集:(执行insert、update、delete无需处理)

ResultSet实际上就是一张二维的表格,我们可以调用其boolean next()方法指向某行记录,当第一次调用next()方法时,便指向第一行记录的位置,这时就可以使用ResultSet提供的getXXX(int col)方法(与索引从0开始不同个,列从1开始)来获取指定列的数据:

rs.next();//指向第一行
rs.getInt(1);//获取第一行第一列的数据
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
public class Demo{
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
                //1.注册驱动(静态方法)(包名+类名)
                Class.forName("com.mysql.jdbc.Driver");
                //2.获取连接对象(导包都导sql里面的,不导jdbc里的;多态!报异常是因为用户输入的串可能写错)后面设置下数据格式
                String url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&ServerTimeZone=utf8";
                String user="root";
                String password="root";
                Connection conn=DriverManager.getConnection(url,user,password);
                //System.out.println(conn);报地址为正确sql服务关了可能报错
                //3.获取语句执行平台:
                Statement sta=conn.createStatement();
                //4.执行sql语句
                String sql="select * from sort";
                ResultSet rs=sta.executeQuery(sql);
                //5.处理结果集(括号里一般是第1列、第2列,但是可以写字段名)
                ArrayList<Sort> arr=new ArrayList<Sort>();
                while(rs.next()){
                    //System.out.println(rs.getInt("sid")+"..."+rs.getString("sname"));
                    Sort sort=new Sort();
                    sort.setSid(rs.getInt("sid"));
                    sort.setSname(rs.getString("sname"));
                    arr.add(sort);
                }
                System.out.println(arr);
                //6.释放资源
                rs.close();
                sta.close();
                conn.close();
    }
}

6、释放资源:

使用后的东西都需要关闭!关闭的顺序是先得到的后关闭,后得到的先关闭。

五、预处理对象:

使用PreparedStatement预处理对象时,建议每条sql语句所有的实际参数,都使用逗号分隔。

String sql = “insert into sort(sid,sname) values(?,?)”;

PreparedStatement预处理对象代码:

PreparedStatement psmt = conn.prepareStatement(sql)

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class Demo02 {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        //1.注册驱动(静态方法)(包名+类名)
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接对象(导包都导sql里面的,不导jdbc里的;多态!报异常是因为用户输入的串可能写错)后面设置下数据格式
        String url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8";
        String user="root";
        String password="root";
        Connection conn=DriverManager.getConnection(url,user,password);
        //System.out.println(conn);报地址为正确sql服务关了可能报错
        //3.获取语句执行平台对象:
        String sql="select count(*) from user where uname=? and pwd=?";
        PreparedStatement pst=conn.prepareStatement(sql);
        //4.执行sql语句
        Scanner sc=new Scanner(System.in);
        System.out.println("请出入用户名:");
        String uname=sc.next();
        System.out.println("请输入密码:");
        String pwd=sc.next();
        //给sql语句的?赋值
        pst.setString(1,uname);
        pst.setString(2, pwd);
        ResultSet rs= pst.executeQuery();//()里不能写sql
        
        //5.处理结果集
        int count=0;
        while(rs.next()){
            count=rs.getInt(1);//因为就一列
            System.out.println(count);    
        }
        //6.释放资源
            rs.close();
            pst.close();
            conn.close();
    }
}

六、JDBC工具类:

“获得数据库连接”操作,将在以后的增删改查所有功能中都存在,可以封装工具类JDBCUtils。提供获取连接对象的方法,从而达到代码的重复利用。

package com.oracle.demo01;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
封装工具类
*/
public class JDBCUtils {
    //获取连接对象的方法(静态的)
    public static  Connection getConnnections(){
        Connection conn=null;
                try {
                    //1.注册驱动(静态方法)(包名+类名)
                    Class.forName("com.mysql.jdbc.Driver");
                    //2.获取连接对象(导包都导sql里面的,不导jdbc里的;多态!报异常是因为用户输入的串可能写错)后面设置下数据格式
                    String url="jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";
                    String user="root";
                    String password="123456";
                    conn=DriverManager.getConnection(url,user,password);
                } catch (ClassNotFoundException | SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return conn;    
    }
    //释放资源
    public static void close(Connection conn,Statement sta){
        if(sta!=null){
            try {
                sta.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    //释放资源2
    public static void close(Connection conn,Statement sta,ResultSet rs){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if(sta!=null){
            try {
                sta.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**

使用工具类
*/
public class Demo05 {

    public static void main(String[] args) throws SQLException {
        add();

    }
    //新增分类Sort
    public static void add() throws SQLException{
        //1.获得连接对象
        Connection conn=JDBCUtils.getConnnections();
        //测试下是地址不System.out.println(conn);
        //2.获取语句执行平台
        String sql="insert into sort (sname) values(?)";
        PreparedStatement pst=conn.prepareStatement(sql);
        //3.执行sql
        pst.setString(1, "打火机");
        int row=pst.executeUpdate();
        System.out.println(row);
        //4.释放资源
        JDBCUtils.close(conn, pst);
    }
}

七、PreparedStatement和Statement的区别 ?

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

使用PreparedStatement(预编译对象)可以用来解决sql注入问题,在执行多次插入数据时,Statement需要编译多次执行多次,而PreparedStatement则需要编译一次执行多次

八、Api接口

DriverManager驱动管理类

​ registDriver(Driver对象):注册驱动,不推荐使用

​ getConnection(url,user,pwd):获取连接

Connection 连接对象接口

​ createStatement():生成命令对象

	     prepareStatement(sql):生成预编译命令对象

Statement命令对象接口

​ executeUpdate(sql):执行增删改语句,返回受影响的行数

​ executeQuery(sql):执行查询语句,返回结果集

​ execute(sql):执行任意sql语句,返回boolean

PreparedStatement预编译命令对象接口

​ executeUpdate():执行增删改语句,返回受影响的行数

​ executeQuery():执行查询语句,返回结果集

​ execute():执行任意sql语句,返回boolean

		setXX(占位符索引,占位符的值):设置对应索引的占位符的值,类型为XX类型

​ setObject(占位符索引,占位符的值):设置对应索引的占位符的值,类型为Object类型

ResultSet结果集对象接口

​ next():下移一行,返回当前行是否有值

​ previous():上移一行,返回当前行是否有值

​ getXX(列索引|列名|别名):返回对应列的值,接收类型为XX

​ getObject(列索引|列名|别名):返回对应列的值,接收类型为Object

九、批处理

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

JDBC的批量处理语句包括下面两个方法:

addBatch():添加需要批量处理的SQL语句或参数

executeBatch():执行批量处理语句;

clearBatch():清空批处理包的语句

通常我们会遇到两种批量执行SQL语句的情况:

①多条SQL语句的批量处理

②一个SQL语句的批量传参

注意:JDBC连接MySQL时,如果要使用批处理功能,请再url中加参数?rewriteBatchedStatements=true

例子:

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

import org.junit.Test;

public class TestBatch {
	/**
	没有使用批处理
	*/
	@Test
	public void noBatch()throws Exception{
		Class.forName("com.mysql.jdbc.Driver");
		
		String url = "jdbc:mysql://localhost:3306/test";
		String user = "root";
		String password = "root";
		Connection conn = DriverManager.getConnection(url, user, password);
		
		
        String sql = "INSERT INTO t_department(dname,description) VALUES(?,?)";
        PreparedStatement st = conn.prepareStatement(sql);
        
        for(int i=0; i<1000; i++){
        	st.setString(1, "测试部门" + i);
        	st.setString(2, "测试部门描述"  + i);
        	
        	st.executeUpdate();
        }
		
		st.close();
		conn.close();
	}
	/**
	使用批处理
	*/
	@Test
	public void useBatch()throws Exception{
		Class.forName("com.mysql.jdbc.Driver");
		
		String url = "jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true";
		String user = "root";
		String password = "root";
		Connection conn = DriverManager.getConnection(url, user, password);
		
		
        String sql = "INSERT INTO t_department(dname,description) VALUES(?,?)";
        PreparedStatement st = conn.prepareStatement(sql);
        
        for(int i=0; i<1000; i++){
        	st.setString(1, "测试部门" + i);
        	st.setString(2, "测试部门描述"  + i);
        	
        	st.addBatch();
        }
        
        st.executeBatch();
		
		st.close();
		conn.close();
	}
}

十、事务

JDBC程序中当一个连接对象被创建时,默认情况下是自动提交事务:每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。

JDBC程序中为了让多个 SQL 语句作为一个事务执行:(重点)

调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务

在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务

在其中某个操作失败或出现异常时,调用 rollback(); 方法回滚事务

若此时 Connection 没有被关闭, 则需要恢复其自动提交状态 setAutoCommit(true);

例子

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

public class TestTransaction {
	public static void main(String[] args){
		Connection conn = null;
		try {
			//1、连接数据库
			Class.forName("com.mysql.jdbc.Driver");

			String url = "jdbc:mysql://localhost:3306/test";
			String user = "root";
			String password = "root";
			conn = DriverManager.getConnection(url, user, password);
			//设置手动提交
			conn.setAutoCommit(false);

			String sql1 = "update t_department set description = ? where did = ?";
			PreparedStatement pst1 = conn.prepareStatement(sql1);
			pst1.setObject(1, "挣大钱的");
			pst1.setObject(2, 4);
			int len1 = pst1.executeUpdate();
			System.out.println(len1>0?"更新部门信息成功":"更新部门信息失败");
			pst1.close();
			
			String sql2 = "update t_employee set salary = salary + ? where did = ?";
			PreparedStatement pst2 = conn.prepareStatement(sql2);
			pst2.setObject(1, 20000);
			pst2.setObject(2, 4);
			int len2 = pst2.executeUpdate();
			System.out.println(len2>0?"更新部门信息成功":"更新部门信息失败");
			pst2.close();
			
			conn.commit();
		}catch (Exception e) {
			try {
				if(conn!=null){
					conn.rollback();
				}
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally{
			try {
				if(conn!=null){
					//恢复自动提交
					conn.setAutoCommit(true);
					//释放连接
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Summer524!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值