JDBC总结

  1. 概念
    • Java database Connectivity Java数据库连接,即通过Java访问数据库。
    • 本质:官方定义的接口,有各个数据库厂商实现这个接口,提供数据库驱动jar包。我们使用这套接口编程。
  2. 使用:
    1导入驱动jar包 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
    1. 注册驱动
      * Calss.forname(“com.mysql.jdbc.Driver”);
      • 理解:实际上就是告知程序该使用哪个驱动jar包。Class.forname实际上是利用反射,将该类加载到内存中,加载的时候会执行其中的静态代码块,完成初始化的相关工作。
         static {
                try {
                    java.sql.DriverManager.registerDriver(new Driver());
                } catch (SQLException E) {
                    throw new RuntimeException("Can't register driver!");
                }
        }
        
    2. 获取数据库连接对象
      * Connection conn = DriverMannager.getConnection(url, user, paaword) ;
      • 理解:利用DiverManager中的getConnection(String url, String user, String password)方法,尝试建立与给定数据库URL的连接。 DriverManager尝试从一组已注册的JDBC驱动程序中选择适当的驱动程序。
    3. 获取执行sql对象
      * Statement stmt = conn.createStatement();
      • 理解: 调用数据库连接对象的createStatement()方法获取执行sql语句的对象
    4. 执行sql语句
      * stmt.excuteUpdate(sql); //用来执行增删改语句
      * stmt.excuteQuery(sql); //用来执行查询语句
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/**
 *设计一个方法
 *public static void execute(String sql)
 *方法接受的参数是SQL语句,无论是增加,删除,还是修改,都调用这个方法,每次传不同的SQL语句作为参数
 */

public class Exercise_01 {

    public static void main(String[] args) {
        //定义sql语句
        //增加
        String sql = "insert into account values(null,'路飞',1000)";
        //删除
        String sql2 = "delete from account where id = 3";
        //改
        String sql3 = "update account set balance = 2000 where id =1";
        //调用方法执行sql语句
        Exercise_01.execute(sql);
        Exercise_01.execute(sql2);
        Exercise_01.execute(sql3);
    }


