JDBC总结

1.JDBC

1.1概念

我们学习了数据库,数据库实现了数据的持久化,但我们最终要在程序里处理数据啊,那java代码中怎么去访问数据库读写数据呢?

这就要用到sun公司设定的一套数据库标准了,这套标准就是JDBC(Java Database Connectivity)。但它只是规范,不做具体实现。于是数据库厂商又根据JDBC标准,实现自家的驱动Driver。如:mysql驱动com.mysql.cj.jdbc.Driver,Oracle的驱动oracle.jdbc.OracleDriver。有了这套解决方案,java就可以访问数据库中的数据了。

public interface Connection extends Wrapper, AutoCloseable {}

public interface Statement extends Wrapper, AutoCloseable {}

public interface PreparedStatement extends Statement {}

public interface CallableStatement extends PreparedStatement {}

public interface ResultSet extends Wrapper, AutoCloseable {}

Java中提倡面向接口开发,而最经典的接口设计莫过于JDBC数据库接口。

Connection链接、Statement语句、PreparedStatement预处理语句、CallableStatement存储过程、ResultSet结果集。

调用方式有三种:Statement语句、PreparedStatement预处理语句、CallableStatement存储过程,推荐使用第二种PreparedStatement,防止SQL注入,其也是预编译性能高。
在这里插入图片描述

1.2使用步骤

导入jar包(丰富的工具类)

获取和数据库的连接(用户名、密码)

通过程序执行SQL

通过程序处理结果

1.3idea 创建项目并导入jar包

创建stage2 Java工程
创建lib目录,拷贝驱动objbc6-11.1.0.7.0到lib目录下
项目引用这个外部jar包

1.4入门案例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
入门案例

package cn.tedu.jdbc;

import java.sql.*;

//测试 jdbc
//需求:查询cgb2104库里的students表里的所有数据
public class Test1 {
    public static void main(String[] args) throws Exception {
        //1,注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2,获取和数据库的连接
//String url= "jdbc:mysql://localhost:3306/cgb2104?characterEncoding=utf8";//指定要连接哪个数据库
String url= "jdbc:mysql:///cgb2104?characterEncoding=utf8";//指定要连接哪个数据库
        String user= "root" ; //使用的用户名
        String pwd= "root" ; //使用的密码
        Connection conn = DriverManager.getConnection(url, user, pwd);
        //3,获取传输器,执行SQL
        Statement st = conn.createStatement();
        //4,执行SQL
        ResultSet rs = st.executeQuery("select * from students");
        //5,解析结果集
        while( rs.next() ){//next()判断结果集中是否有数据
            for (int i = 1; i <= 5 ; i++) {
                //获取每列的值并打印
                System.out.println( rs.getString(i) );
            }
        }
        //6,释放资源
        rs.close(); //关闭结果集
        st.close();//关闭传输器
        conn.close();//关闭连接
    }
}


1.5SQL注入

/*自己准备user2表(id/name/password),准备数据
    CREATE TABLE `user2` (
          `id` int(11)  PRIMARY KEY  auto_increment,
          `name` varchar(10) default NULL,
          `password` varchar(10) default NULL
    ) ;
 */
//需求:利用jdbc,根据用户名和密码查询cgb2104库里的user表
//SQL注入攻击问题
private static void login() {
    try{
        Class.forName("com.mysql.jdbc.Driver");
        String url="jdbc:mysql:///cgb2104?characterEncoding=utf8";
        Connection conn = DriverManager.getConnection(url, "root", "root");
        Statement st = conn.createStatement();
// String sql ="select * from user2 where name='jack' and password='123456'";//写死了

        String user = new Scanner(System.in).nextLine();//用户输入jack'#
        String pwd = new Scanner(System.in).nextLine();
        //SQL注入攻击问题:本质上是因为SQL语句中出现了特殊符号#,改变了SQL语义
String sql ="select * from user2 where name='"+user+"' and password='"+pwd+"'";
        ResultSet rs = st.executeQuery(sql);//执行查询的SQL,返回结果集
        if(rs.next()){
            System.out.println("登录成功~");
        }else{
            System.out.println("登录失败~");
        }
        st.close();
        conn.close();
    }catch(Exception e){
        e.printStackTrace();//有异常,直接打印异常信息
        //System.out.println("执行失败。。。");//上线
    }

}


