JDBC

1,JDBC概述

JDBC(Java DataBase Connectivity) java数据库连接。是一套通过java操作数据的公共规范。 作用:JAVA程序连接访问关系型数据库的。

2, JDBC快速入门

2.0 java操作数据库,需要驱动jar包

1、在项目中创建lib 文件夹,然后将  mysql链接的jar 文件拖放到  lib 文件夹下

JDBC_第1张图片

 

2.、构建 lib 库

A 在mysql-connector-java-5.1.7-bin-jar 文件上右键--选择build--addbuild

JDBC_第2张图片

 

 

 

 B buil成功后结果

JDBC_第3张图片

 

 

2.1 实现步骤

  1. 导入数据库jdbc驱动包

  2. 配置数据库连接相关信息

  3. 通过Class.forName、DriverManager加载驱动并创建Connection对象连接数据库

  4. 通过Connection对象创建PrepareStatement对象发送sql到数据库并执行

  5. 通过PrepareStatement设置参数(如果sql没有占位符则跳过)

  6. 执行sql,获取结果

  7. 关闭连接

DQL:

public class JDBCTest {
​
    public static void main(String[] args) throws Exception {
        //配置数据库连接信息
        //数据库驱动
        String driverClass = "com.mysql.jdbc.Driver";
        //数据库url
        String url = "jdbc:mysql://localhost:3306/eshop?useUnicode=true&characterEncoding=UTF-8";
        //用户名
        String user = "root";
        //密码
        String password = "123456";
​
        //加载数据库驱动
        Class.forName(driverClass);
        //创建数据库连接
        Connection conn = DriverManager.getConnection(url, user, password);
        //发送sql语句到数据库
        PreparedStatement pst = conn.prepareStatement(
        "select * from student");
        //执行sql语句并返回结果
        ResultSet rs = pst.executeQuery();
        //提取执行结果
        while(rs.next()) {
            System.out.println("name: " + rs.getString("stu_name") + " password: " + rs.getString(2));
        }
        conn.close();
    }
}

 

DML:

public class JDBCTest {
​
    public static void main(String[] args) throws Exception {
        //配置数据库连接信息
        //数据库驱动
        String driverClass = "com.mysql.jdbc.Driver";
        //数据库url
        String url = "jdbc:mysql://localhost:3306/eshop?useUnicode=true&characterEncoding=UTF-8";
        //用户名
        String user = "root";
        //密码
        String password = "123456";
​
        //加载数据库驱动
        Class.forName(driverClass);
        //创建数据库连接
        Connection conn = DriverManager.getConnection(url, user, password);
        //发送sql语句到数据库
        PreparedStatement pst = conn.prepareStatement(
        "delete from student where stu_id = ? ");
        //执行sql语句并返回结果
        int i = pst.executeUpdate();
        //提取执行结果
        if(i>0){
            System.out.println("删除成功");
        }else{
            System.out.println("删除失败");
        }
        conn.close();
    }
}

 

2.2 代码实现说明

Connection接口:与特定数据库的连接(会话)。 PreparedStatement接口:表示预编译的 SQL 语句的对象。SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。

ResultSet接口:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。

2.3 JDBC事务管理

事务是数据库中非常重要的一个特性,事务属于原子性操作,是数据库执行过程中的一个逻辑单位,要么全部成功要么全部失败。

Connection接口中的事务操作

  • pulic void commit() 事务提交

  • pulic void rollback() 事务回滚

  • pulic void setAutoCommit(boolean autoCommit) 执行是否自动提交事务,默认自动提交事务

