全站资源开放下载,感谢广大网友的支持
链接失效请移步职涯宝平台的学习路线|资源下载分类
支持用户留言评论_客服实时在线_问题解决更快

第二十七天 数据库基础&JDBC使用&工具类Properties&连接池&DBUtils【悟空教程】

140
发表时间:2018-09-06 16:39

第二十七天 数据库基础&JDBC使用&工具类Properties&连接池&DBUtils【悟空教程】


第27天 数据库基础&JDBC使用&工具类Properties&连接池&DBUtils

第1章 数据库

1.1 数据库概述

1.1.1 数据库(数据库管理系统):

数据库就是存储数据的仓库,其本质是一个文件系统,数据库按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作。

常见的数据库

MySQL:开源免费的数据库,小型的数据库.已经被Oracle收购了.MySQL6.x版本也开始收费。

Oracle:收费的大型数据库,Oracle公司的产品。Oracle收购SUN公司,收购MYSQL。

DB2:IBM公司的数据库产品,收费的。常应用在银行系统中.

SQLServer:MicroSoft 公司收费的中型的数据库。C#、.net等语言常使用。

SyBase:已经淡出历史舞台。提供了一个非常专业数据建模的工具PowerDesigner。

SQLite:嵌入式的小型数据库,应用在手机端。

Java常用的数据库:MySQL,Oracle。

这里使用MySQL数据库。


1.1.2 数据库

MySQL中可以有多个数据库,数据库是真正存储数据的地方。

1.1.3 数据库与数据库管理系统的关系

1.1.4

数据库中以表为组织单位存储数据。

表类似我们的Java类,每个字段都有对应的数据类型。

那么用我们熟悉的java程序来与关系型数据对比,就会发现以下对应关系。

类----------表

类中属性----------表中字段

对象----------记录

1.1.5 表数据

根据表字段所规定的数据类型,我们可以向其中填入一条条的数据,而表中的每条数据类似类的实例对象。表中的一行一行的信息我们称之为记录。


财务表


用户表


进而有类似如下的对应关系:


1.1.6 SQL语句

数据库是不认识JAVA语言的,但是我们同样要与数据库交互,这时需要使用到数据库认识的语言SQL语句,它是数据库的代码。

结构化查询语言(Structured Query Language)简称SQL,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。

创建数据库、创建数据表、向数据表中添加一条条数据信息均需要使用SQL语句。


1.2 MySql使用

  • 安装

官网下载安装文档:www.javahelp.com.cn

安装后,MySQL会以windows服务的方式为我们提供数据存储功能。开启和关闭服务的操作:右键点击我的电脑→管理→服务→可以找到MySQL服务开启或关闭

  • 登录

MySQL是一个需要账户名密码登录的数据库,登陆后使用,它提供了一个默认的root账号,使用安装时设置的密码即可登录。

格式:cmd>  mysql –u用户名 –p

           密码

例如:mysql -uroot –p

           密码


1.3 SQLyog 安装与使用


输入用户名、密码,点击连接按钮,进行访问MySQL数据库进行操作

在Query窗口中,输入SQL代码,选中要执行的SQL代码,按F8键运行,或按执行按钮运行。


1.4 SQL语句句法

1.4.1 SQL分类

  • 数据定义语言:简称DDL(Data Definition Language),用来定义数据库对象:数据库,表,列等。关键字:create,alter,drop等

  • 数据操作语言:简称DML(Data Manipulation Language),用来对数据库中表的记录进行修改。关键字:insert,delete,update等

  • 数据控制语言:简称DCL(Data Control Language),用来定义数据库的访问权限和安全级别,及创建用户。

  • 数据查询语言:简称DQL(Data Query Language),用来查询数据库中表的记录。关键字:select等


1.4.2 SQL通用语法

  • SQL语句可以单行或多行书写,以分号结尾

  • 可使用空格和缩进来增强语句的可读性

  • MySQL数据库的SQL语句不区分大小写,建议使用大写,例如:SELECT * FROM user。

  • 同样可以使用/**/的方式完成注释

  • MySQL中的我们使用的数据类型


