复习1:数据库以及JDBC复习

本文是对数据库和JDBC的复习,主要包括面试常问问题,如SQL分类、分组查询中having和where的区别、三大范式特点、事务特性以及JDBC的本质。此外,还涉及多表查询、JDBC操作数据库的学习思路,从基础的JDBC使用到连接池技术如C3P0和Druid,以及Spring JDBC的介绍。
摘要由CSDN通过智能技术生成

这段时间一直都是在学习javaEE的相关内容,一直都是边听课边操作,一直听到了后面会话的内容了,但是前面的一些知识由于内容过多所以很多都忘记了。在这里分几次进行复习,第一次先复习数据库的先关内容。在这里主要不是将所有的知识点都囊括进来,而是将上课老师提到的面试题以及一些经典例题以及老师上课的一些思路进行一些整体,方便之后能够对照着代码进行反复学习。

1.面试题:

1. 什么是SQL?

答:Structured Query Language:结构化查询语言
其实就是定义了操作所有关系型数据库的规则。每一种数据库操作的方式存在不一样的地方,称为“方言”。

2. SQL分类

DDL(Data Definition Language)
数据定义语言
用来定义数据库对象:数据库,表,列等。关键字:create, drop,alter 等
DML(Data Manipulation Language)
数据操作语言
用来对数据库中表的数据进行增删改。关键字:insert, delete, update 等
DQL(Data Query Language)
数据查询语言
用来查询数据库中表的记录(数据)。关键字:select, where 等
DCL(Data Control Language)
数据控制语言(了解)
用来定义数据库的访问权限和安全级别,及创建用户。关键字:GRANT, REVOKE 等

3. 分组查询中having和where的区别

1)where 在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不满足结果,则不会被查询出来
eg:

SELECT 
sex , AVG(math),COUNT(id) 
FROM 
student WHERE math > 70 
GROUP BY 
sex 
HAVING 
COUNT(id) > 2;

2) where 后不可以跟聚合函数,having可以进行聚合函数的判断。

4. 三大范式各自的特点:

1)第一范式(1NF):每一列都是不可分割的原子数据项
2)第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的部分函数依赖)
3)第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)
5. 多表查询的分类
1)内连接查询:

  • 隐式内连接:使用逗号和where条件消除无用数据
    eg:
-- 查询员工表的名称,性别。部门表的名称
				SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
				
				SELECT 
					t1.name, -- 员工表的姓名
					t1.gender,-- 员工表的性别
					t2.name -- 部门表的名称
				FROM
					emp t1,
					dept t2
				WHERE 
					t1.`dept_id` = t2.`id`;
  • 显式内连接:
* 语法: select 字段列表 from 表名1 [inner] join 表名2 on 条件
* 例如:
	* SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;	
	* SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;

2)外连接查询

  • 左外链接:查询的是左表所有数据以及其交集部分
-- 查询所有员工信息,如果员工有部门,则查询部门名称,没有部门,则不显示部门名称
SELECT 	
t1.*,t2.`name` 
FROM 
emp t1 
LEFT JOIN 
dept t2 
ON 
t1.`dept_id` = t2.`id`;
  • 右外连接:查询的是右表所有数据以及其交集部分。
SELECT 	* FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;

5.事务的四大特征:

  1. 原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。
  2. 持久性:当事务提交或回滚后,数据库会持久化的保存数据。
  3. 隔离性:多个事务之间。相互独立。
  4. 一致性:事务操作前后,数据总量不变

6.JDBC的本质

官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

2.练习题

1. 这里为了体现一对一、一对多、多对多的关系,采用了一个旅游网站来作为数据库例子。
1)一个旅游类别中有多个旅游种类:
在这里插入图片描述

--创建一张种类表
CREATE TABLE tab_category(
cid INT PRIMARY KEY AUTO_INCREMENT,
cname VARCHAR(100) NOT NULL UNIQUE
);
INSERT INTO tab_category(cname) VALUES ('周边游'),('出境游'),('国内游'),('港澳游');
SELECT * FROM tab_category;