public class JDBCTest {
​
    public static void main(String[] args) throws SQLException {
        //配置数据库连接信息
        //数据库驱动
        String driverClass = "com.mysql.jdbc.Driver";
        //数据库url
       String url = "jdbc:mysql://localhost:3306/eshop?useUnicode=true&characterEncoding=UTF-8";
        //用户名
        String user = "root";
        //密码
        String password = "123456";
​
        Connection conn = null;
​
        try {
            //加载数据库驱动
            Class.forName(driverClass);
            //创建数据库连接
            conn = DriverManager.getConnection(url, user, password);
            //设置事务为手动提交
            conn.setAutoCommit(false);
            //发送sql语句到数据库
            // 添加一条数据
            PreparedStatement pst1 = conn.prepareStatement("insert into student(stu_name, stu_password, stu_age) values(?,?,?)");
            pst1.setString(1, "seven");
            pst1.setString(2, "123");
            pst1.setInt(3, 20);
            //执行sql语句并返回结果
            int count1 = pst1.executeUpdate();
            // 删除一条数据
             PreparedStatement pst2 = conn.prepareStatement("delete from student where stu_name = ? ");
            pst2.setString(1, "zhangsan");            
            //执行sql语句并返回结果
            int count2 = pst2.executeUpdate();
            
            //事务提交:事务内的添加操作跟删除操作要么全部成功,要么全部失败。
            conn.commit();
            //受影响条数
            System.out.println("count: " + count);
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
            conn.rollback();
        }
​
    }
}

 

3 其它

3.1 Statement与PrepareStatement的区别

  1. PreparedStatement是预编译的,对于多次执行的SQL可以大大提高效率。而Statement不行

  2. PreparedStatement可以通过占位符的方式解决SQL注入的问题,而Statement不行

  3. 2者SQL的传入位置不同

//  Statement code :
   Statement statement = conn.createStatement();
   String sqlString = " delete from student where stu_name ='seven' " ;
   statement.executeUpdate(sqlString);
//PreparedStatement code:
   PreparedStatement updateSales = conn.prepareStatement("delete from student where stu_name ='seven' "); 
  updateSales.executeUpdate();

 

3.2 使用Batch功能

当执行一行的SQL,不同的参数(比如插入N条数据)的时候可以使用PreparedStatement的Batch功能。这样不管操作多少条数据都只需要2次网络往返(1次是预存储statement,1次是执行batch命令)。