详详细的数据类型(不建议详细阅读!)

a) 数据库相关语句

create database 数据库名;           创建数据库

show databases;                          查看数据库

show create database 数据库名;  查看建库语句

drop database 数据库名;              删除数据库

use 数据库名;                                使用指定数据库


b) 表结构相关语句

  • 建表语句:

create table 表名(

字段1 类型,

字段2 类型,

...

)

  • 主键约束:

主键是用于标识当前记录的字段。它的特点是非空,唯一。  

在开发中一般情况下主键是不具备任何含义,只是用于标识当前记录。

1.在创建表时创建主键,在字段后面加上  primary key.

create table tablename(      

id int primary key,

.......

)

2. 在创建表时创建主键,在表创建的最后来指定主键        

create table tablename(      

id int,

.......,

primary key(id)

)


3.删除主键:alter table 表名 drop primary key ;

4.主键自动增长:一般主键是自增长的字段,不需要指定。

添加自增长语句   主键字段后加auto_increment(只适用MySQL)

其他约束:其他约束还有如外键、唯一、非空等基础加强中详解


  • 查看表:

desc 表名;                         查看某个现有表的结构

show tables;                     查看当前数据库下所有的表

show create table 表名;    查看建表语句

  • 修改/删除表:

rename table 旧表名 to 新表名        修改表名

alter table 表名 add 列名 类型;        添加列操作

alter table 表名 modify 列名 类型;   修改列类型

alter table 表名 drop 列名;              删除列

alter table 表名 change 旧列名 新列名 类型;    修改列名称

drop table 表名;                              删除表

truncate 表名;                                 摧毁表(删除表)


c) 表数据相关语句

  • 插入数据

insert into 表名(列名1,列名2, ...) values(列值1, 列值2, ...); 指定列插入

insert into 表名 values(列值1, 列值2, ...);  不指定列插入(所有列)

注意:

插入的数据应与字段的数据类型相同

数据的大小应该在列的长度范围内

在values中列出的数据位置必须与被加入列的排列位置相对应。

除了数值类型外,其它的字段类型的值必须使用 单引号引起。

如果要插入空值,可以不写字段,或者插入 null。  

对于自动增长的列在操作时,直接插入null值即可。


  • 更新(修改)数据

update 表名 set 字段=值 ,... where 条件    修改指定条件的数据,将这条数据的指定列修改为指定值

  • 删除数据

delete from 表名 where 条件   删除指定条件的数据

delete from 表名       删除表内所有数据

truncate table 表名   摧毁表再重新创建表,达到删除表内所有数据

  • 查询语句

select 字段1,字段2,...from 表名;  查询指定字段信息        

select * from 表名;      查询表中所有字段

注意:使用"*"在练习,学习过程中可以使用,在实际开发中,不建议使用。

select distinct 字段 from 表名;   distinct用于去除重复

使用as 别名可以给表中的字段,表设置别名. 当查询语句复杂时,使用别名可以极大的简便操作。

select 字段 as 别名,字段 AS 别名 from 表名;

我们在sql操作中,可以直接对列进行运算。

  • where子句

where语句表条件过滤。满足条件操作,不满足不操作,多用于数据的查询与修改。

格式 :

select 字段  from 表名  where 条件;

select 字段 from 表名 where  name=’香蕉’;

select 字段 from 表名 where  price<5;

select 字段 from 表名 where  name>5’;


    • where条件种类:    

1.比较运算符

> >= < <= = !=(<>)

2.逻辑运算符

And(并且)  or (或者)  not(取反)      

3.between ...and...

在指定范围内    

注意:between 后面的值必须是小值 and后面的是大值

4.in

可以比较多个值      

5.like

模糊查询


通配符使用:

1.% 匹配多个

2._ 匹配一个

