美文网首页
Java 操作数据库

Java 操作数据库

作者: 圣堂刺客_x | 来源:发表于2019-11-23 17:15 被阅读0次

1 JDBC

1.1 JDBC概述

  JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范
  JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
  JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。
今天我们使用的是mysql的驱动mysql-connector-java-5.1.39-bin.jar

1.2 JDBC原理

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

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

1.3 案例分析

  我们学习了sql语句的使用,并创建的分类表sort,今天我们将使用JDBC对分类表进行增删改查操作。

#创建数据库
create database day22_JDBC;
#使用数据库
use day22_JDBC;
###创建分类表
create table sort(
  sid int PRIMARY KEY ,
  sname varchar(100)
);
#初始化数据
insert into sort(sname) values('家电');
insert into sort(sname) values('服饰');
insert into sort(sname) values('化妆品');

1.4 JDBC开发步骤

  1. 注册驱动,告知JVM使用的是哪一个数据库驱动
  2. 获得连接,使用JDBC的类,完成数据库的连接
  3. 获得语句执行平台,通过连接对象获取SQL语句的执行对象
  4. 执行sql语句,使用执行对象向数据库执行SQL语句,获取数据库的执行结果
  5. 处理结果
  6. 释放资源.

1.4.1 导入驱动jar包

1.4.2 API详解:注册驱动

Class.forName("com.mysql.jdbc.Driver");

  JDBC规范定义驱动接口:java.sql.Driver,MySql驱动包提供了实现类:com.mysql.jdbc.Driver
  DriverManager工具类,提供注册驱动的方法 registerDriver(),方法的参数是java.sql.Driver,所以我们可以通过如下语句进行注册:

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

以上代码不推荐使用,存在两方面不足
  1. 硬编码,后期不易于程序扩展和维护
  2. 驱动被注册两次。
  通常开发我们使用Class.forName() 加载一个使用字符串描述的驱动类。
  如果使用Class.forName()将类加载到内存,该类的静态代码将自动执行。
  通过查询com.mysql.jdbc.Driver源码,我们发现Driver类“主动”将自己进行注册

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }
……
}

1.4.3 API详解:获得链接

Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","root");

  获取连接需要方法 DriverManager.getConnection(url,username,password),三个参数分别表示,url 需要连接数据库的位置(网址) user用户名 password 密码
url比较复杂,下面是mysql的url:
jdbc:mysql://localhost:3306/mydb
JDBC规定url的格式由三部分组成,每个部分中间使用冒号分隔。
  第一部分是jdbc,这是固定的;
  第二部分是数据库名称,那么连接mysql数据库,第二部分当然是mysql了;
  第三部分是由数据库厂商规定的,我们需要了解每个数据库厂商的要求,mysql的第三部分分别由数据库服务器的IP地址(localhost)、端口号(3306),以及DATABASE名称(mydb)组成。

1.4.4 API详解:获得语句执行平台

String sql = "某SQL语句";
获取Statement语句执行平台:Statement stmt = con.createStatement();

常用方法:

int executeUpdate(String sql); --执行insert update delete语句.
ResultSet executeQuery(String sql); --执行select语句.
boolean execute(String sql); --执行select返回true 执行其他的语句返回false.

1.4.5 API详解:处理结果集(执行insert、update、delete无需处理)

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

rs.next();//指向第一行
rs.getInt(1);//获取第一行第一列的数据

常用方法:

//获得任意对象
Object getObject(int index)
Object getObject(String name) 
//获得字符串
String getString(int index)
Object getObject(String name) 
 获得整形
int getInt(int index)
Object getObject(String name)
获得双精度浮点型
double getDouble(int index)
Object getObject(String name) 

1.4.6 API详解:释放资源

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

rs.close();
stmt.close();
con.close();

TestDemo.java执行insert、update、delete

package com.qtw.api;

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