1.6SQL注入的解决方案

//解决SQL注入攻击的方案
private static void login2() {
    try{
        Class.forName("com.mysql.jdbc.Driver");
        String url="jdbc:mysql:///cgb2104?characterEncoding=utf8";
        Connection conn = DriverManager.getConnection(url, "root", "root");
//            Statement st = conn.createStatement();不行,不安全,会被SQL攻击

        String user = new Scanner(System.in).nextLine();//用户输入jack'#
        String pwd = new Scanner(System.in).nextLine();
        //?叫占位符 ,SQL的骨架
String sql ="select * from user2 where name=? and password=?";
        //先把SQL骨架发给数据库执行
        PreparedStatement ps = conn.prepareStatement(sql);
        //给SQL里的? 设置参数
        ps.setString(1,user);//给第一个?设置值是user
        ps.setString(2,pwd);//给第二个?设置值是pwd
        
        ResultSet rs = ps.executeQuery();//执行拼接好的SQL,返回结果集

        if(rs.next()){
            System.out.println("登录成功~");
        }else{
            System.out.println("登录失败~");
        }
        ps.close();
        conn.close();
    }catch(Exception e){
        e.printStackTrace();//有异常,直接打印异常信息
        //System.out.println("执行失败。。。");//上线
    }
}


1.7重复补充:

1.7.1创建工具类

package cn.tedu.jdbc;

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

//提供丰富的方法,方便的jdbc操作
public class JDBCUtils {
    //1,获取数据库的连接(注册驱动+获取连接)
    /**
     * 获取数据库的连接
     * @return 数据库的连接对象Connection
     * @throws Exception
     */
    static public Connection getConnection() throws Exception{
        //1,注册驱动
        Class.forName("com.mysql.jdbc.Driver");//全路径
        //2,获取数据库的连接(用户名/密码)
        //jdbc连接mysql数据库的协议//本机:端口号/数据库的名字   解决中文乱码             指定时区                     关闭权限检验
        String url="jdbc:mysql://localhost:3306/cgb2108?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false" ;
        Connection c = DriverManager.getConnection(
                url,"root","root");
        return c ;//返回给调用者
    }

}



1.7.2模拟用户登录

package cn.tedu.jdbc;

import java.sql.*;
import java.util.Scanner;

//需求:利用JDBC,查询tb_user表里的数据
/* 1,创建表,并插入数据 2,利用JDBC,查询数据
CREATE TABLE tb_user(
   id int PRIMARY KEY auto_increment,
   name varchar(20) default NULL,
   password varchar(20) default NULL
)
insert into tb_user values(null,'jack','321')
 */
public class Test2 {
    public static void main(String[] args) throws Exception {
//        method();//查询tb_user表里的数据
//        method2();//模拟用户登录
        method3();//解决SQL攻击问题
    }
    //解决SQL攻击问题
    private static void method3() throws Exception {
        //1,注册驱动 2,获取连接
        Connection c = JDBCUtils.getConnection();
        //3,执行SQL
        String a = new Scanner(System.in).nextLine();//用户名
        String b = new Scanner(System.in).nextLine();//密码
        //如果动态的拼接字符串时,数据在中间的位置  "+a+"
//        String sql="select * from tb_user where name='jack' and password='321'" ;
//        String sql="select * from tb_user where name='"+a+"' and password='"+b+"'" ;
        //SQL骨架:用?代替了参数的位置,?叫占位符,好处:简洁(避免了SQL拼接参数)
        String sql="select * from tb_user where name=? and password=?" ;
        //4,获取传输器
//        Statement s = c.createStatement();
        PreparedStatement s = c.prepareStatement(sql);
        //设置SQL参数--setXxx()设置不同类型的参数
        s.setString(1,a);//?的索引,要给?设置的值
        s.setString(2,b);//?的索引,要给?设置的值
        //TODO 当用户名输入jack'#时还会发生SQL攻击吗???
        ResultSet r = s.executeQuery();
        //5,解析结果集
        if(r.next()){//查到数据了吗?查到了就登录成功
            System.out.println("登录成功~");
        }else{
            System.out.println("用户名或者密码输入错误,登录失败~");
        }
        //6,关闭资源
        r.close();
        s.close();
        c.close();
    }