select 字段 from 表名 where 字段 like ‘%果’;   #任意个字符+果,以果结尾

select 字段 from 表名 where 字段 like ‘果%’;  #果+任意个字符,以果开头

select 字段 from 表名 where 字段 like ‘%果%’;  #包含果

select 字段 from 表名 where 字段 like ‘_果’;   #某果

select 字段 from 表名 where 字段 like ‘_果_’;  #某果某

6.null值操作

is null; 判断为空

is not null; 判断不为空

查询例句如下:

查询所有支出记录

SELECT * FROM gjp_ledger WHERE parent = '支出';

查询出金额价格大于1000的信息

SELECT * FROM gjp_ledger WHERE money >1000;

查询出金额在2000-5000之间的账务信息

SELECT * FROM gjp_ledger WHERE money >=2000 AND money <=5000;

SELECT * FROM gjp_ledger WHERE money BETWEEN 2000 AND 5000;

查询出金额是1000或5000或3500的商品信息

SELECT * FROM gjp_ledger WHERE money =1000 OR money =5000 OR money =3500;

SELECT * FROM gjp_ledger WHERE money IN(1000,5000,3500);

查询出账务的银行有工商银行的账务信息。

SELECT * FROM gjp_ledger WHERE account LIKE "%工商%";

查询出账务描述中是两个字的账务信息

SELECT * FROM gjp_ledger WHERE ldesc LIKE "__";

查询出账务accont不为null账务信息

SELECT * FROM gjp_ledger WHERE account IS NOT NULL;

SELECT * FROM gjp_ledger WHERE NOT account IS NULL;

  • order by子句

order by可以将查询出的结果进行排序。放置在select语句的最后。

ASC 升序 (默认)

DESC 降序

格式:

SELECT * FROM 表名 ORDER BY 字段ASC;

SELECT * FROM 表名 ORDER BY 字段DESC;

SELECT * FROM 表名 ORDER BY 字段DESC LIMIT 3;

查询字段中最贵的3个。(逻辑倒叙排列取三个值)

 

  • 记录操作-聚合函数

之前我们做的查询都是横向查询,它们都是根据条件一行一行的进行判断,而使用聚合函数查询是纵向查询,它是对一列的值进行计算,然后返回一个单一的值;另外聚合函数会忽略空值。

今天我们学习如下五个聚合函数:

count:统计指定列不为NULL的记录行数;

格式:select count(字段) from 表名;

sum:计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;

max:计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;

min:计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;

avg:计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;


格式:

select avg(字段) from 表名;

select avg(字段) as ‘平均价格’ from 表名;


查询例句如下:

统计账务表中共有多少条记录

SELECT COUNT(*) FROM gjp_ledger;

统计账务表中金额大于3000的有多少条记录

SELECT COUNT(*) FROM gjp_ledger WHERE money>3000;

统计有多少收入的账务信息

SELECT SUM(money) FROM gjp_ledger WHERE parent = '收入';

SELECT SUM(IFNULL(money,0)) FROM gjp_ledger WHERE parent = '收入';

统计出记录中支出的平均值

SELECT AVG(money) FROM gjp_ledger where parent = '支出';

统计出商品表中收入的最大与最小值

SELECT MAX(money),MIN(money) FROM gjp_ledger;

SELECT MAX(money),MIN(IFNULL(money,0)) FROM gjp_ledger;

  • 分组查询

分组查询是指使用group by字句对查询信息进行分组,例如:我们要统计出gjp_ledger表中所有分类账务的总数量,这时就需要使用group by 来对gjp_ledger表中的商品根据parent进行分组操作。

分组后我们在对每一组数据进行统计。

格式:

select 分组的字段 ,avg(计算的字段) from 表名 group by 分组的字段;

分组操作中的having子名是用于在分组后对数据进行过滤的,作用类似于where条件。

having与where的区别:    

1.having是在分组后对数据进行过滤.