public class TestDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.注册驱动,反射技术,将驱动类加载到内存
        Class.forName("com.mysql.jdbc.Driver");
        //2.获得数据库连接DriverManager类中的静态方法
        //public static Connection getConnection(String url,String user, String password)
        //返回值是Connection接口的实现类,在mysql驱动程序
        String url = "jdbc:mysql://192.168.134.66:3306/Train";
        String username = "root";
        String password = "root123";
        Connection conn = DriverManager.getConnection(url, username, password);
        System.out.println(conn);
        //3.通过连接对象获取SQL语句的执行对象
        //Statement createStatement()
        //返回的是Statement接口的实现类对象,,在mysql驱动程序
        Statement stat = conn.createStatement();
        //4.执行sql语句
        //通过执行者对象调用方法,执行sql语句获得结果
        //int executeUpdate(String sql) 执行数据库中的语句,insert delete update
        //返回值int 操作成功数据多少行
        String sql = "INSERT INTO Student(s_id,s_name,s_birth,s_sex) values('10','老王','2000-01-01','男');";
        stat.executeUpdate(sql);
        //6.释放资源
        stat.close();
        conn.close();
    }
}

TestDemo.java执行select

package com.qtw.api;

import java.sql.*;

public class TestDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.注册驱动,反射技术,将驱动类加载到内存
        Class.forName("com.mysql.jdbc.Driver");
        //2.获得数据库连接DriverManager类中的静态方法
        String url = "jdbc:mysql://192.168.134.66:3306/Train";
        String username = "root";
        String password = "root123";
        Connection conn = DriverManager.getConnection(url, username, password);
        System.out.println(conn);
        //3.通过连接对象获取SQL语句的执行对象
        Statement stat = conn.createStatement();
        //4.执行select语句,获取结果集
        //ResultSet executeQuery(String sql)  执行select查询
        //返回值 ResultSet接口的实现类对象,实现类在mysql驱动中
        String sql = "SELECT * FROM Student;";
        ResultSet rs = stat.executeQuery(sql);
        //5.处理结果集
        //ResultSet接口方法 boolean next()返回true有结果集,返回false没有结果集
        while(rs.next()){
            //获取每列数据,使用ResultSet接口的getXXX方法
            System.out.println(rs.getInt("s_id")+"   "+rs.getString("s_name")+"   "+rs.getString("s_birth")+"   "+rs.getString("s_sex"));
        }
        //6.释放资源
        rs.close();
        stat.close();
        conn.close();
    }
}

1.5 SQL注入问题用户登录

在数据库创建用户信息

CREATE TABLE users(
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(100),
    password VARCHAR(100)
);

INSERT INTO users (username,password) VALUES ('a','1'),('b','2');

SELECT * FROM users;
-- 登录查询 --
SELECT * FROM users WHERE username = 'a' and password = '1';

-- 改造后 --
SELECT * FROM users WHERE username = 'AAA' and password = 'BBB' or 1=1;

假设有登录案例SQL语句如下:

SELECT * FROM 用户表 WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码;

此时,当用户输入正确的账号与密码后,查询到了信息则让用户登录。但是当用户输入的账号为XXX 密码为:XXX’ OR ‘a’=’a时,则真正执行的代码变为:

SELECT * FROM 用户表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’  OR ’a’=’a’;

此时,上述查询语句时永远可以查询出结果的。那么用户就直接登录成功了,显然我们不希望看到这样的结果,这便是SQL注入问题。
演示代码如下:

package com.qtw.api;
/*
* Java程序实现用户登录,用户名和密码,数据库检查
* 演示被别人注入攻击
* */

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

public class TestDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.注册驱动,反射技术,将驱动类加载到内存
        Class.forName("com.mysql.jdbc.Driver");
        //2.获得数据库连接DriverManager类中的静态方法
        String url = "jdbc:mysql://192.168.134.66:3306/Train";
        String username = "root";
        String password = "root123";
        Connection conn = DriverManager.getConnection(url, username, password);
        System.out.println(conn);
        //3.通过连接对象获取SQL语句的执行对象
        Statement stat = conn.createStatement();
        Scanner sc = new Scanner(System.in);
        String user = sc.nextLine();
        String pass = sc.nextLine();

        //执行sql语句,查询用户名和密码,如果存在登录成功,如果不存在,登录失败
        String sql = "SELECT * FROM users WHERE username = '"+user+"' and password = '"+pass+"';";
        System.out.println(sql);

        ResultSet rs = stat.executeQuery(sql);
        while (rs.next()){
            System.out.println(rs.getString("username") + "..." + rs.getString("password"));
        }
        //6.释放资源
        rs.close();
        stat.close();
        conn.close();
    }
}