DROP TABLE tab_category;
DROP TABLE tab_route;
--创建一张线路表
CREATE TABLE tab_route(
rid INT PRIMARY KEY AUTO_INCREMENT,
rname VARCHAR(100) NOT NULL UNIQUE,
price DOUBLE,
rdate DATE,
cid INT,
FOREIGN KEY (cid) REFERENCES tab_category(cid)
);
INSERT INTO tab_route VALUES
(NULL, '【厦门+鼓浪屿+南普陀寺+曾厝垵 高铁 3 天 惠贵团】尝味友鸭面线 住 1 晚鼓浪屿', 1499,'2018-01-27', 1),
(NULL, '【浪漫桂林 阳朔西街高铁 3 天纯玩 高级团】城徽象鼻山 兴坪漓江 西山公园', 699, '2018-02-22', 3),
(NULL, '【爆款¥1699 秒杀】泰国 曼谷 芭堤雅 金沙岛 杜拉拉水上市场 双飞六天【含送签费 泰风情 广州往返 特价团】', 1699, '2018-01-27', 2),
(NULL, '【经典•狮航 ¥2399 秒杀】巴厘岛双飞五天 抵玩【广州往返 特价团】', 2399, '2017-12-23',2),
(NULL, '香港迪士尼乐园自由行 2 天【永东跨境巴士广东至迪士尼去程交通+迪士尼一日门票+香港如心海景酒店暨会议中心标准房 1 晚住宿】', 799, '2018-04-10', 4);
SELECT * FROM tab_route;

2)一个用户可以收藏多条线路,一条线路也可以被多个用户收藏,这就是多对多的关系,这个时候就需要一张中间表了
在这里插入图片描述

-- 创建用户表
CREATE TABLE tab_user(
uid INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(100) UNIQUE NOT NULL,
PASSWORD VARCHAR(30) NOT NULL,
NAME VARCHAR(100),
birthday DATE,
sex CHAR(1) DEFAULT '男',
telephone VARCHAR(11),
email VARCHAR(100)
);
INSERT INTO tab_user VALUES
(NULL, 'cz110', 123456, '老王', '1977-07-07', '男', '13888888888', '66666@qq.com'),
(NULL, 'cz119', 654321, '小王', '1999-09-09', '男', '13999999999', '99999@qq.com');
SELECT * FROM tab_user;

CREATE TABLE tab_favorite(
rid INT,
DATE DATETIME,
uid INT,
-- 创建复合主键
PRIMARY KEY(rid,uid),
FOREIGN KEY (rid) REFERENCES tab_route(rid),
FOREIGN KEY(uid) REFERENCES tab_user(uid)
);

INSERT INTO tab_favorite VALUES 
(1, '2018-01-01', 1), -- 老王选择厦门
(2, '2018-02-11', 1), -- 老王选择桂林
(3, '2018-03-21', 1), -- 老王选择泰国
(2, '2018-04-21', 2), -- 小王选择桂林
(3, '2018-05-08', 2), -- 小王选择泰国
(5, '2018-06-02', 2); -- 小王选择迪士尼
SELECT * FROM tab_favorite;

2. 多表查询练习
采用如下sql语句创建如下图所示的四张表,请完成以下查询需求

-- 部门表
CREATE TABLE dept (
  id INT PRIMARY KEY PRIMARY KEY, -- 部门id
  dname VARCHAR(50), -- 部门名称
  loc VARCHAR(50) -- 部门所在地
);

-- 添加4个部门
INSERT INTO dept(id,dname,loc) VALUES 
(10,'教研部','北京'),
(20,'学工部','上海'),
(30,'销售部','广州'),
(40,'财务部','深圳');



-- 职务表,职务名称,职务描述
CREATE TABLE job (
  id INT PRIMARY KEY,
  jname VARCHAR(20),
  description VARCHAR(50)
);