where是在分组前对数据进行过滤

格式:select 分组的字段 ,avg(计算的字段) from 表名 where 计算的字段>20 group by 分组的字段 having avg(计算的字段)>20;  

逻辑:先确定where语句   然后在确定having语句

 

2.having后面可以使用分组函数(统计函数)

  where后面不可以使用分组函数。


查询例句如下:

对账务分类别统计,求出每一种类账务的总金额

SELECT parent,SUM(money) FROM gjp_ledger GROUP BY parent;

对账务分类别统计,求出每一种类账务的总金额,金额要大于20000才显示

SELECT parent,SUM(money)  FROM gjp_ledger GROUP BY parent HAVING SUM(money)>2000;


1.4.3 DOS操作数据乱码解决

我们在dos命令行操作中文时,会报错

insert into user(username,password) values(‘张三’,’123’);  

ERROR 1366 (HY000): Incorrect string value: '\xD5\xC5\xC8\xFD' for column 'username' at row 1

原因:

因为mysql的客户端编码的问题我们的是utf8,而系统的cmd窗口编码是gbk

解决方案(临时解决方案):

修改mysql客户端编码。

show variables like 'character%'; 查看所有mysql的编码

在图中与客户端有关的编码设置:

client connetion result 和客户端相关

database server system 和服务器端相关


将客户端编码修改为gbk.

set character_set_results=gbk; / set names gbk;

以上操作,只针对当前窗口有效果,如果关闭了服务器便失效。

如果想要永久修改,通过以下方式:

在mysql安装目录下有my.ini文件

default-character-set=gbk 客户端编码设置      

character-set-server=utf8 服务器端编码设置

注意:修改完成配置文件,重启服务


1.5 作业:

1:完成数据库表的创建并插入数据、读取数据

2:完成课上所有SQL练习


第2章 使用JDBC完成分类表增删改查的操作

2.1 JDBC

2.1.1 JDBC概述

JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范

JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。

今天我们使用的是mysql的驱动mysql-connector-java-5.1.37-bin.jar


2.1.2 JDBC原理

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

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


2.1.3 JDBC开发步骤

1. 注册驱动

2. 获得连接

3. 获得语句执行平台

4. 执行sql语句

5. 处理结果

6. 释放资源


2.1.4 导入驱动jar

创建lib目录,用于存放当前项目需要的所有jar包

选择jar包,右键执行build path / Add to Build Path

2.1.5 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!");

}

}

……

}

import java.sql.SQLException;

import com.mysql.jdbc.Driver;

/*

*   注册 驱动 : 加载 Driver 类 就可以注册了. new Driver(),虽然可以加载类完成注册,但是并不好.

*   用反射的方式加载Driver.

*   Class.forName(类名);

*/

public class Demo {

public static void main(String[] args) throws SQLException, ClassNotFoundException {


System.out.println("连接数据库...... ");

Driver driver = new Driver();

//注册驱动

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

System.out.println("注册成功");

}

}


2.1.6 API详解:获得连接

代码:Connection con = DriverManager.getConnection(“jdbc:mysql://localhost:3306/mydb”,”root”,”123”);

获取连接需要方法 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)组成。

2.1.7 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.

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;

/*

*  获取连接

*  DriverManager.getConnection(url, user, password)

*  url : 数据的地址.

*  

*  jdbc:mysql://localhost:3306/mydb

*   jdbc: 写死的.

*   mysql:写死的.(目前)

*   库的地址 :localhost 本机, 3306 数据库端口.  mydb(你指定的库名字)

*  user:数据库管理员用户名(root)

*  password: 就是root 的 密码. (root)

*/