运行结果

为此,我们使用PreparedStatement来解决对应的问题。

1.6 API详解:预处理对象

  1. 使用PreparedStatement预处理对象时,建议每条sql语句所有的实际参数,都使用逗号分隔。
String sql = "insert into sort(sid,sname) values(?,?)";;
PreparedStatement预处理对象代码:
PreparedStatement psmt = conn.prepareStatement(sql)

常用方法:

  1. 执行SQL语句:
int executeUpdate(); --执行insert update delete语句.
ResultSet executeQuery(); --执行select语句.
boolean execute(); --执行select返回true 执行其他的语句返回false.
  1. 设置实际参数
    void setXxx(int index, Xxx xx) 将指定参数设置为给定Java的xx值。在将此值发送到数据库时,驱动程序将它转换成一个 SQL Xxx类型值。
    演示代码:
package com.qtw.api;
/*
* Java程序实现用户登录,用户名和密码,数据库检查
* 防止被别人注入攻击
* Statement接口实现类,作用执行SQL语句,返回结果集
* 有一个子接口PreparedStatement(SQL预编译存储,多次高效的执行SQL)
* */

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

public class TestDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.注册驱动,反射技术,将驱动类加载到内存
        Class.forName("com.mysql.jdbc.Driver");
        //2.获得数据库连接DriverManager类中的静态方法
        String url = "jdbc:mysql://192.168.134.66:3306/Train";
        String username = "root";
        String password = "root123";
        Connection conn = DriverManager.getConnection(url, username, password);

        Scanner sc = new Scanner(System.in);
        String user = sc.nextLine();
        String pass = sc.nextLine();

        //执行sql语句,查询用户名和密码,如果存在登录成功,如果不存在,登录失败
        //SQL语句中的参数用?占位
        String sql = "SELECT * FROM users WHERE username = ? and password = ?;";
        //调用Connection接口的方法prepareStatement,获取PrepareStatement接口的实现类。
        PreparedStatement pst = conn.prepareStatement(sql);
        //设置参数
        pst.setObject(1, user);
        pst.setObject(2, pass);
        ResultSet rs = pst.executeQuery();
        while (rs.next()){
            System.out.println(rs.getString("username") + "..." + rs.getString("password"));
        }
        //6.释放资源
        rs.close();
        pst.close();
        conn.close();
    }
}

运行结果

1.7 JDBC工具类

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

package com.qtw.api;

import java.sql.*;

/*
* 实现JDBC工具类
* 定义方法,直接返回数据库的连接对象
* */
public class JDBCUtils {
    private JDBCUtils(){}
    private static Connection conn;

    static {
        try {
            //1.注册驱动,反射技术,将驱动类加载到内存
            Class.forName("com.mysql.jdbc.Driver");
            //2.获得数据库连接DriverManager类中的静态方法
            String url = "jdbc:mysql://192.168.134.66:3306/Train";
            String username = "root";
            String password = "root123";
            conn = DriverManager.getConnection(url, username, password);
        }catch (Exception ex){
            throw new RuntimeException(ex+"数据库连接失败");
        }
    }

    /*
    * 定义静态方法,返回数据路的连接对象
    * */
    public static Connection getConnection(){
        return conn;
    }