-- 添加4个职务
INSERT INTO job (id, jname, description) VALUES
(1, '董事长', '管理整个公司,接单'),
(2, '经理', '管理部门员工'),
(3, '销售员', '向客人推销产品'),
(4, '文员', '使用办公软件');



-- 员工表
CREATE TABLE emp (
  id INT PRIMARY KEY, -- 员工id
  ename VARCHAR(50), -- 员工姓名
  job_id INT, -- 职务id
  mgr INT , -- 上级领导
  joindate DATE, -- 入职日期
  salary DECIMAL(7,2), -- 工资
  bonus DECIMAL(7,2), -- 奖金
  dept_id INT, -- 所在部门编号
  CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
  CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
);

-- 添加员工
INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES 
(1001,'孙悟空',4,1004,'2000-12-17','8000.00',NULL,20),
(1002,'卢俊义',3,1006,'2001-02-20','16000.00','3000.00',30),
(1003,'林冲',3,1006,'2001-02-22','12500.00','5000.00',30),
(1004,'唐僧',2,1009,'2001-04-02','29750.00',NULL,20),
(1005,'李逵',4,1006,'2001-09-28','12500.00','14000.00',30),
(1006,'宋江',2,1009,'2001-05-01','28500.00',NULL,30),
(1007,'刘备',2,1009,'2001-09-01','24500.00',NULL,10),
(1008,'猪八戒',4,1004,'2007-04-19','30000.00',NULL,20),
(1009,'罗贯中',1,NULL,'2001-11-17','50000.00',NULL,10),
(1010,'吴用',3,1006,'2001-09-08','15000.00','0.00',30),
(1011,'沙僧',4,1004,'2007-05-23','11000.00',NULL,20),
(1012,'李逵',4,1006,'2001-12-03','9500.00',NULL,30),
(1013,'小白龙',4,1004,'2001-12-03','30000.00',NULL,20),
(1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10);



-- 工资等级表
CREATE TABLE salarygrade (
  grade INT PRIMARY KEY,   -- 级别
  losalary INT,  -- 最低工资
  hisalary INT -- 最高工资
);

-- 添加5个工资等级
INSERT INTO salarygrade(grade,losalary,hisalary) VALUES 
(1,7000,12000),
(2,12010,14000),
(3,14010,20000),
(4,20010,30000),
(5,30010,99990);

SELECT * FROM emp;
SELECT * FROM salarygrade;
SELECT * FROM dept;
SELECT * FROM job;

职员表:
在这里插入图片描述
部门表:
在这里插入图片描述
职位表:
在这里插入图片描述
工资等级表:
在这里插入图片描述
几张表之间的关系如图所示:
在这里插入图片描述

1)查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述

USE exercises;
-- 查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述
SELECT 
	t1.`id`, -- 员工编号
	t1.`ename`, -- 员工姓名
	t1.`salary`,-- 工资
	t2.`jname`, -- 职务名称
	t2.`description` -- 职务描述
FROM
	emp t1,job t2
WHERE 
	t1.`job_id`=t2.`id`

结果如下图:
在这里插入图片描述

注意:先把emp t1,job t2给写出来,然后后面打出t1然后再打出’.'就能直接获取相关的列名,不用再自己手敲了。

2)查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置

SELECT
	t1.`id`, -- 员工编号
	t1.`ename`, -- 员工姓名
	t1.`salary`,-- 工资
	t2.`jname`, -- 职务名称
	t2.`description`, -- 职务描述
	t3.`dname`, -- 部门名称
	t3.`loc` -- 部门位置
FROM
	emp t1,job t2,dept t3
WHERE
	t1.`dept_id`=t3.`id` AND t1.`job_id`=t2.`id`;

在这里插入图片描述
3)查询员工姓名,工资,工资等级

SELECT 
	t1.ename ,
	t1.`salary`,
	t2.`grade`
FROM emp t1, salarygrade t2
WHERE t1.`salary` BETWEEN t2.`losalary` AND t2.`hisalary`;

在这里插入图片描述
4)查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级