public class Demo2 {

public static void main(String[] args) throws ClassNotFoundException, SQLException {

// 1. 注册驱动

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


String url  = "jdbc:mysql://localhost:3306/bj_230";

String user = "root";

String password  = "root" ;

// 2. 获取连接  

Connection connection = DriverManager.getConnection(url, user, password);

System.out.println(connection); //com.mysql.jdbc.JDBC4Connection@be8464

// 3. 获取 sql 语句的执行者 .

Statement stat  = connection.createStatement();


// 4. 执行 sql

String sql  = "INSERT INTO goods VALUES(3,'草莓',15,'','昌平' )"; // 插入一条记录

int executeUpdate = stat.executeUpdate(sql);


System.out.println("插入记录成功");


//5------------------------------------------

System.out.println(executeUpdate);

// 6. 关闭资源

stat.close();

connection.close();

}

}


2.1.8 API详解:处理结果集

ResultSet实际上就是一张二维的表格,我们可以调用其boolean next()方法指向某行记录,当第一次调用next()方法时,便指向第一行记录的位置,这时就可以使用ResultSet提供的

1.getXXX(int col)方法(与索引从0开始不同个,列从1开始)来获取指定列的数据:

2.getXXX(String columnName)方法,通过列名字获取指定列的数据。

rs.next();//指向第一行

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

常用方法:

  • Object getObject(int col) ,获得任意对象

  • String getString(int col),获得字符串

  • int getInt(int col),获得整形

  • double getDouble(int col),获得双精度浮点型


2.1.9 API详解:释放资源

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

rs.close();

stmt.close();

con.close();

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.Statement;

/*

*  修改一条记录.

*  

*  id 3记录, gname 修改为 桃子 , 产地 修改为平谷, 价格修改为 10.  

*/

public class Test {

public static void main(String[] args) throws Exception {

// 1.注册驱动

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

// 2. 获取连接

String url = "jdbc:mysql://localhost:3306/bj_230";

String user ="root" ;

String password = "root" ;

Connection con = DriverManager.getConnection(url, user, password);

// 3.获取 sql语句执行者

Statement stat  = con.createStatement();

// 4.执行sql executeUpdate()

String sql ="UPDATE goods SET gname='桃子',area='平谷' ,price=10 WHERE id=3";

stat.executeUpdate(sql);

// 5.没有


// 6.释放资源

stat.close();

con.close();

System.out.println("修改成功 ");

}

}


2.1.10 SQL注入问题

案例:

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

SELECT * FROM 用户表

WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码;

此时,当用户输入正确的账号u密码后,查询到了信息则让用户登录。

但是当用户输入的账号为XXX 密码为:XXX’  OR ‘a’=’a时

则真正执行的代码变为:

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

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

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


2.1.11 API详解:预处理对象

使用处理对象时,建议每条sql语句所有的实际参数,都使用逗号分隔。

String sql = "insert into category(cid,cname) values(?,?)";;

PreparedStatement预处理对象代码:PreparedStatement psmt = conn.prepareStatement(sql)

常用方法:

1. 执行SQL语句:

  • int executeUpdate(); --执行insert update delete语句.

  • ResultSet executeQuery(); --执行select语句.

  • boolean execute(); --执行select返回true 执行其他的语句返回false.

2. 设置实际参数

  • setXxxx(int , T) 通过setter方法将?占位符替换成实际参数

  • 例如:setString() 实际参数类型为hi字符串。


2.1.12 案例:查询所有记录信息

public class JDBCTest {

public static void main(String[] args) {

try {

//1,注册驱动

/*

* 加载MySqlDriver类到内存,MySqlDriver类在自己的静态代码块实现注册驱动的操作

* 1.使用类加载器,完成MySqlDriver类的加载

* Class.forName( 要加载的类名 ); //类名为带有包名的完整路径名称

*/

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

//2,获取连接

/*

* 参数1:  要连接的数据库地址 jdbc:mysql://localhost:3306/mydb 最后的mydb为数据库名称,我们可以改变

* 参数2: 连接数据库时 使用的用户名

* 参数3: 连接数据库时 使用的密码

*/

Connection conn = DriverManager.getConnection(

"jdbc:mysql://localhost:3306/day22_JDBC", "root", "root");


//3,获取SQL语句执行者

Statement stat = conn.createStatement();


//4,执行SQL语句

String sql = "SELECT * FROM sort";

ResultSet resultSet = stat.executeQuery(sql);


//5,处理结果集(遍历结果集合)

while( resultSet.next() ){

//获取当前行的分类ID

String sid = resultSet.getString("sid");//方法参数为数据库表中的列名

//获取当前行的分类名称

String sname = resultSet.getString("sname");

//显示数据

System.out.println(sid+"-----"+sname);

}


//6,释放资源

/*

* 释放resultSet

* 释放Statement

* 释放Connection

*/

resultSet.close();

stat.close();

conn.close();


} catch (Exception e) {

e.printStackTrace();

}

}

}