    //查询tb_user表里的数据
    private static void method() throws Exception{
        //调用工具类的方法
        Connection c = JDBCUtils.getConnection();
        //3,获取传输器
        Statement s = c.createStatement();
        //4,执行SQL
        ResultSet r = s.executeQuery("select * from tb_user");
        //5,解析结果集
        while(r.next()){//判断r有数据
            //获取r的数据
            int a = r.getInt("id");//获取表里的id字段的值
            String b = r.getString("name");//获取表里的name字段的值
            String c1 = r.getString("password");//获取表里的password字段的值
            System.out.println(a+b+c1);
        }
        //6,释放资源
        r.close();//释放结果集
        s.close();//释放传输器
        c.close();//释放连接器
    }
    /* 模拟用户登录
1,发起SQL:select * from tb_user where name='jack' and password='321'
2,判断result,如果有结果就登录成功,没结果就登录失败

问题: SQL攻击/SQL注入,
本质上就是因为SQL语句中出现了特殊符号(#,注释掉了一些条件),导致了SQL语义改变了
解决方案:Statement低级的传输器,不安全,低效
      换成PreparedStatement高级,安全
    */
    private static void method2() throws Exception {
        //1,注册驱动 2,获取连接
        Connection c = JDBCUtils.getConnection();
        //3,获取传输器
        Statement s = c.createStatement();
        //4,执行SQL
        String a = new Scanner(System.in).nextLine();//用户名
        String b = new Scanner(System.in).nextLine();//密码
        //如果动态的拼接字符串时,数据在中间的位置  "+a+"
//        String sql="select * from tb_user where name='jack' and password='321'" ;
String sql="select * from tb_user where name='"+a+"' and password='"+b+"'" ;
        ResultSet r = s.executeQuery(sql);
        //5,解析结果集
        if(r.next()){//查到数据了吗?查到了就登录成功
            System.out.println("登录成功~");
        }else{
            System.out.println("用户名或者密码输入错误,登录失败~");
        }
        //6,关闭资源
        r.close();
        s.close();
        c.close();
    }
}


1.7.3JDBC的练习

package cn.tedu.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

//JDBC的练习
public class Test3 {
    public static void main(String[] args) throws Exception{
//        method();//查询部门表的<100数据
        method2();//向dept表里插入数据
    }
    //向dept表里插入数据
    private static void method2() throws Exception {
        Connection c = JDBCUtils.getConnection();
        //插入数据时怎么决定要几个问号? 要看表里有几个字段需要设置值
        String sql = "insert into dept values(?,?,?)" ;
        PreparedStatement p = c.prepareStatement(sql);
        //设置SQL的参数
        p.setObject(1,666);
        p.setObject(2,"软件测试部");
        p.setObject(3,"大山西");
        //执行SQL
        p.executeUpdate();//执行增删改的SQL
        //TODO 会返回结果集吗?返回了的是啥?
    }
    //查询部门表的<100数据
    private static void method() throws Exception{
        Connection c = JDBCUtils.getConnection();//利用工具类,获取数据库的连接
        //获取传输器,执行SQL骨架
        String sql = "select * from dept where deptno < ?";
        PreparedStatement s = c.prepareStatement(sql);
        //设置SQL的参数
        s.setInt(1,100);//给第一个?设置100
        ResultSet r = s.executeQuery();//执行查询的SQL语句
        //处理结果集
        while(r.next()){//next()判断有数据吗
            //获取数据getXxx()--获取表里的dname字段的值,并打印
            String str = r.getString("dname");
            System.out.println(str);
        }
        //关闭资源
        r.close();
        s.close();
        c.close();
    }
}


1.7.4JDBC的总结