SELECT
	t1.`ename`,
	t1.`salary`,
	t3.`jname`,
	t3.`description`,
	t2.`dname`,
	t2.`loc`,
	t4.`grade`
FROM 
	emp t1, dept t2, job t3, salarygrade t4
WHERE
	t1.`dept_id`=t2.`id`	
AND 
	t1.`job_id`=t3.`id`
AND
	t1.`salary` BETWEEN t4.`losalary` AND t4.`hisalary`;

在这里插入图片描述
5).查询出部门编号、部门名称、部门位置、部门人数
这里就需要我们采用分组查询产生一个新表,然后再进行一个多表查询

SELECT 
	t1.`id`,t1.`dname`,t1.`loc`, t2.total
FROM
	dept t1,(SELECT dept_id, COUNT(id) total FROM emp GROUP BY dept_id) t2
WHERE
	t1.`id`= t2.dept_id;

在这里插入图片描述
6)查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询
这个时候我们就通过外连接的方法进行查询

SELECT 
	t1.ename,
	t2.`ename`
FROM emp t1
LEFT JOIN emp t2
ON t1.`mgr` = t2.`id`;

在这里插入图片描述
3. 这里主要介绍的是JDBC的一个学习思路,从一开始不依靠任何框架直接采用java.sql包中的方法来创建对象到后来用Spring JDBC来进行一个JDBC相关程序的编写。
首先,一开始,我们就是直接采用驱动管理对象创建连接,再由连接对象获取执行sql 的对象,再依靠执行sql 的对象执行sql语句,最后释放资源。

  1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
    * 复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
    * 右键–>Add As Library
  2. 注册驱动(可以在逻辑上可以省略,因为相当于自动给你做了)
  3. 获取数据库连接对象 Connection
  4. 定义sql
  5. 获取执行sql语句的对象 Statement
  6. 执行sql,接受返回结果
  7. 处理结果
  8. 释放资源
package cn.itcast.jdbc;

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