注意:

  • 事务的设置,不能使自动提交,要批量添加后才提交。

  • 在mysql 下使用批量执行的时候要在,url 后面添加手动设置支持批量添加

    String url="jdbc:mysql://localhost:3306/XXdb?rewriteBatchedStatements=true"
    
        // statement executeBatch  code :
        con.setAutoCommit(false);   
        Statement stmt = conn.createStatement();
        stmt.addBatch("INSERT into student values ('张三','123','18'))");
        stmt.addBatch("INSERT into student values ('李四','456','21'))");
        stmt.addBatch("INSERT into student values ('王五','789','22'))");
        
        int [] updateCounts=stmt.executeBatch();
        con.commit();
        pstm.clearBatch();
    //  PreparedStatement executeBatch  code :
    conn.setAutoCommit(false);
    PreparedStatement ps = conn.prepareStatement("INSERT into student values (?,?,?))";
        for (n = 0; n < 100; n++) {
        ps.setString(name[n]);
        ps.setLong(id[n]);
        ps.setInt(salary[n]);
    ps.addBatch();
    }
    int [] = ps.executeBatch();
    con.commit();
    pstm.clearBatch();

     

3.3 SQL注入(攻击)

在定义SQL的时候把用户输入的内容作为参数跟SQL拼接的话,当用户输入不合理的数据值的时候有可能导致SQL执行异常。 例如: 正常的登录SQL : select * from student where stu_name = 'seven' and stu_pwd = '123' 其中seven123为用户从界面传入的登录账号,如果用户输入字段带'号则会异常。

如果用户输入 1' or 1='1 时候则拼接的SQL为 select * from student where stu_name = '1' or 1='1' and stu_pwd = '123' 此时用户只知道用户名不知道密码则也可以登录成功。

再例如如果用户输入 abc' or 1='1' -- (最后要有个空格)则拼接的SQL为 select * from student where stu_name = 'abc' or 1='1' -- ' and stu_pwd = '123' 则用户此时不知道用户名跟密码情况都可以登录成功。

4 dbutils

dbutils是Apache公司开发的一个封装了JDBC的框架。是一种用于执行SQL语句的JAVA API,可以为多种关系数据库提供统一访问。 下载地址 http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi

4.1 dbutils的使用

新增(删除、修改类似)

// 先获取连接
Connection conn = DBHelper.getConn();
// 创建QueryRunner对象
QueryRunner qr = new QueryRunner();
// 定义SQL
String sql = "insert into  student(stu_name,stu_pwd) values(?,?)" ;
// 执行SQL,获取结果
int i = qr.update(conn, sql,"古天乐","123");

 

查询

// 先获取连接
Connection conn = DBHelper.getConn();
// 创建QueryRunner对象
QueryRunner qr = new QueryRunner();
// 定义SQL
String sql = "select * from student " ;
// 执行查询,BeanListHandler表示把结果封装到一个Student对象的List集合中
// Bean中的属性必须跟数据库中的字段名一样才可以映射上
List list =  qr.query(conn, sql,new BeanListHandler(Student.class));
DBHelper.closeConn(conn);

 

重点在BeanListHandler,它是ResultSetHandler接口的实现类,每种实现类表示将结果封装成不同的对象。Bean中的属性必须跟数据库中的字段名一样才可以映射上

  • 1 BeanListHandler将查询结果的每一行封装到Bean对象,然后再存入List集合

String sql = "select * from student " ;
List list =  qr.query(conn, sql,new BeanListHandler(Student.class));

 

  • 2 BeanHandler将查询结果的第一行数据,封装到Bean对象

String sql = "select * from student where stu_id = 1  " ;
Student bean =  qr.query(conn, sql,new BeanHandler(Student.class));

 

  • 3 ColumnListHandler 将查询结果的指定列的数据封装到List集合中

String sql = "select stu_name from student " ;
List list =  (List) qr.query(conn, sql,new ColumnListHandler()); 
  
 

 

  • 4 ScalarHandler 封装结果为单行单列的结果,类似count、avg、max、min、sum......函数

String sql = "select count(*) from student " ;
Object object =  qr.query(conn, sql,new ScalarHandler());  
  
 

 

  • 5 ArrayHandler:将查询结果的第一行数据,保存到Object数组中

String sql = "select * from student " ;
Object [] object =  qr.query(conn, sql,new ArrayHandler()); 

 

  • 6 ArrayListHandler 将查询的结果,每一行先封装到Object数组中,然后将数据存入List集合

String sql = "select * from student " ;
List list =  qr.query(conn, sql,new ArrayListHandler());  
  
 

 

  • 7 MapHandler 将查询结果的第一行数据封装到map结合(key==列名,value==列值)

String sql = "select * from student " ;
Map map =  qr.query(conn, sql,new MapHandler()); 

 

  • 8 MapListHandler将查询结果的每一行封装到map集合(key==列名,value==列值),再将map集合存入List集合

String sql = "select * from student " ;
List> list =  qr.query(conn, sql,new MapListHandler()); 

 

5 连接池

5.1 获取DataSource对象

  • 1 方式1

        DruidDataSource ds = new DruidDataSource();
        ds.setUrl(URL);
        ds.setUsername(USER);
        ds.setPassword(PWD);
        ds.setDriverClassName(DRIVER);

 

  • 2 方式2

    Map map = new HashMap();
    map.put("driverClassName", DRIVER);
    map.put("url", URL);
    map.put("username", USER);
    map.put("password", PWD);
    DataSource ds = DruidDataSourceFactory.createDataSource(map);

 

  • 3 方式3

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/test1?                        useUnicode=true&characterEncoding=UTF-8
    username=root
    password=root
    Properties p = new Properties();
    InputStream is = new FileInputStream(new File("src/datasource.properties"));
    p.load(is);
    DataSource ds = DruidDataSourceFactory.createDataSource(p);

 

5.2 使用DataSource对象

    QueryRunner qr = new QueryRunner(ds);
    String sql = " select * from student " ;
    List list = qr.query(sql, new BeanListHandler(Student.class));
​
    QueryRunner qr = new QueryRunner( );
    String sql = " select * from student " ;
    List list = qr.query(ds.getConnection(),sql, new BeanListHandler(Student.class));

 

如果不需要DataSource对象,而需要原始的Connection对象的话也可以通过DataSource的getConnection()方法获取连接对象。

你可能感兴趣的:(JDBC)