2.2 工具类

“获得连接”将在之后的增删改查所有功能中都存在,可以封装工具类JDBCUtils提供获取连接方法从而达到代码的重复利用。该工具类提供方法:public static Connection getConnection()。


2.2.1 获得连接方法

package cn.com.javahelp;

import java.sql.Connection;

import java.sql.DriverManager;

/*

* JDBC工具类

*/

public class JDBCUtil {

static String driverName = "com.mysql.jdbc.Driver";

static String url = "jdbc:mysql://localhost:3306/mydatabase";

static String user = "root";

static String password = "123";


static {

// 1. 注册驱动

try {

Class.forName(driverName);

} catch (ClassNotFoundException e) {

System.out.println("数据库驱动注册失败!");

}

}


/**

* 提供获取连接的方法

* @return 连接对象

* @throws Exception

*/

public static Connection getConn() throws Exception {

// 2. 获得连接

Connection conn = DriverManager.getConnection(url,user,password);

//返回连接

return conn;

}

}

2.2.2 使用properties配置文件(选做)

开发中获得连接的4个参数(驱动、URL、用户名、密码)通常都存在配置文件中,方便后期维护,程序如果需要更换数据库,只需要修改配置文件即可。

通常情况下,我们习惯使用properties文件,此文件我们将做如下要求:

1. 文件位置:任意,在指定位置,一般在项目根目录下

2. 文件名称:任意,扩展名为properties

3. 文件内容:一行一组数据,格式是“key=value”.

a) key命名自定义,如果是多个单词,习惯使用点分隔。(习惯性可以使用静态常量方式记录固定的key)例如:jdbc.driver

b) value值不支持中文,如果需要使用非英文字符,将进行unicode转换。(如果没有指定编码,并且默认编码与properties不同,或者使用properties文件默认的iso8859-1会出现乱码)


2.2.3 创建配置文件

右键/New/File,输入“db.properties”文件名。

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/mydb

jdbc.user=root

jdbc.password=123

2.2.4 加载配置文件:Properties对象

对应properties文件处理,开发中也使用Properties对象进行。我们将采用加载properties文件获得流,然后使用Properties对象进行处理。

static{

try {

//1 使用Properties处理流

// * 使用load()方法加载指定的流

Properties props = new Properties();

props.load(is);


//2 使用getProperty(key),通过key获得需要的值,

driver = props.getProperty("jdbc.driver");

url = props.getProperty("jdbc.url");

user = props.getProperty("jdbc.user");

password = props.getProperty("jdbc.password");

} catch (Exception e) {

throw new RuntimeException(e);

}

}


2.2.5 获得连接

/**

* 获得连接

* @return

*/

public static Connection getConnection(){

try {

//1 注册驱动

Class.forName(driver);

//2 获得连接

Connection conn = DriverManager.getConnection(url,user,password);

return conn;

} catch (Exception e) {

throw new RuntimeException(e);

}

}


2.3 作业:

1:完成JDBC步骤的课上查询语句,集合昨天学习的多样SQL需求

2:参照课上的查询操作executeQuery,自己完成增删改的操作executeUpdate


第3章 使用DBUtils优化增删改查操作

