JavaWeb之JDBC

JDBC

在这里插入图片描述

概述

全称

( Java DataBase Connectivity ) Java 数据库连接

JDBC 就是使用Java语言操作关系型数据库的一套API

好处

希望程序员只写一套代码就能够操作所有的数据库

JDBC

JDBC 入门

  1. 新建项目
  2. 导入jar
  3. 编写代码
    public static void main(String[] args) throws Exception {


       //1. 注册驱动: 告诉底层用的是mysql
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/数据库名";
        String username = "root";
        String password = "密码";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql = "update 表名 set 修改的数据 where 条件语句";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();

        //5. 执行sql
        int count = stmt.executeUpdate(sql);//受影响的行数
        //6. 处理结果
        System.out.println(count);
        //7. 释放资源
        stmt.close();
        conn.close();
    }

解析

注册驱动

// 虚拟机会加载该类的字节码,从而会执行static 代码块,完成注册驱动
Class.forName("com.mysql.jdbc.Driver"); // 优点: 后续可以改为通过配置文件配置更加灵活
底层
static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }

URL 链接

String url = “jdbc:mysql://127.0.0.1:3306/数据库名”;

  1. 如果链接的是本地的3306 ip 和端口号可以不写
    jdbc:mysql:///数据库名
  2. 本机ip 固定 127.0.0.1 或者 localhost
  3. 端口号 一台电脑端口号有很多 1-65535 都可以用 每个软件启动时会占用一个或多个,请求到该软件占用的端口则请求由这个软件处理

连接对象

两台电脑(服务) 之间想要数据交互必须有一个链接对象Connection

  1. Connection 不负责执行sql , 会创建一个Statement(小弟) 对象,负责sql 的执行

  2. Connection 负责事务

    ​ // 开启事务
    ​ conn.setAutoCommit(false);
    ​ // 提交事务
    ​ conn.commit();
    ​ // 回滚事务
    ​ conn.rollback();

  3. Connection 负责自己的销毁
    conn.close();

Statement 对象

  1. int count = stmt.executeUpdate(sql);//执行完DML语句,受影响的行数
  2. 也可以执行 DDL ,但是不使用
  3. ResultSet resultSet = stmt.executeQuery(sql);

ResultSet

ResultSet 和Java里的set完全没有关系

ResultSet

   //6. 处理结果, 遍历rs中的所有数据
        //  默认 光标指向的是 数据外面, 必须 调用 .next() 方法才能获取数据
        // 6.1 光标向下移动一行,并且判断当前行是否有数据

        while (rs.next()){
            //6.2 获取数据  getXxx()
           // String name1 =rs.getString("uname"); // 如果有别名,必须使用别名
            int id = rs.getInt(1);
            String name = rs.getString(2);
            double money = rs.getDouble(3);
            System.out.println(id);
            System.out.println(name);
            System.out.println(money);
            System.out.println("--------------");
        }
        // 6.1 光标向下移动一行,并且判断当前行是否有数据
        while (rs.next()){
            //6.2 获取数据  getXxx()
            int id = rs.getInt("id"); // 如果有别名,应该使用别名
            String name = rs.getString("name");
            double money = rs.getDouble("money");
            System.out.println(id);
            System.out.println(name);
            System.out.println(money);
            System.out.println("--------------");

        }
  1. java 分包开发 ,一般会把同一类对象放在一个统一的包中,方便后续的维护
  2. java 实体类命名一般和数据库保持一直(不完全一样)
  3. Java 实体类 属性名 和数据库保持一直(不完全一样) 保持驼峰式命名习惯
  4. Date 类型: jdbc 返回的是 java.sql.Date
    // java.sql.Date
    Date birthday = rs.getDate(“birthday”);

字符串转义符

   // 字符串转义符
String sql2 = "     select  *from tb_user  where username =\"zhangsan\" and password =\"123\"        ";

String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";

sql 注入及PreparedStatement

原因

​ 字符串拼接导致拼出来的sql 和预期不一致
select * from tb_user where username = ‘X’ and password = ‘X’
黑客输入的字符串 : ’ or ‘1’='1
select * from tb_user where username = ‘X’ and password = ‘’ or ‘1’=‘1’

解决方案
// 接收用户输入用户名和密码
        String name = "zhangsan";
        String pwd = "' or '1' = '1";
        // 定义sql
        String sql = "select * from tb_user where username = ? and password = ?";
        // 获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);
// 设置?的值
    	pstmt.setString(1,name);
    	pstmt.setString(2,pwd);