    //需求的方法
    public static void execute(String sql) {

        //注册驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        try(
            //获取连接对象
            Connection conn = DriverManager.getConnection("jdbc:mysql:///db3", "root","root");
            //获取执行sql对象
            Statement stmt = conn.createStatement();
            ) {
            //执行sql
            stmt.executeUpdate(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}

  1. JDBC查询
    • 查询需要用到excuteQuery();该方法返回的是ResultSet对象。
      • ResultSet类详解:
        • 结果集对象,用来封装查询结果。
        • 方法:
          • boolean next() 游标向下移动一行,判断当前行是否是最后一行的末尾(是否有数据),是返回false,不是则返回true。
          • getXxx(参数):
            • XXX代表数据类型:getInt(), getDouble(), getString()。
            • 参数
              • int :代表列的编号,从1开始 如:getString(1)
              • String : 代表列的名称。如:getDouble("balance”)
            • 使用步骤:
              • 游标向下移动一行
              • 判断是否有数据
              • 获取数据(一般用while循环来判断是否在最后一行末尾)
public class JDBCDemo7 {

    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
            //3.定义sql
            String sql  = "select * from account";
            //4.获取执行sql对象
            stmt = conn.createStatement();
            //5.执行sql
            rs = stmt.executeQuery(sql);
            //6.处理结果
            //循环判断游标是否是最后一行末尾。
            while(rs.next()){

                //获取数据
                //6.2 获取数据
                int id = rs.getInt(1);
                String name = rs.getString("name");
                double balance = rs.getDouble(3);

                System.out.println(id + "---" + name + "---" + balance);
            }
	        
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //7.释放资源

            if(rs != null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(stmt != null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
  1. JDBC预编译Statement
    • PrepareStatement类详解:
      • 和Statement一样,PrepareStatement也是用来执行sql语句的,不同的是,创建PrepareStatement对象的时候把sql语句当做参数传递进去。
      • 优点:
        • 可以通过设置参数,指定sql语句相应变量的值。
          * Statement 需要进行字符串拼接,可读性和维护性比较差
          String sql = “insert into hero values(“select * from account where id = '”+id+’”, name = ‘"+name+"’")";
          * PreparedStatement 使用参数设置,可读性好,不易犯错
          String sql = “insert into hero values(null,?,?,?)”;
        • PrepareStatement有预编译机制,性能比Statement快,效率更高。
          • Statement每次执行,需要把每个sql语句传输到数据端,数据库需要对每一次来的sql语句进行编译处理。
          • PrepareStatement每次执行,只需要一次把sql语句传入到数据库端,数据库对带?的sql进行预编译,每次执行,只需要传输参数到数据库端,网络传输量比sql更小,数据库不需要再重新进行编译,响应更快。
        • PrepareStatement 可以解决注入的问题
          * SQL注入问题:在拼接sql时候,有一些sql特殊的关键词参与字符串拼接,会造成安全问题。
          * 登录问题:
          例如:
          * 用户随便输入密码:password’ or ‘password’ = 'password
          * sql语句:select * from user where name = ‘user’ and password = ‘password’ or ‘password’ = 'password’由于恒成立,故则会导致登录成功。
          * 内存占用:
          例如:
          * 用户提交的数据为:String name = “‘路飞’ or 1 = 1”;
          * 使用Statement的话拼接出来的sql语句是:select * from onepeace where name = ‘路飞’ or 1 = 1 由于有or 1 = 1,恒成立,故会查询数据库表中的所有数据,如果表中的数据炒鸡多,那么就会使得CPU的负载过高,进而使得响应变得及其缓慢。而PrepareStatement为参数设置,就不存在这样的问题。
    • 使用步骤:
      • 导入驱动jar包:mysql-connector-java-5.1.37-bin.jar
      • 注册驱动
      • 获取数据库连接对象Connection
      • 定义sql
        * 注意: sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?;
      • 获取执行sql语句的对象PrepareStatement
      • 给?赋值:
        • 方法:setXxx(参数一,参数二)
          • 参数一:?的位置编号,从一开始
          • 参数二:?的值
      • 执行sql
      • 处理结果
      • 释放资源
import java.sql.*;

/**
 * 测试PreparedStatement的优点:注入式问题
 */
public class TestJDBC04 {

    public static void main(String[] args) {

        try {
            //注册驱动
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        String sql1 = "select * from account where name = ?";
        try(
                //获取连接数据库的对象
                Connection conn = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
                //利用Statement获取执行sql对象
                Statement stmt = conn.createStatement();

                //利用PrepareStatement来获取执行对象
                PreparedStatement preStmt =conn.prepareStatement(sql1);
                ) {

            //定义sql
            String select_name = "lisi";
            String sql2 = "select * from account where name = '"+select_name+"'or 1 = 1";
            //执行sql
            ResultSet rs = stmt.executeQuery(sql2);
            //打印结果
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                double balance = rs.getDouble("balance");
                System.out.println("id:" + id + "\nname:" + name + "\nbalance:" + balance);
                System.out.println("\n");
            } //打印出了表中所有的数据

            System.out.println("====================");

            //利用PrepareStatement来获取的对象来执行sql语句
            preStmt.setString(1,select_name);
            ResultSet rs2 = preStmt.executeQuery();
            //再次查询
            while (rs2.next()) {
                int id = rs2.getInt("id");
                String name = rs2.getString("name");
                double balance = rs2.getDouble("balance");
                System.out.println("id:" + id + "\nname:" + name + "\nbalance:" + balance);
                System.out.println("\n");
            } //子查询出了一条数据

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

    }
}

  1. excute和excuteUpdate区别

    • 相同点:都可以执行增,删,改。
    • 不同点:
      • excute可以执行查询语句。然后可以通过getResult,把结果集取出来。excuteUpdate不能执行查询语句。
      • excute返回的是boolean类型,true表示的是查询语句,false表示的是insert,delete,update等语句。excuteUpdate返回的是int,表示有多少条数据受到了影响。
  2. JDBC特殊操作—获取自增长id以及表的元数据

    • 获取自增长id
      * 在Statement通过execute或者executeUpdate执行完插入语句后,MySQL会为新插入的数据分配一个自增长id,(前提是这个表的id设置为了自增长,在Mysql创建表的时候,AUTO_INCREMENT就表示自增长)
      CREATE TABLE hero (
      id int(11) AUTO_INCREMENT,
      }
      但是无论是execute还是executeUpdate都不会返回这个自增长id是多少。(excute返回执行的语句类型,true表示的是查询,false表示的是insert,update等,excuteUpdate返回的是影响的行数。)需要通过Statement的getGeneratedKeys获取该id
import java.sql.*;

public class JDBCDemo05 {

    public static void main(String[] args) {

        try {
            //注册驱动
            Class.forName("com.mysql.jdbc.Driver");//总是在这里忘记加;号了,注意!!!
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //定义sql语句
        String sql = "insert into account values(null, '索隆',5000)";
        try(
                //获取连接数据库对象
                Connection conn = DriverManager.getConnection("jdbc:mysql:///db3","root","root");//忘记传入账号密码了
                //获取执行sql的对象
                PreparedStatement pstm = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//进行预编译
        ) {
            //执行sql
             pstm.executeUpdate();
            //通过getGenartedekeys()获取id
            ResultSet rs = pstm.getGeneratedKeys();
            while(rs.next()){
                int id = rs.getInt(1);
                System.out.println("加入的信息的id为:" + id);
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        }


    }
}

  1. 获取表的元数据
    * 概念:和数据库服务器相关的概念,比如数据库版本,有哪些列表,字段类型是什么等等。
import java.sql.*;

public class JDBCDemo06 {

    public static void main(String[] args) {

        try {
            //注册驱动
            Class.forName("com.mysql.jdbc.Driver");//总是在这里忘记加;号了,注意!!!
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //定义sql语句
        String sql = "insert into account values(null, '索隆',5000)";
        try(
                //获取连接数据库对象
                Connection conn = DriverManager.getConnection("jdbc:mysql:///db3","root","root");//忘记传入账号密码了
        ) {
            //查看数据库层面的元数据
            DatabaseMetaData dbmd = conn.getMetaData();

            //获取数据库服务器产品的名称
            System.out.println("数据库产品的名称为:" + dbmd.getDatabaseProductName());

            //获取数据库服务器产品的版本号
            System.out.println("数据库服务器产品的版本号为:" + dbmd.getDatabaseProductVersion());

            //获取数据库用于作用与类别和表名之间的分隔符
            System.out.println("数据库用于作用与类别和表名之间的分隔符为:" + dbmd.getCatalogSeparator());

            //获取驱动版本
            System.out.println("驱动版本为:" + dbmd.getDriverVersion());

            //获取数据库名称
            System.out.println("可用的数据库表名称为:");
            ResultSet rs = dbmd.getCatalogs();
            while (rs.next()) {
                System.out.println("数据库名称为:" + rs.getString(1));

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

  1. JDBC事务
    • 概念:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
    • 操作
      • 开启事务
      • 提交事务
      • 回滚事务
    • 使用Connection对象来管理事务
      • 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
        * 在执行sql之前开启事务
      • 提交事务:commit()
        * 当所有sql都执行完提交事务
      • 回滚事务:rollback()
        * 在catch中回滚事务
/**设计一个代码,删除表中前10条数据,但是删除前会在控制台弹出一个提示:
 * 是否要删除数据(Y/N)
 * 如果用户输入Y,则删除
 * 如果输入N则不删除。
 * 如果输入的既不是Y也不是N,则重复提示
 */

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

public class Exercise_8_4_demo2 {

    public static void main(String[] args) {

        //注册驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }



        //定义sql语句
        String sqlDelete = "delete from account where id = ?";
        String sqlSelect = "select * from account where id = ? ";
        try (
                //获取数据库连接对象
                Connection conn = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
                //获取执行sql语句对象
                PreparedStatement pstmt = conn.prepareStatement(sqlSelect);
                PreparedStatement pstmt2 = conn.prepareStatement(sqlDelete);

        ) {


            //开启事务
            conn.setAutoCommit(false);

            int a = 1; //设置初始ID = 1;

            //用for循环找出前十位ID
            for (int i = 1; i <= 10; i++) {
                while (true) {
                    pstmt.setInt(1,a);
                    ResultSet rs = pstmt.executeQuery();
                    //判断是否有ID存在
                    if (rs.next()) {
                        pstmt2.setInt(1,a);
                        pstmt2.executeUpdate();     //存在就删除
                        System.out.println("即将删除id = "+  a + " 的数据");
                        break;  //如果存在终止循环
                    } else {
                        //不存在则判断下一个ID(a++)
                        a++;
                    }
                }
            }

            //提示是否删除信息
           while(true) {
               System.out.println("是否删除这些数据Y/N:");
               Scanner sc = new Scanner(System.in);
               String select = sc.nextLine();
               if (select.equals("Y")) {   //字符串与字符串之间的比较需要用equals()方法。
                   //关闭事务
                   conn.commit();
                   System.out.println("删除成功!");
                   break;
               } else if (select.equals("N")){
                   System.out.println("取消删除!");
                   break;
               } else {
                   System.out.println("输入有误,请重新输入!");
               }
           }


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

    }

}

  1. 对象和关系数据库的映射-ORM

    • ORM(Object Relationship Database Mapping):一个对象对应着数据库里的一条记录。
    • DAO(Data Access Object):数据访问对象。
  2. 数据库连接池

    • 其实就是一个容器(集合),存放数据库连接的容器。当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库的时候,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器.
    • 好处:
      • 节约资源
      • 用户访问高效.
    • 实现:
      • 标准接口:dataSource java.sql包下面的.
        • 方法:
          • 获取连接;getConnection()
          • 归还连接;Connection.close.如果连接的对象是从连接池中获取的,那么调用Connection,close()方法,则不会关闭连接了,而是归还连接.
    1. c3p0数据库连接池
      步骤:
      1. 导入jar包 (两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar ,不要忘记导入数据库驱动jar包
      2. 定义配置文件:
      * 名称: c3p0.properties 或者 c3p0-config.xml
      * 路径:直接将文件放在src目录下即可。
      3. 创建核心对象 数据库连接池对象 ComboPooledDataSource
      4. 获取连接: getConnection
    2. Druid:数据库连接池实现技术,由阿里巴巴提供的
      步骤:
      1. 导入jar包 druid-1.0.9.jar
      2. 定义配置文件:
        • 是properties形式的
        • 可以叫任意名称,可以放在任意目录下
      3. 加载配置文件。Properties
      4. 获取数据库连接池对象:通过工厂来来获取 DruidDataSourceFactory
      5. 获取连接:getConnection
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值