如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC开发,本案例我们讲采用apache commons组织的一个成员:DBUtils。

DBUtils就是JDBC的简化开发工具包。需要使用技术:连接池(获得连接),SQL语句都没有少。


3.1 JavaBean组件

JavaBean就是一个类,在开发中常用于封装数据。具有如下特性

1. 需要实现接口:java.io.Serializable ,通常偷懒省略了。

2. 提供私有字段:private 类型 字段名

3. 提供getter/setter方法

4. 提供无参构造

public class Category {

private String cid;

private String cname;

public Category() {

super();

}

public String getCid() {

return cid;

}

public void setCid(String cid) {

this.cid = cid;

}

public String getCname() {

return cname;

}

public void setCname(String cname) {

this.cname = cname;

}

   …toString….

}


3.2 DBUtils完成CRUD

3.2.1 概述

DBUitls是Apache组织提供的一个对JDBC进行简单封装的开源工具类,使用DBUItils工具类对数据库进行开发, 使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。

DBUtils操作的是数据库表数据,不会使用其进行表结构字段的设置,因为数据库的定义通常是预先已经设置好了。

Dbutils三个核心类介绍

  • QueryRunner中提供对sql语句操作的API。

  • ResultSetHandler接口,用于定义select操作后,怎样封装结果集。

  • DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法。


3.2.2 DBUtils的查询操作

DBUtils的使用是相对固定的步骤,是常规Java项目的基本操作。

  • 导入DBUtils的Jar包 (我们提供的版本为commons-dbutils-1.6.jar)

  • 通过DriverManger注册驱动

  • 通过DriverManager获取连接对象Connection

  • 通过DBUtils的QueryRunner的query方法使用对应的Connection完成SQL操作

  • 针对执行查询语句时,通过不同的ResultSetHandler子类可以在查询数据后,直接将得到的数据封装为想要的数据组织方式

常用Handler(处理方式):

3.2.3 DBUtils的增删改操作

在查询数据的基本步骤基础上,使用QueryRunner调用update(String sql, Object... params) ,执行增删改操作。前边的sql可以添加?,其后边的可变参数为前边的?赋值。

在增删改操作中,没有对结果集的操作。


第4章 连接池

4.1 连接池概述

4.1.1 连接池规范

Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池。

常见的连接池:DBCP、C3P0。

这里学习DBCP连接池。C3P0连接池在就业班学习。


4.1.2 连接池技术简述

当多个程序(多个用户)的多个需求时,我们需要创建多个Connection对象,而与数据库创建连接是十分消耗资源的,连接池创建了多个连接,当使用连接操作数据时,会分配一个连接,而这个连接也可供其他程序(用户)的数据库操作使用,类似线程池。

javax.sql包下的 DataSource是线程池接口。可以使用getConnection()方法获取一个连接,如果连接对象Connection是通过连接池获取的,当通过Connection对象调用close()方法时,不再是销毁连接对象,而是将连接对象放回到连接池。

不使用连接池

使用连接池

a) dbcp连接池介绍

DBCP 是 Apache 软件基金组织下的一个优秀的开源连接池实现,使用DBCP数据源,应用程序应在系统中增加如下两个 jar 文件:

  • Commons-dbcp.jar:连接池的实现

  • Commons-pool.jar:连接池实现的依赖库

Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。


b) dbcp连接池配置

//导包加入classpath

// 1.创建连接池对象

BasicDataSource ds = new BasicDataSource();

// 2.设置相关属性

ds.setDriverClassName("com.mysql.jdbc.Driver");

ds.setUrl("xxx");

ds.setUsername("xxx");

ds.setPassword("xxx");

c) DBUtils使用连接池

当拥有了连接池后,我们可以直接使用连接池获取连接对象,完成普通的sql操作。(在获取连接后,关闭连接是将连接返还给连接池)

而在DBUtils的学习过程中,我们使用QueryRunner的空参构造完成,每次请求调用query方法时传入连接对象。