    //关闭
    public static void close(Connection conn, Statement stat, ResultSet rs){
        if(rs != null){
            try {
                rs.close();
            }catch (SQLException ex){}
        }

        if(stat != null){
            try {
                stat.close();
            }catch (SQLException ex){}
        }

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

    public static void close(Connection conn, Statement stat){
        if(stat != null){
            try {
                stat.close();
            }catch (SQLException ex){}
        }

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

TestDemo.java

package com.qtw.api;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class TestDemo {
    public static void main(String[] args) throws Exception{
        Connection conn = JDBCUtils.getConnection();
        System.out.println(conn);
        PreparedStatement pst = conn.prepareStatement("SELECT s_name FROM Student;");
        ResultSet rs = pst.executeQuery();
        while(rs.next()){
            System.out.println(rs.getString("s_name"));
        }
        JDBCUtils.close(conn,pst);
    }
}

2 properties配置文件

2.1 使用properties配置文件

开发中获得连接的4个参数(驱动、URL、用户名、密码)通常都存在配置文件中,方便后期维护,程序如果需要更换数据库,只需要修改配置文件即可。
通常情况下,我们习惯使用properties文件,此文件我们将做如下要求:

  1. 文件位置:任意,建议src下
  2. 文件名称:任意,扩展名为properties
  3. 文件内容:一行一组数据,格式是“key=value”.
    a) key命名自定义,如果是多个单词,习惯使用点分隔。例如:jdbc.driver
    b) value值不支持中文,如果需要使用非英文字符,将进行unicode转换。

2.2 创建配置文件

在项目跟目录下,创建文件,输入“db.properties”文件名。
文件中的内容

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb
user=root
password=root

2.3 测试

db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.134.66:3306/Train
user=root
password=root123

JDBCUtilsConfig.java

package com.qtw.api;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/*
* 编写数据库连接的工具类,JDBC工具类
* 获取连接对象采用读取配置文件的方法
* 读取数据库连接,执行一次,static{}
* */
public class JDBCUtilsConfig {
    private JDBCUtilsConfig(){}
    private static Connection conn;
    private static String driverClass;
    private static String url;
    private static String user;
    private static String password;

    static {
        try {
            readConfig();
            //连接数据库
            Class.forName(driverClass);
            conn = DriverManager.getConnection(url,user,password);
            System.out.println(conn);
        }catch (Exception ex){
            throw new RuntimeException(ex+"数据库连接失败");
        }
    }
    /*
    * 定义静态方法,返回数据路的连接对象
    * */
    public static Connection getConnection(){
        return conn;
    }
    /*
    * 读取文件
    * */
    public static void readConfig() throws Exception{
        //使用类的加载器,在class文件目录下面寻找文件
        InputStream in = PropertiesDemo.class.getClassLoader().getResourceAsStream("db.properties");
        Properties pro = new Properties();
        pro.load(in);
        //获取集合中的键值对
        driverClass = pro.getProperty("driver");
        url = pro.getProperty("url");
        user = pro.getProperty("user");
        password = pro.getProperty("password");
    }
}

TestDemo.java

package com.qtw.api;
import java.sql.Connection;

public class TestDemo {
    public static void main(String[] args) throws Exception{
        Connection conn = JDBCUtilsConfig.getConnection();
        System.out.println(conn);
    }
}

3 DBUtils

  如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC开发,本案例我们讲采用apache commons组件一个成员:DBUtils。
  DBUtils就是JDBC的简化开发工具包。需要项目导入commons-dbutils-1.6.jar才能够正常使用DBUtils工具。

3.1 概述

DBUtils是java编程中的数据库操作实用工具,小巧简单实用。
DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
Dbutils三个核心功能介绍
  1.QueryRunner中提供对sql语句操作的API.
  2.ResultSetHandler接口,用于定义select操作后,怎样封装结果集.
  3. DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法

3.2 QueryRunner核心类

update(Connection conn, String sql, Object... params) ,用来完成表数据的增加、删除、更新操作
query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) ,用来完成表数据的查询操作

3.3 QueryRunner实现添加、更新、删除操作

演示代码TestDemo.java

package com.qtw.api;
import org.apache.commons.dbutils.QueryRunner;

import java.sql.Connection;
import java.sql.SQLException;