// 执行sql
		ResultSet rs = pstmt.executeQuery();

PreparedStatement 原理及优势

原理

对传入的参数 中的特殊字符 进行转移处理

优点
  1. 解决了sql 注入问题
  2. 提升了sql 效率
    jdbc:mysql:///数据库名?useSSL=false&useServerPrepStmts=true
  • select * from tb_user where username = 'zhangsan' and password = '123'
    
    /*
     * 0)解析前判断有没有解析过
     * 1)解析 : 查询那个表,where 后有哪些条件等
     * 2)会把解析的结果缓存
     * 3)执行返回
     * 4) 如果有相同的sql  执行
     * */
    
    
    
    select * from tb_user where username = ? and password = ?
    
    /*
     * 0)解析前判断有没有解析过
     * 1)解析 : 查询那个表,where 后有哪些条件等
     * 2)会把解析的结果缓存
     * 3) 执行(传递参数)返回
     * 4) 如果有相同的sql  执行
     * */
    

    数据库连接池

数据库访问 执行sql 影响效率的步骤是 创建链接 及关闭链接,可以使用连接池的思想解决问题

数据库连接池

Driud使用

        static DataSource dataSource=null;
        static {
            Properties prop =new Properties();
            try {
                prop.load(new FileInputStream("src/druid.properties"));
                dataSource = DruidDataSourceFactory.createDataSource(prop);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    public static void main(String[] args) {
        try {
            DButil();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void DButil() throws  Exception {
        //1. 注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false";
        String username = "root";
        String password = "密码";
        Connection conn=DriverManager.getConnection(url,username,password);
        //3. 定义sql
        String sql="select * from stu";
         //4. 获取执行sql的对象 Statement
        Statement statement = conn.createStatement();
        //5. 执行sql
        ResultSet resultSet = statement.executeQuery(sql);
        //6.遍历获取的数据
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            int age = resultSet.getInt("age");
            String sex = resultSet.getString("sex");
            System.out.println(id+" "+name+" "+age+" "+sex);
        }
         //7. 释放资源
        statement.close();
        conn.close();
    }

三层架构开发思想

  1. web
  2. service
  3. dao

三层架构开发思想

JDBC缺点

  1. 占位符赋值繁琐
  2. 代码繁琐(重复多)
  3. 查询结果集返回封装繁琐

动态代理

动态代理

public class BrandService {

    private BrandDao dao = new BrandDaoImpl();

    /**
     *          Proxy jdk 内置的对象, 主要是用来增强对象的(创建代理对象)
     *                      1) ClassLoader : 增强那个对象,使用那个对象的类加载器
     *                      2) Class<?>[] 数组 : 增强那个对象就传递那个对象的接口(要求必须有接口)
     *                      3) 是一个匿名内部类对象 InvocationHandler,在 invoke 方法中可以写增强逻辑
     */
    private BrandDao dao_plus = (BrandDao)Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(),
            new InvocationHandler() {
                /*
                 obj : 最终生成对象的引用,没用
                * method  调用那个方法 就是对应的方法名对象
                * args  方法参数
                * */
                @Override
                public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
//                    // 增强逻辑
//                    String methodName = method.getName();
//                    if("findAll".equals(methodName)){
//                        long start =System.currentTimeMillis();
//                         int num = dao.findAll();
//                        long end =System.currentTimeMillis();
//                         System.out.println("BrandDaoImpl_findAll"+new Date()+":"+(end-start));
//                         return  num;
//                    }
//                    if("insert".equals(methodName)){
//                        long start =System.currentTimeMillis();
//                        dao.insert();
//                        long end =System.currentTimeMillis();
//                        System.out.println("BrandDaoImpl_insert"+new Date()+":"+(end-start));
//                        return null;
//                    }
                    long start =System.currentTimeMillis();
                     Object result  = method.invoke(dao,args); // 反射调用更加通用
                    long end =System.currentTimeMillis();
                   System.out.println(method.getDeclaringClass().getName()+method.getName()+new Date()+":"+(end-start));
                    return result;
                }
            });

    public int  findAll(){
        return dao_plus.findAll();
    }
    
    public void  insert(){
        dao_plus.insert();
    }
}

JDBC常见错误

Unknown database 'db4-jdbc

库名写错了

Unknown database 'db4-jdbc

Access denied for user ‘root’@‘localhost’

密码错误

 Access denied for user 'root'@'localhost'

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

java白杨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值