而当有了线程池后,可以调用QueryRunner的带参构造创建对象:

QueryRunner(DataSource connectionPool);

这时,在每次访问数据库时,将无需再传入连接对象。因为在每次使用QueryRunner时,都已经通过连接池获取了连接。

如:

BasicDataSource ds = new BasicDataSource();

ds.setUrl("jdbc:mysql://localhost:3306/javahelp_gjp");//设置数据库连接

ds.setDriverClassName("com.mysql.jdbc.Driver");//设置驱动名称

ds.setUsername("root");//设置登录用户名

ds.setPassword("abc");//设置登录密码


ds.setMaxIdle(3);//连接池最大空闲连接个数

ds.setMaxWait(3000);//连接池最大等待时间

ds.setMaxActive(5);//连接池最大连接个数

ds.setInitialSize(3);//连接池初始化连接个数


QueryRunner qr = new QueryRunner(ds);

//再查询时无需传入连接对象,因为QueryRunner对象已经从连接池中获取了连接

返回值类型 query = qr.query(SQL语句,Handler对象);


4.1.3 编写工具类(最简单方式)

/*

* 创建DBCP连接池工具类

*

* 作用: 配置DBCP连接池,提供获取连接池中连接对象的方法

*/

public class DBCPUtils {

//创建连接池

private static BasicDataSource dataSource = new BasicDataSource();

public static final String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";

public static final String URL = "jdbc:mysql://localhost:3306/day22_jdbc";

public static final String USER_NAME = "root";

public static final String PASSWORD = "root";

//通过静态代码块,完成dataSource对象的信息配置

static {

//指定驱动名称

dataSource.setDriverClassName(DRIVER_CLASS_NAME);

//指定数据库URL

dataSource.setUrl(URL);

//指定数据库连接的用户名

dataSource.setUsername(USER_NAME);

//指定数据库连接的密码

dataSource.setPassword(PASSWORD);

}


/*

* 提供获取连接池中连接对象的方法

*/

public static Connection getConnection(){

try {

return dataSource.getConnection();

} catch (Exception e) {

throw new RuntimeException(e);

}

}

}


4.1.4 常见配置项


参考文档:http://commons.apache.org/proper/commons-dbcp/configuration.html


4.2 作业:

1:定义MyDBUtils类,提供连接池方法(提示:所有连接池的属性设置项均可以为静态成员变量)

2:使用QueryRunner带预处理的查询或更新方法,将where条件的值使用?的方式传入

3:分别使用连接池与不使用连接池操作QueryRunner,完成查询。

4:将所有Handler对象使用一遍。sql语句参照day27的课上语句。


支付宝赞助-Java帮帮社区
微信赞助-Java帮帮社区
Java帮帮公众号生态

Java帮帮公众号生态

总有一款适合你

Java帮帮-微信公众号

Java帮帮-微信公众号

将分享做到极致

Python帮帮-公众号

Python帮帮-公众号

人工智能,爬虫,学习教程

大数据驿站-微信公众号

大数据驿站-微信公众号

一起在数据中成长

九点编程-公众号

九点编程-公众号

深夜九点学编程

程序员生活志-公众号

程序员生活志-公众号

互联网,职场,程序员那些事儿

Java帮帮学习群生态

Java帮帮学习群生态

总有一款能帮到你

Java学习群

Java学习群

与大牛一起交流

大数据学习群

大数据学习群

在数据中成长

九点编程学习群

九点编程学习群

深夜九点学编程

python学习群

python学习群

人工智能,爬虫

测试学习群

测试学习群

感受测试的魅力

Java帮帮生态承诺

Java帮帮生态承诺

一直坚守,不负重望

初心
勤俭
诚信
正义
分享
合作品牌 非盈利生态-优质内容分享传播者
友链交换:加帮主QQ2524138991 留言即可 24小时内答复  
会员登录
获取验证码
登录
登录
我的资料
留言
回到顶部