|
第二十七天 数据库基础&JDBC使用&工具类Properties&连接池&DBUtils【悟空教程】149
发表时间: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分类
1.4.2 SQL通用语法
详详细的数据类型(不建议详细阅读!)
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语句表条件过滤。满足条件操作,不满足不操作,多用于数据的查询与修改。 格式 : select 字段 from 表名 where 条件; select 字段 from 表名 where name=’香蕉’; select 字段 from 表名 where price<5; select 字段 from 表名 where name>5’;
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可以将查询出的结果进行排序。放置在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 JDBC2.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的格式由三部分组成,每个部分中间使用冒号分隔。
2.1.7 API详解:获得语句执行平台String sql = "某SQL语句"; 获取Statement语句执行平台:Statement stmt = con.createStatement(); 常用方法:
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);//获取第一行第一列的数据 常用方法:
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语句:
2. 设置实际参数
2.1.12 案例:查询所有记录信息public class JDBCTest { public static void main(String[] args) { try { //1,注册驱动 /* * 加载MySql的Driver类到内存,MySql的Driver类在自己的静态代码块实现注册驱动的操作 * 1.使用类加载器,完成MySql的Driver类的加载 * 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完成CRUD3.2.1 概述DBUitls是Apache组织提供的一个对JDBC进行简单封装的开源工具类,使用DBUItils工具类对数据库进行开发, 使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。 DBUtils操作的是数据库表数据,不会使用其进行表结构字段的设置,因为数据库的定义通常是预先已经设置好了。
Dbutils三个核心类介绍
3.2.2 DBUtils的查询操作DBUtils的使用是相对固定的步骤,是常规Java项目的基本操作。
常用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 文件:
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
|