public class JdbcDemo2 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String sql = "insert into account values(null,'王五',3000)";
            //获取连接对象
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db4","root","root");
            //获取执行对象
            stmt = conn.createStatement();
            int count = stmt.executeUpdate(sql);
            System.out.println(count);
            if(count>0){
                System.out.println("添加成功");
            }else{
                System.out.println("添加失败");
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally {//释放资源
            if (stmt != null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

接着由于我们这整个过程中存在很多重复的操作,所以我们可以自己抽象出一个工具包,然后直接调用工具包中的方法来完成这些步骤,我们同时采用一个配置文件来将一些我们常用的参数比如数据库用户名和密码,数据库名称直接写在上面
工具类中需要存在获取连接、关闭资源、注册驱动这些个方法:

package cn.itcast.util;

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {
    private static String url;
    private static String user;
    private static String password;
    private static String driver;
    static {
        try {
            //1.创建Properties集合类
            Properties pro = new Properties();
//            //获取src路径下的文件的方式--->ClassLoader类记载器
//            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
//            URL re = classLoader.getResource("jdbc.properties");
//            String path = re.getPath();
//            System.out.println(path);
//            //2.加载文件
//            pro.load(new FileReader(path));
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"));
            //3.获取数据,赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //4.注册驱动
            Class.forName(driver);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
        /*获取连接*/

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

以下是findAll是直接来写的程序,findAll2是利用这个工具类来编写的JDBC程序:

package cn.itcast.jdbc;

import cn.itcast.domain.Emp;
import cn.itcast.util.JDBCUtils;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JDBCDemo8 {
    public static void main(String[] args) {
        List<Emp> list = new JDBCDemo8().findAll2();
        System.out.println(list);
    }
    public List<Emp> findAll(){
        Connection conn = null;
        Statement stat = null;
        ResultSet res = null;
        List<Emp> list = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
            String sql = "select * from emp";
            stat = conn.createStatement();
            res = stat.executeQuery(sql);
            Emp emp = null;
            list = new ArrayList();
            while(res.next()){
                int id = res.getInt(1);
                String ename = res.getString("ename");
                int job_id = res.getInt("job_id");
                int mgr = res.getInt("mgr");
                Date join_date = res.getDate("joindate");
                double salary = res.getDouble("salary");
                double bonus = res.getDouble("bonus");
                int dept_id = res.getInt("dept_id");

                emp = new Emp();
                emp.setId(id);
                emp.setEname(ename);
                emp.setJob_id(job_id);
                emp.setMgr(mgr);
                emp.setJoindate(join_date);
                emp.setSalary(salary);
                emp.setBonus(bonus);
                emp.setDept_id(dept_id);
                list.add(emp);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if (res != null){
                try {
                    res.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }if (stat != null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }if (conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return list;
    }
    //用于测试工具类
    public List<Emp> findAll2(){
        Connection conn = null;
        Statement stat = null;
        ResultSet res = null;
        List<Emp> list = null;
        try {
            conn = JDBCUtils.getConnection();
            String sql = "select * from emp";
            stat = conn.createStatement();
            res = stat.executeQuery(sql);
            Emp emp = null;
            list = new ArrayList();
            while(res.next()){
                int id = res.getInt(1);
                String ename = res.getString("ename");
                int job_id = res.getInt("job_id");
                int mgr = res.getInt("mgr");
                Date join_date = res.getDate("joindate");
                double salary = res.getDouble("salary");
                double bonus = res.getDouble("bonus");
                int dept_id = res.getInt("dept_id");

                emp = new Emp();
                emp.setId(id);
                emp.setEname(ename);
                emp.setJob_id(job_id);
                emp.setMgr(mgr);
                emp.setJoindate(join_date);
                emp.setSalary(salary);
                emp.setBonus(bonus);
                emp.setDept_id(dept_id);
                list.add(emp);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(res, stat, conn);
        }
        return list;
    }
}

同时需要强调的是,以上写法是一个典型的查找的写法,我们可以把一个表的表头当做是一个类的各种属性,然后每一个行查找到的值相当于一个对象,所以可以通过创建一个类并写好set、get、toString方法来进行查找程序的具体编写。

**4.**使用JDBC做一个登录的功能,注意看这里采用了PreparedStatement这个类,是为了防sql注入攻击的。

package cn.itcast.jdbc;

import cn.itcast.util.JDBCUtils;

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

public class JDBCDemo9 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = sc.nextLine();
        System.out.println("请输入密码:");
        String password = sc.nextLine();
        //2.调用方法
        Boolean login = new JDBCDemo9().login2(username, password);
        System.out.println(login);
    }
    public boolean login(String username, String password){
        if(username == null || password == null){
            return false;
        }
        Connection conn = null;
        Statement stat = null;
        ResultSet res = null;
        //1.获取连接
        try {
            conn = JDBCUtils.getConnection();
            //2.定义sql
            String sql = "select * from users where name = '"+username+"' and password = '"+password+"'";
            //3.获取执行sql的对象
            stat = conn.createStatement();
            //4.执行查询
            res = stat.executeQuery(sql);
            //5.判断
            return res.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(res, stat, conn);
        }
        return false;
    }
    public boolean login2(String username, String password){
        if(username == null || password == null){
            return false;
        }
        Connection conn = null;
        PreparedStatement pstat = null;
        ResultSet res = null;
        //1.获取连接
        try {
            conn = JDBCUtils.getConnection();
            //2.定义sql
            String sql = "select * from users where name = ? and password = ?";
            //3.获取执行sql的对象
            pstat = conn.prepareStatement(sql);
            pstat.setString(1, username);
            pstat.setString(2, password);
            //4.执行查询
            res = pstat.executeQuery();
            //5.判断是否找到
            return res.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(res, pstat, conn);
        }
        return false;
    }
}

**5.**这里是接着上面的,上面的每次我们有对数据库进行操作的请求时我们就去申请对象,执行完sql语句后再将其释放,这样每次都要向底层重新申请连接对象,会导致时间的浪费,效率的降低。就好比一个餐馆,每次来客人时现招一批服务员,伺候完客人之后再将其解雇,就是三和的日结工。但是我们需要的是雇一批固定的员工,每次服务完之后能够接着服务下一批客人。这就是连接池的思想。所以接下来课程介绍了两种连接池技术:C3P0、druid,但是重点介绍的是druid。
druid的还是依靠加载配置文件来进行数据库连接池对象的获取的,但是,这里就不必通过getProperty来一个个依靠键来获取值了,而是直接采用工厂类DruidDataSourceFactory来实现对对象的创建,创建后连接对象,如下:

package cn.itcast.datasorce.druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileReader;
import java.io.InputStream;
import java.net.URL;
import java.sql.Connection;
import java.util.Properties;

public class DruidDemo1 {
    public static void main(String[] args) throws Exception {
        //1.导入jar包
        //2.定义配置文件
        //3.加载配置文件
        //1.创建Properties集合类
        Properties pro = new Properties();
        InputStream is = DruidDemo1.class.getClassLoader().getResourceAsStream("druid.properties");
        pro.load(is);
        //通过工厂类来创建datasource
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);
        Connection conn = ds.getConnection();
        System.out.println(conn);
    }
}

既然我们清楚了druid的工作原理,所以我们还是写一个工具类来将这些方法给抽象出来,需要包含获取数据库连接池对象的方法、获取连接的方法、关闭连接的方法。

package cn.itcast.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtils {
    //1.定义成员变量DataSource
    private static DataSource ds;
    static{
        try {
            //1.加载配置文件
            Properties pro = new Properties();
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //2.获取DataSource
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //2.获取连接
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
    //3.释放资源
    public static void close(ResultSet res, Statement stat, Connection conn){
        if(res != null){
            try {
                res.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }if(stat != null){
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close(Statement stat, Connection conn){
        close(null,stat,conn);
    }
    public static DataSource getDataSource(){
        return ds;
    }
}

以下是采用工具类实现的一个JDBC程序:

package cn.itcast.datasorce.druid;

import cn.itcast.utils.JDBCUtils;

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

public class DruidDemo2 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstat = null;
        try {
            //1.获取连接
            conn= JDBCUtils.getConnection();
            //2.定义sql
            String sql = "insert into account values(null,?,?)";
            //3.获取stat对象
            pstat = conn.prepareStatement(sql);
            //4.给?赋值
            pstat.setString(1,"张三");
            pstat.setDouble(2,9999999);
            int count = pstat.executeUpdate();
            System.out.println(count);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(pstat,conn);
        }
    }
}

由于我们采用前面的方法,虽然已经对程序进行了很大程度的缩减,但是仍然有很多异常要去抓,需要提前创建对象变量。这就很繁琐。于是就引入了Spring JDBC,它对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发。其步骤为:

  1. 导入jar包

  2. 创建JdbcTemplate对象。依赖于数据源DataSource
    * JdbcTemplate template = new JdbcTemplate(ds);

  3. 调用JdbcTemplate的方法来完成CRUD的操作

* update():执行DML语句。增、删、改语句
* queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合
	* 注意:这个方法查询的结果集长度只能是1
* queryForList():查询结果将结果集封装为list集合
	* 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
* query():查询结果,将结果封装为JavaBean对象
	* query的参数:RowMapper
		* 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
		* new BeanPropertyRowMapper<类型>(类型.class)
* queryForObject():查询结果,将结果封装为对象
	* 一般用于聚合函数的查询

具体可以看一个程序:

package cn.itcast.jdbctemplate;

import cn.itcast.utils.JDBCUtils;
import org.springframework.jdbc.core.JdbcTemplate;

public class TemplateDemo1 {
    public static void main(String[] args) {
        //1.导入jar包
        //2.创建JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        //3.调用方法
        String sql = "update account set balance = 5000 where id = ?";
        //注意这里括号后面是按照先后顺序跟sql语句中的查询参数
        int count = template.update(sql, 3);
        System.out.println(count);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值