public class TestDemo {
    public static void main(String[] args) throws Exception{
        insert();
        update();
        delete();
    }
    public static void insert(){
        try {
            //获取一个用来执行SQL语句的对象   QueryRunner
            QueryRunner qr = new QueryRunner();
            String sql = "INSERT INTO Student(s_id,s_name,s_birth,s_sex) VALUES(?,?,?,?); ";
            Object[] params = {"11","张三","1990-11-22","男"};
            Connection conn = JDBCUtilsConfig.getConnection();
            int line = qr.update(conn,sql,params);// 用来完成表数据的增加、删除、更新操作
            //结果集处理
            System.out.println("line = " + line);
        } catch (SQLException ex) {
            throw new RuntimeException(ex);
        }
    }
    public static void update(){
        try {
            //创建一个QueryRunner对象,用来完成SQL语句的执行
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "UPDATE Student SET s_birth = ? WHERE s_id = ?;";
            Object[] params = {"1992-11-09","11"};
            Connection conn = JDBCUtilsConfig.getConnection();
            int line = qr.update(conn, sql, params);
            //结果集的处理
            System.out.println("line="+line);

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public static void delete(){
        try {
            //创建一个QueryRunner对象,用来完成SQL语句的执行
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "DELETE FROM Student WHERE s_id = ?";
            Object[] params = {"11"};
            Connection conn = JDBCUtilsConfig.getConnection();
            int line = qr.update(conn, sql, params);
            //结果集的处理
            System.out.println("line="+line);

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

3.4 QueryRunner实现查询操作

query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) ,用来完成表数据的查询操作

3.4.1 ResultSetHandler结果集处理类

方法 描述
ArrayHandler 将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值
ArrayListHandler 将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。
BeanHandler 将结果集中第一条记录封装到一个指定的javaBean中。
BeanListHandler 将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中
ColumnListHandler 将结果集中指定的列的字段值,封装到一个List集合中
ScalarHandler 它是用于单数据。例如select count(*) from 表操作。
MapHandler 将结果集第一行封装到Map集合中,Key 列名, Value 该列数据
MapListHandler 将结果集第一行封装到Map集合中,Key 列名, Value 该列数据,Map集合存储到List集合

3.4.2 JavaBean

JavaBean就是一个类,在开发中常用封装数据。具有如下特性
  1. 需要实现接口:java.io.Serializable ,通常实现接口这步骤省略了,不会影响程序。
  2. 提供私有字段:private 类型 字段名;
  3. 提供getter/setter方法:
  4. 提供无参构造
Student.java

package com.qtw.api;

public class Student {
    private int s_id;
    private String s_name;
    private String s_birth;
    private String s_sex;
    
    public Student() {
        super();
    }
    
    public int getS_id() {
        return s_id;
    }

    public void setS_id(int s_id) {
        this.s_id = s_id;
    }

    public String getS_name() {
        return s_name;
    }

    public void setS_name(String s_name) {
        this.s_name = s_name;
    }

    public String getS_birth() {
        return s_birth;
    }

    public void setS_birth(String s_birth) {
        this.s_birth = s_birth;
    }

    public String getS_sex() {
        return s_sex;
    }

    public void setS_sex(String s_sex) {
        this.s_sex = s_sex;
    }

    @Override
    public String toString() {
        return "Student{" +
                "s_id=" + s_id +
                ", s_name='" + s_name + '\'' +
                ", s_birth='" + s_birth + '\'' +
                ", s_sex='" + s_sex + '\'' +
                '}';
    }
}

3.4.3 结果集处理

演示代码TestDemo.java

package com.qtw.api;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class TestDemo {
    public static void main(String[] args) throws Exception{
        //method1();
        //method2();
        //method3();
        //method4();
        //method5();
        //method6();
        //method7();
        method8();
    }
    //ArrayHandler:将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值
    public static void method1(){
        try {
            //获取QueryRunner对象
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "SELECT * FROM Student;";
            Object[] params = {};
            Connection conn = JDBCUtilsConfig.getConnection();
            Object[] objArray = qr.query(conn, sql, new ArrayHandler(), params);
            //结果集的处理
            System.out.println(Arrays.toString(objArray));
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //ArrayListHandler:将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。
    public static void method2() {
        try {
            //获取QueryRunner对象
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "SELECT * FROM Student WHERE s_name = ?;";
            Object[] params = {"老王"};
            Connection conn = JDBCUtilsConfig.getConnection();
            List<Object[]> list = qr.query(conn, sql, new ArrayListHandler(), params);
            //结果集的处理
            for (Object[] objArray : list) {
                System.out.println(Arrays.toString(objArray));
            }
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //BeanHandler:将结果集中第一条记录封装到一个指定的javaBean中
    public static void method3(){
        try{
            //获取QueryRunner
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "SELECT * FROM Student WHERE s_id=?";
            Object[] params = {01};
            Connection conn = JDBCUtilsConfig.getConnection();
            Student zw = qr.query(conn, sql, new BeanHandler<Student>(Student.class), params);
            //结果集处理
            System.out.println(zw);
            conn.close();
        } catch(SQLException e){
            throw new RuntimeException(e);
        }
    }
    //BeanListHandler:将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中
    public static void method4(){
        try{
            //获取QueryRunner
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "SELECT * FROM Student WHERE s_name = ?;";
            Object[] params = {"老王"};
            Connection conn = JDBCUtilsConfig.getConnection();
            List<Student> list = qr.query(conn, sql, new BeanListHandler<Student>(Student.class), params);
            //结果集处理
            for (Student zw : list) {
                System.out.println(zw);
            }

            conn.close();
        } catch(SQLException e){
            throw new RuntimeException(e);
        }
    }
    //ColumnListHandler:将结果集中指定的列的字段值,封装到一个List集合中
    public static void method5(){
        try {
            //获取QueryRunner对象
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "SELECT s_name FROM Student;";
            Connection conn = JDBCUtilsConfig.getConnection();
            List<String> list = qr.query(conn, sql, new ColumnListHandler<String>());
            //结果集的处理
            for (String str : list) {
                System.out.println(str);
            }

            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //ScalarHandler:它是用于单数据。例如select count(*) from 表操作。
    public static void method6(){
        try {
            //获取QueryRunner对象
            QueryRunner qr = new QueryRunner();

            //执行SQL语句
            String sql = "SELECT COUNT(s_name) FROM Student;";
            Object[] params = {};
            Connection conn = JDBCUtilsConfig.getConnection();
            Long count = qr.query(conn, sql, new ScalarHandler<Long>(), params);
            //结果集的处理
            System.out.println("count=" + count);

            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //MapHandler    将结果集第一行封装到Map集合中,Key 列名, Value 该列数据
    public static void method7(){
        try {
            //获取QueryRunner对象
            QueryRunner qr = new QueryRunner();

            //执行SQL语句
            String sql = "SELECT * FROM Student;";
            Object[] params = {};
            Connection conn = JDBCUtilsConfig.getConnection();
            //返回值Map集合
            Map<String,Object> map = qr.query(conn, sql, new MapHandler());
            //结果集的处理
            for(String key:map.keySet()){
                System.out.println(key+"..."+map.get(key));
            }

            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //MapListHandler    将结果集第一行封装到Map集合中,Key 列名, Value 该列数据,Map集合存储到List集合
    public static void method8(){
        try {
            //获取QueryRunner对象
            QueryRunner qr = new QueryRunner();

            //执行SQL语句
            String sql = "SELECT * FROM Student;";
            Object[] params = {};
            Connection conn = JDBCUtilsConfig.getConnection();
            //返回值Map集合
            List<Map<String,Object>> list = qr.query(conn, sql, new MapListHandler());
            //结果集的处理
            for(Map<String,Object> map:list){
                for(String key:map.keySet()){
                    System.out.println(key+"..."+map.get(key));
                }
            }

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

4 连接池

  实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程,为了解决此类性能问题,通常情况我们采用连接池技术,来共享连接Connection。这样我们就不需要每次都创建连接、释放连接了,这些操作都交给了连接池

4.1 连接池概述

1. 概念
  用池来管理Connection,这样可以重复使用Connection。有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。池就可以再利用这个Connection对象了。

2. 规范
  Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!
常见的连接池:DBCP、C3P0。
3. 常见配置

分类 属性 描述
必须项 driverClassName 数据库驱动名称
必须项 url 数据库的地址
必须项 username 用户名
必须项 password 密码
基本项(扩展) maxActive 最大连接数量
基本项(扩展) minIdle 最小空闲连接
基本项(扩展) maxIdle 最大空闲连接
基本项(扩展) initialSize 初始化连接

4.2 DBCP连接池

  DBCP也是一个开源的连接池,是Apache Common成员之一,在企业开发中也比较常见,tomcat内置的连接池。
导入jar包

4.3 编写工具类

JDBCUtils.java

package com.qtw.api;

import org.apache.commons.dbcp.BasicDataSource;

import javax.sql.DataSource;

/*
* 使用DBCP实现数据库的连接池
* 连接池配置,自定义类
* 最基本四项配置
* 对于数据库连接池的其他配置,自定义
* */
public class JDBCUtils {
    //创建BasicDataSource类对象
    private static BasicDataSource datasource = new BasicDataSource();

    //静态代码快,对象BasicDataSource对象中的配置,自定义
    static {
        datasource.setDriverClassName("com.mysql.jdbc.Driver");
        datasource.setUrl("jdbc:mysql://192.168.134.66:3306/Train");
        datasource.setUsername("root");
        datasource.setPassword("root123");
        //对象连接池的连接数量配置。可选的
        datasource.setInitialSize(10); //初始化的连接
        datasource.setMaxActive(8);    //最大连接数量
        datasource.setMaxIdle(5);      //最大空闲数
        datasource.setMinIdle(1);      //最小空闲数
    }

    //定义静态方法,返回BasicDataSource类的对象
    public static DataSource getDataSource(){
        return datasource;
    }
}

4.4 测试

TestDemo.java

package com.qtw.api;
/*
* 测试写好的工具类
* 提供是一个DataSource接口的数据源
* QueryRunner类构造方法,接收DataSource接口的实现类
* 后面,调用update,query,无需传递他们Connection连接对象
*
* */

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayListHandler;

import java.sql.SQLException;
import java.util.List;

public class TestDemo {
    public static void main(String[] args) throws Exception{
        //insert();
        select();
    }

    //定义2个方法,实现数据表的添加,数据表的查询
    //QueryRunner类对象
    private static QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());

    //数据表插入数据
    public static void insert(){
        String sql = "INSERT INTO Student(s_id,s_name,s_birth,s_sex) VALUES (?,?,?,?);";
        Object[] params = {"11","小王","2019-11-02","男"};
        try{
            int row = qr.update(sql,params);
        }catch (SQLException ex){
            System.out.println(ex);
            throw new RuntimeException("数据添加失败");
        }
    }

    public static void select(){
        String sql = "SELECT * FROM Student";
        try {
            List<Object[]> list = qr.query(sql, new ArrayListHandler());
            for(Object[] objs:list){
                for(Object obj:objs){
                    System.out.println(obj+"\t");
                }
            }

        }catch (SQLException ex){
            System.out.println(ex);
            throw new RuntimeException("查询失败");
        }
    }
}

相关文章

  • java学习路线

    javaSE java基础语法 java文件操作 java网络操作 java多线程 java数据库操作 java ...

  • JDBC

    直接用Java对数据库进行操作 JDBC(Java DataBase Connectivity,java数据库连接...

  • JDBC学习笔记(一)

    JDBC:Java Database Connectivity,即java数据库连接,用java语言操作数据库。 ...

  • JDBC

    概念∶Java DataBase Connectivity Java 数据库连接, Java语言操作数据库。JDB...

  • JDBC基础

    概念 Java Database Connectivity Java数据库链连接,Java语言操作数据库 JDBC...

  • 连接数据库(JDBC)

    JDBC:Java DataBase Connection Java数据库连接,用来操作关系型数据库。 连接数据库...

  • 1.4JDBC

    JDBC 1.概念:Java Database Connectivity Java数据库连接,Java语言操作...

  • JDBC1

    JDBC介绍 java data base connectivity, java数据库连接java通过该标准去操作...

  • JavaWeb——JDBC

    1.概念: Java DataBase Connectivity Java 数据库连接,Java 语言操作数据...

  • 【JAVA基础】JAVA 连接数据库

    为什么要连接数据库 JAVA如何去连接,操作数据库*. JDBC Java Database Connecti...

网友评论

      本文标题:Java 操作数据库

      本文链接:https://www.haomeiwen.com/subject/znehwctx.html