1, 什么是JDBC? java程序连接数据库的标准方案,全称是java database connectivity
2, 使用JDBC步骤? 导入jar包,注册驱动,获取数据库的连接,获取传输器,执行SQL,解析结果集(查询),关闭资源
3, 传输器Statement和PreparedStatement有什么区别? Statement不安全(可能发生SQL攻击),而且低效
4, Statement和PreparedStatement有什么关系? public interface PreparedStatement extends Statement ,是父子接口
5, SQL攻击? 原因是:SQL中出现了特殊符号#(注释符号)改变了SQL的语义 解决方案:使用新的传输器PreparedStatement
6, 执行SQL: 先执行SQL骨架,然后再给SQL设置参数
executeUpdate(): 用来执行增删改的SQL语句,并且返回了影响行数
executeQuery(): 用来执行查的SQL语句,并且返回了结果集ResultSet

1.7.5修改释放资源的代码

package cn.tedu.jdbc;

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

//JDBC的练习
public class Test3 {
    public static void main(String[] args) throws Exception{
        method();//查询部门表的<100数据
//        method2();//向dept表里插入数据
    }
    //向dept表里插入数据
    //为了资源一定会被释放?
    // 把释放资源的代码放入finally里+扩大变量的作用范围
    // +在try里修改变量的默认值null+在finally里进行try catch
    private static void method2(){
        //扩大变量的作用范围?因为想让finally也使用
        Connection c = null ;
        PreparedStatement p = null;
        try{
            c = JDBCUtils.getConnection();
            //插入数据时怎么决定要几个问号? 要看表里有几个字段需要设置值
            String sql = "insert into dept values(?,?,?)" ;
            p = c.prepareStatement(sql);
            //设置SQL的参数
            p.setObject(1,666);
            p.setObject(2,"软件测试部");
            p.setObject(3,"大山西");
            //执行SQL
            int rows = p.executeUpdate();//执行增删改的SQL
            //TODO 会返回结果集吗?返回了的是啥?
            System.out.println("影响的行数是: "+rows);
        }catch (Exception e){
            System.out.println("出错啦~");
        }finally {//资源的释放是一定要执行的
            //关闭资源
            try{
                p.close();
            }catch (Exception e){
                e.printStackTrace();
            }
            try {
                c.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    //查询部门表的<100数据
    private static void method() {
        Connection c =null;
        PreparedStatement s =null;
        ResultSet r =null;
        try{
            c = JDBCUtils.getConnection();//利用工具类,获取数据库的连接
            //获取传输器,执行SQL骨架
            String sql = "select * from dept where deptno < ?";
             s = c.prepareStatement(sql);
            //设置SQL的参数
            s.setInt(1,100);//给第一个?设置100
             r = s.executeQuery();//执行查询的SQL语句
            //处理结果集
            while(r.next()){//next()判断有数据吗
                //获取数据getXxx()--获取表里的dname字段的值,并打印
                String str = r.getString("dname");
                System.out.println(str);
            }
        }catch (Exception e){
           //项目上线阶段,给出的解决方案,比如输出
            System.out.println("数据库连接出错~~");
           //项目开发调试阶段,给出的解决方案,根据报错信息
            e.printStackTrace();
        }finally {
            //关闭资源
            try {
                r.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                s.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            try {
                c.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}


1.7.6改造JDBC释放资源

package cn.tedu.jdbc;

import java.sql.*;

//提供丰富的方法,方便的jdbc操作
public class JDBCUtils {
    //1,获取数据库的连接(注册驱动+获取连接)
    /**
     * 获取数据库的连接
     * @return 数据库的连接对象Connection
     * @throws Exception
     */
    static public Connection getConnection() throws Exception{
        //1,注册驱动
        Class.forName("com.mysql.jdbc.Driver");//全路径
        //2,获取数据库的连接(用户名/密码)
        //jdbc连接mysql数据库的协议//本机:端口号/数据库的名字   解决中文乱码             指定时区                     关闭权限检验
        String url="jdbc:mysql://localhost:3306/cgb2108?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false" ;
        Connection c = DriverManager.getConnection(
                url,"root","root");
        return c ;//返回给调用者
    }
    /**
     * 释放资源,提取了长长的代码
     * @param r 结果集资源
     * @param s 传输器资源
     * @param c 连接资源
     */
    static public void close(ResultSet r, PreparedStatement s,Connection c){
        if(r != null){ //避免了空指针异常
            try {
                r.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(s != null) {
            try {
                s.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(c != null) {
            try {
                c.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

}


1.7.7修改测试类

package cn.tedu.jdbc;

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

//JDBC的练习
public class Test3 {
    public static void main(String[] args) throws Exception{
        method();//查询部门表的<100数据
//        method2();//向dept表里插入数据
    }
    //向dept表里插入数据
    //为了资源一定会被释放?
    // 把释放资源的代码放入finally里+扩大变量的作用范围
    // +在try里修改变量的默认值null+在finally里进行try catch
    private static void method2(){
        //扩大变量的作用范围?因为想让finally也使用
        Connection c = null ;
        PreparedStatement p = null;
        try{
            c = JDBCUtils.getConnection();
            //插入数据时怎么决定要几个问号? 要看表里有几个字段需要设置值
            String sql = "insert into dept values(?,?,?)" ;
            p = c.prepareStatement(sql);
            //设置SQL的参数
            p.setObject(1,666);
            p.setObject(2,"软件测试部");
            p.setObject(3,"大山西");
            //执行SQL
            int rows = p.executeUpdate();//执行增删改的SQL
            //TODO 会返回结果集吗?返回了的是啥?
            System.out.println("影响的行数是: "+rows);
        }catch (Exception e){
            System.out.println("出错啦~");
        }finally {//资源的释放是一定要执行的
            //调用工具类里的close(),增删改没有结果集,就不关闭结果集了,传入null就行了
            JDBCUtils.close(null,p,c);
        }
    }
    //查询部门表的<100数据
    private static void method() {
        Connection c =null;
        PreparedStatement s =null;
        ResultSet r =null;
        try{
            c = JDBCUtils.getConnection();//利用工具类,获取数据库的连接
            //获取传输器,执行SQL骨架
            String sql = "select * from dept where deptno < ?";
             s = c.prepareStatement(sql);
            //设置SQL的参数
            s.setInt(1,100);//给第一个?设置100
             r = s.executeQuery();//执行查询的SQL语句
            //处理结果集
            while(r.next()){//next()判断有数据吗
                //获取数据getXxx()--获取表里的dname字段的值,并打印
                String str = r.getString("dname");
                System.out.println(str);
            }
        }catch (Exception e){
           //项目上线阶段,给出的解决方案,比如输出
            System.out.println("数据库连接出错~~");
           //项目开发调试阶段,给出的解决方案,根据报错信息
            e.printStackTrace();
        }finally {//关闭资源
            JDBCUtils.close(r,s,c);//调用工具类里的close()
        }
    }
}


2.JDBC常见问题

2.1Class.forName这句话有用没?

Class.forName可以指定class类路径进行动态创建对象实例,可JDBC这句话没有返回对象啊,那写这句有什么作用呢?看看java.sql.Driver.class的源码就找到真相了,原来它用了静态代码块创建对象。

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


写了创建了,那不写呢?怎么不写也能执行呢?

Java提供了SPI机制,用户可以自行配置类,JDBC高版本驱动就都引入了这个支持。如果用户使用了Class.forName方式就自己指定了驱动,如果未写这句话,则Java自动去META-INF/services/java.sql.Driver文件中找启动类。
在这里插入图片描述

2.2驱动版本

不同版本的mysql需要不同版本的驱动

Mysql5.0x mysql-connector-java-5.1.32.jar

Mysql8.0x mysql-connector-java-8.0.21.jar

Driver变成了: com.mysql.cj.jdbc.Driver,中间多了cj
url必须加时区参数: serverTimezone=Asia/Shanghai

2.3中文乱码

url增加参数:characterEncoding=utf8防止中文乱码

String url ="jdbc:mysql://localhost:3306/mydb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";

2.4SQL注入

String condition = "陈强";
String condition = "陈强' or 1=1 or '";
String condition = "陈强' or true or '";

String sql = "select * from teachers where tname='" + condition+"'";


利用sql中’单撇是字符串的结束符,or只要一个条件成立其它就不用再判断,而恶意造成sql查询失效,本应该只展示一条数据,结果全部展现。
注入后形成的SQL:

SELECT * FROM teachers WHERE tname='陈强' OR 1=1 OR ''

试想如果是一个财务表,本你只能看自己的信息,结果你看了所有人的信息。

2.5PreparedStatement 语句

SQL注入解决方案:
Statement对象换为PreparedStatement对象

sql = "select * from teachers where tname=?";			#参数使用问号
PreparedStatement stat = cn.prepareStatement(sql); 		#对象换掉
stat.setString(1, condition);					#对应参数类型,第几个问号
ResultSet rs = stat.executeQuery();			#去掉sql参数


PS后的结果:

SELECT * FROM teachers WHERE tname='陈强\' or 1=1 or \''

利用转义字符,屏蔽了SQL中的恶意字符。不仅解决了sql注入问题,使系统变的安全,PreparedStatement还有个极大的好处,它是预编译的语句,其主干部分mysql进行预编译后缓存,下次这部分就无需在解析,只把条件拼入,这样执行效率远高于statement每次都要编译sql语句。

3.常见错误

3.1java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

错误原因
1)jar没有导入,没有builder path

2)Class.forName(“com.mysql.jdbc.Driver”); 字符串拼写错误

3.2Unknown database mydb;

错误原因:
数据库名称拼写错误

3.3Access denied for user ‘root123’@‘localhost’ (using password: YES)

错误原因:
数据库用户名或者密码错误

3.4Table ‘py-school-db.mydb’ doesn’t exist

错误原因:

表不存在,也可能表名写错了

笔记补充:

1、在配置jdbc的jar包环境时需要注意jar包的工具类版本与安装的数据库版本一致
2、在获取数据库的连接时,localhost代表本地的意思,到时候去公司里面得写人家数据库得地址
3、在jdbc中如果前两步骤需要多次调用,所以可以单独创建(封装一个工具类,但是这个工具类的方法要为public)一个工具类,并把这个工具类得方法设置为static,在创建对象得时候只使用一次资源(省内存,省创建的时间),且可以直接通过方法名进行调用
4、底层调用的是注释,大部分是文档注释
5、如果自己提供工具类的话最好说明这个工具类需要哪些参数,返回值,作用等
6、拼接字符串:如果动态的拼接字符串时,数据在中间的位置 “+a+” 第一个双引号与前面的对应,第二个双引号与后面的对应 旧的传输器使用
7、问题: SQL攻击/SQL注入,本质上就是因为SQL语句中出现了特殊符号(#,注释掉了一些条件),导致了SQL语义改变了
解决方案:Statement低级的传输器,不安全,低效,换成PreparedStatement高级,安全
8、项目上线阶段,给出的解决方案,比如输出System.out.println(“数据库连接出错~~”);
9、项目开发调试阶段,给出的解决方案,根据报错信息e.printStackTrace();
10、SQL骨架:用?代替了参数的位置,?叫占位符,好处:简洁(避免了SQL拼接参数)
11、 s.setString(1,a);//?的索引,要给?设置的值
12、采用新的传输器了,后面execunteQuery就不用传参数了
14、setObject体现的时多态,通用性更强,功能更强(啥类型都可以)
15、增删改返回的是影响的行数,看业务需要,有处理需求才返回解析
16、插入数据时怎么决定要几个问号? 要看表里有几个字段需要设置值
17、获取数据getXxx()–获取表里的dname字段的值,并打印
18、什么是JDBC? java程序连接数据库的标准方案,全称是java database connectivity
19、使用JDBC步骤? 导入jar包,注册驱动,获取数据库的连接,获取传输器,执行SQL,解析结果集(查询),关闭资源
20、传输器Statement和PreparedStatement有什么区别? Statement不安全(可能发生SQL攻击),而且低效
21、Statement和PreparedStatement有什么关系? public interface PreparedStatement extends Statement ,是父子接口
22、SQL攻击? 原因是:SQL中出现了特殊符号#(注释符号)改变了SQL的语义 解决方案:使用新的传输器PreparedStatement
23、 执行SQL: 先执行SQL骨架,然后再给SQL设置参数
24、executeUpdate(): 用来执行增删改的SQL语句,并且返回了影响行数
25、executeQuery(): 用来执行查的SQL语句,并且返回了结果集ResultSet
26、向dept表里插入数据
//为了资源一定会被释放?
// 把释放资源的代码放入finally里+扩大变量的作用范围
// +在try里修改变量的默认值null+在finally里进行try catch
27、 会返回结果集吗?返回了的是啥?

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值