分页查询的语法
select 指定的字段列表 from 表名 limit 起始索引,每页显示的条数;
-- 起始索引 = (当前页码数-1)*每页显示的条数;
-- 当前页码数以及 每页显示的条数----前端传过来的数据!
-- 后端 pageBean:自定义分页组件
class PageBean<T>{
private int currentPage; 当前页码
private int pageSize ; 每页显示的条件
private int totalPage; 总页数 ---
-- (totalCount % pageSize == 0)?totalCount/pageSize:向上取整;
private int totalCount ; 总记录数
private List<T> list ; 分页的列表数据
}
2.通过sql添加/删除为唯一约束的语法
-- 通过sql添加唯一约束
-- 如果在创建表的时候,没有设置唯一约束名称,默认和字段名称一致;
alter table 表名 add constraint <唯一约束名称> unique(字段名称) ;
-- 通过sql删除唯一约束
alter table 表名 drop index 唯一约束名称;
3.通过sql添加外键约束和删除外键约束
-- 添加外键约束
alter table 表名
add
constraint 外键名称(主表名缩写_从表名的缩写_fk)
foreign key(外键作用字段名称)
references 主表名(主键id字段) ;
-- 删除外键约束
alter table 表名 drop foreign key 外键名称;
4.模糊搜索的语法
select 指定的字段列表 from 表名 where 字段名称 like '%关键字%' ; -- '关键字%'
5.反射获取一个类的字节码文件后如何调用成员方法?
//获取当前正在运行的这个类Class,字节码文件对象
Class c = Class.forName("包名.类名") ;
//如果当前类的无参构造方法公共的,直接创建当前类实例
Object obj = c.newInstance();
//通过字节码文件对象获取成员方法所在的Method类对象
Method m = c.getDeclareedMethod("方法名",形式参数类型的.class属性...) ;
//取消Java语言访问检查
c.setAccessiable(true) ;
//调用方法
m.invoke(obj,实际参数和形式参数类型匹配) ;
//有返回值直接返回Object,或者没有返回值,单独调用或者return null;
级联查询
级联删除/级联修改
写在字段列表尾部
删除或者修改主表的时候从表也随之变化 不用一个一个的删除修改
on update cascade
on delete casecade
CREATE TABLE employee (
id INT PRIMARY KEY AUTO_INCREMENT,
-- 员工编号
NAME VARCHAR (10),
-- 员工姓名
gender VARCHAR (3),
-- 员工性别
salary DOUBLE,
-- 工资
dept_id INT,
-- 所在的部门编号
-- 声明
CONSTRAINT -- 外键名称:主表名_从表名_fk
dept_emp_fk -- 外键作用在哪个字段上
FOREIGN KEY (dept_id) -- 关联
REFERENCES -- 主表的主键字段(就是id)
dept(id)
ON UPDATE CASCADE -- 级联修改
ON DELETE CASCADE -- 级联删除
) ;
SQL直接添加级联修改/删除
alter table 表名
add constraint 外键名
foreign key (列名)
references 主表名(列名)
on update cascade on delete casecade
表和表的关系
一对多举例
部门和员工的关系
从部门维度--->一个部门中包含多个员工
从员工维度---> 一个员工从属于某个部门
用户和订单
一个用户(用户维度):一个用户可以下多个订单
订单(订单维度):一个订单在某个时刻属于某个用户的
一个订单可以可以从属于多个用户的
多对多举例
学生表和选课表
一个学生可以选择多个课程
一个课程被多个学生选择
用户表和角色表 (用户表和角色表中间表)
从用户维度--看角色:一个用户有多个角色
从角色维度--看用户:一个角色赋予多个用户
角色表和权限表 (角色表和权限表中间表)
从角色表维度--看权限:一个角色可以多个权限
CEO:crud(添加,查询,修改和删除)
从权限维度---看角色:一个权限可以被多个角色赋予
查询权限:
CEO
hr
root管理员
普通管理员
一对一
三大范式
目的是为了减少冗余,建立结构合理的数据库,从而提高数据存储和使用的性能。
第一范式
遵循原子性,表中的字段数据不可再拆分, 每一列都是独立的
反例:
学生id | 姓名 | 年龄 |
---|---|---|
1 | 一年级小张 | 16 |
2 | 二年级小李 | 15 |
3 | 三年级小黄 | 17 |
可以看出 列2的数据是可以继续拆分的 所以不符合第一范式
修改成第一范式的如下:
正例:
学生id | 姓名 | 年级 | 年龄 |
---|---|---|---|
1 | 小张 | 一年级 | 16 |
2 | 小李 | 二年级 | 15 |
3 | 小黄 | 三年级 | 17 |
第二范式
在第一范式情况下 消除部分依赖 遵循唯一性,
表中任意一个主键可以确定除该主键外的所有非主键值
即非主键字段必须完全依赖主键字段
即每张表只能描述一件事情
总表
员工id | 姓名 | 年龄 | 绩效 | 部门 | 薪水 |
---|---|---|---|---|---|
1 | 小胡 | 33 | A | 销售部 | 3000 |
1 | 小胡 | 23 | A | 开发部 | 6000 |
2 | 小陈 | 24 | B | 策划部 | 5000 |
2 | 小陈 | 24 | C | 开发部 | 6000 |
3 | 小梁 | 30 | C | 测试部 | 4500 |
主键是ID可以确定姓名年龄 但是不能确定部门,工龄
主键是部门 可以确定薪水 但是无法确定其他数据
以此类推 不合适 所以拆分成三张表
员工表
员工id | 姓名 | 年龄 | 绩效 |
---|---|---|---|
1 | 小胡 | 33 | A |
1 | 小胡 | 23 | A |
2 | 小陈 | 24 | B |
2 | 小陈 | 24 | C |
3 | 小梁 | 30 | C |
部门表
部门 | 薪水 |
---|---|
销售部 | 3000 |
开发部 | 6000 |
测试部 | 4500 |
策划部 | 5000 |
第三范式
满足第二范式的情况下 消除依赖传递
即 知道任一主键就可以确定其他所有非主键字段的值的情况下,不能存在某非主键字段A可以获取某非主键字段B的情况。
员工id | 姓名 | 部门 | 直属上级 |
---|---|---|---|
1 | 小胡 | 销售部 | 王科 |
id为主键可以确定姓名部门和直属上级 但是知道直属上级也可以推导出是哪个部门的
员工表
学号 | 姓名 | 部门 |
---|---|---|
1 | 小胡 | 销售部 |
部门表
部门 | 直属上级 |
---|---|
销售部 | 王科 |
多表查询–内连接-显隐/外连接-左右
最基本的语法:
select 指定字段名称 from 表名1 ,表名2;
查询两个表(主表 从表)的数据不加连接条件的话,会造成笛卡尔乘积
例如
A报表三组数据
B组五组数据
不设置连接条件会输出十五天数据
内连接:
1)隐式内连接 where 条件1 and 条件2 and 条件3....
2)显示内连接 表名1 inner(inner可写可不写) join 表名2 on 连续条件;
外连接
左外:left (outer) join
右外:right (outer) join
outer 可写可不写
子查询
select 嵌套 select
利用聚合函数--查询出来的单行单列的数据和比较运算符 (完成嵌套)
条件字段名称 in(嵌套selct...)
(select 指定字段列表 from 表名)----> 虚表 和另一种张进行连接条件
表名别名 .* 查询该表所有数据
隐式内连接例子
# 创建部门表
CREATE TABLE dept(
id INT PRIMARY KEY AUTO_INCREMENT, -- 部门编号
NAME VARCHAR(20) -- 部门名称
);
INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');
# 创建员工表
CREATE TABLE emp (
id INT PRIMARY KEY AUTO_INCREMENT, -- 员工编号
NAME VARCHAR(10), -- 员工名称
gender CHAR(1), -- 性别
salary DOUBLE, -- 工资
join_date DATE, -- 入职日期
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键,关联部门表(部门表的主键) (省略constraint 外键名称)
) ;
# 写入内容
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男
',7200,'2021-02-24',1);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男
',3600,'2022-12-02',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES
('唐僧','男',9000,'2020-08-08',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女
',5000,'2021-10-07',3);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女
',4500,'2021-11-14',1);
# 给表起别名
SELECT
e.`id` '员工编号',
e.`name` '员工姓名',
e.`gender` '性别',
e.`salary` '工资',
e.`join_date` '入职日期',
d.`name` '部门名称'
FROM
emp e,
-- 给表起一个别名
dept d -- d是部门表的别名
WHERE e.`dept_id` = d.`id` ;
显示内连接例子
# 创建部门表
CREATE TABLE dept(
id INT PRIMARY KEY AUTO_INCREMENT, -- 部门编号
NAME VARCHAR(20) -- 部门名称
);
INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');
# 创建员工表
CREATE TABLE emp (
id INT PRIMARY KEY AUTO_INCREMENT, -- 员工编号
NAME VARCHAR(10), -- 员工名称
gender CHAR(1), -- 性别
salary DOUBLE, -- 工资
join_date DATE, -- 入职日期
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键,关联部门表(部门表的主键) (省略constraint 外键名称)
) ;
# 写入内容
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男
',7200,'2021-02-24',1);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男
',3600,'2022-12-02',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES
('唐僧','男',9000,'2020-08-08',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女
',5000,'2021-10-07',3);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女
',4500,'2021-11-14',1);
INSERT INTO emp(NAME,gender,salary,join_date)
VALUES('王大炮','男',8000,'2018-10-30') ;//插入一个没有部门信息的数据
INSERT INTO emp(NAME,gender,salary,join_date) VALUES('文章','男',7000.0,'2020-05-01') ; //插入一个没有部门信息的数据
select
t1.`id` '员工编号',
t1.`name` '员工姓名',
t1.`salary` '工资',
t1.`join_date` '入职日期',
t2.`dept_id`'员工部门'
from
emp t1
inner join dept t2
on t1.`dept_id`=t2.`id`;
左外连接(比较常用)
将A表的数据全部显示以及A和B的有连接关系的所有数据查询
select
指定的字段列表
from
A 表 别名1
left (outer) join
B表 别名2
on
A 和 B 的连接条件 ;
-- 查询员工表的所有数据 包括没有部门的信息(王大炮)
SELECT
e.*,
d.`id`,
d.`name`
FROM
emp e
LEFT OUTER JOIN depts d
ON e.`depts_id` = d.`id` ;
id NAME gender salary join_date depts_id id name
1 孙悟空 男 7200 2021-02-24 1 1 开发部
5 蜘蛛精 女 4500 2021-11-14 1 1 开发部
2 猪八戒 男 3600 2022-12-02 2 2 市场部
3 唐僧 男 9000 2020-08-08 2 2 市场部
4 白骨精 女 5000 2021-10-07 3 3 财务部
6 王大炮 男 8000 2018-10-30 \N \N \N
INSERT INTO emp(NAME,gender,salary,join_date) VALUES('文章','男',7000.0,'2020-05-01') ;
-- 如果提示:仅仅没有部门的员工的也需要查询出来,使用左外连接
SELECT
e.`name` '员工姓名',
e.`gender` '员工性别',
e.`salary` '员工工资',
e.`join_date` '入职日期',
d.`name` '部门名称'
FROM
emp e
LEFT JOIN dept d
ON e.`dept_id` = d.`id` -- 作为两张表的连接条件
WHERE e.`salary` >= -- 附件条件
(SELECT
AVG(salary)
FROM
emp) ;
员工姓名 员工性别 员工工资 入职日期 部门名称
孙悟空 男 7200 2021-02-24 开发部
唐僧 男 9000 2020-08-08 市场部
王大炮 男 8000 2018-10-30 \N
文章 男 7000 2020-05-01 \N
右外连接
将B表的数据全部显示以及A和B的有连接关系的所有数据查询
select
指定的字段列表
from
B 表 别名1
right (outer) join
A表 别名2
on
A 和 B 的连接条件 ;
子查询
(select 嵌套)
需求:查询工资是九千的员工信息部门
select
t1.*,
t2.*
from
emp t1,dept t2
where
t1.`dept_id`=t2.`id`
and
t1.salary
=(select max(salary)from emp);
需求: 子查询 in(值1,值2,值3...);
查询在2或者3号部门的所有员工信息
select
e.*,
d.`id`,
d.name
from
emp.e,
dept.d
where
e.`dept_id`=d.`id`
and e.`dept_id`in(
select
id
form
dept
where name in('市场部','财务部')
);
子查询-虚表
将某张表select的结果集---当做一张虚表和其他表建立连接查询
-- 需求:要查询出员工入职日期大于2021-10-07的员工的所有信息以及它的部门信息;
-- 查询员工入职日期大于 2021-10-07的员工所有信息 (查询出来的结果集当作 "虚表")
SELECT
t1.*,
-- 所有的部门信息
t2.* -- 所有员工信息
FROM
depts t1
INNER JOIN
(SELECT
*
FROM
emp
WHERE emp.`join_date` > '2021-10-07')
t2
ON t1.`id` = t2.`depts_id` ;
把员工表的满足入职日期在2021-10-07之后的数据的结果当作一个新的表
id NAME id NAME gender salary join_date depts_id
1 开发部 5 蜘蛛精 女 4500 2021-11-14 1
2 市场部 2 猪八戒 男 3600 2022-12-02 2
隐式内连接版本:
SELECT
e.*,
d.*
FROM
emp e,
depts d
WHERE e.`depts_id` = d.`id`
AND e.`join_date` > '2021-10-07' ;
id NAME gender salary join_date depts_id id NAME
5 蜘蛛精 女 4500 2021-11-14 1 1 开发部
2 猪八戒 男 3600 2022-12-02 2 2 市场部
数据库的事务
DBA(数据库管理员)用户在操作多个sql的时候,有一条执行语句异常,其他sql不执行,导致数据紊乱。应将整个sql的执行看作一个整体,要么同时执行成功,要么同时执行失败。
开启事务:start transaction
事务回滚:rollback 回滚最初的数据
commit:事务提交 不提交的话无法永久更改
传统事务特点(ACID)
原子性:
执行的某个业务操作,同时执行多个sql ,增删改。
要么同时成功要么同时失败
一致性:
实际开发中,多个线程同时去读和写的时候,数据必须保持一致性
隔离性:
事务和事务(业务和业务)之间,相互独立互不影响
持续性:
对增删改的这些sql数据,一旦事务提交了。对数据库的表的操作是永久的,及时关机也不会改变
传统事务的隔离级别:
执行效率从大到小。安全性从低到高 级别 从低到高
#读未提交 read uncommitted;
一个事务读取到另一个没有提交的事务(最不安全的),出现脏读。
#读已提交:read committed;
//有效防止脏读,但是又出现另一个问题:'不可重复读'
读取到自己本身没有提交的事务的数据前后两次不一致 本身这个事务没有提交
多次读取到的数据必须一致,
# 可重复读,Mysql的默认隔离级别(repetable-read)
//有效防止脏读,'不可重复读',但是又出现新的问题:幻读
#可序列化:serializable;
最高级别的隔离 避免脏读 避免不可重复读 避免幻读
事务只能一个接一个执行
设置隔离级别
set global transaction isoloation level
查看隔离级别
select @@tx_isoloation
1.什么是事务?
关系型数据库中--支持"多事务",都会在事务机制,当某个业务同时操作多个sql语句或者是多张表的sql插入/删除/修改),这多个sql要么同时执行成功,要么同时执行失败,保证数据的完整性!
2.事务的特点和事务的隔离级别
事务的特点
原子性:多个sql要么同时执行成功,要么同时执行失败,保证数据的完整性!
一致性:事务同时去操作多个sql的时候,需要保证数据的一致性!
隔离性:多个事务(业务和业务之间)之间互相独立的,互不影响
持久性:当事务一旦提交,对数据的更改是永久性的,即使关机也存在!
事务的隔离级别:
-- 下面依次从小到大,安全性低大高,效率:从高到低;
read uncommitted ; 读未提交
read committed ; 读已提交
repetable read ; 可重复读 mysql的默认级别:有效防止脏读以及不可重复读
serializable ; 串行话
3.mysql多表查询内连接和左外连接的语法
-- 隐式内连接
select 指定的字段名称 from 表名1,表名2 where 条件1 and 条件2.... ;
-- 显示内连接
select 指定的字段名称 from 表名1 inner join 表名2 on 连接条件;
-- 左外连接语法:将左表数据全部查询以及它们的交集部分的数据
select 指定的字段名称 from 表名1 left outer join 表名2 on 连接条件 where 附件条件..
4.数据库的三大范式描述
1NF:
数据库表中的每一列是独立,不能在拆分的原子数据项
2NF:
在1NF基础上
1)数据库指定表中,描述一件事情(一张表描述一件事情)
2)数据库表中的非主键字段必须完全依赖主键字段
3NF:
在2NF基础上
数据库表中非主键字段之间不能产生传递依赖!
非主键字段A---字段B---->字段C :产生传递依赖
-- 解决冗余:比如多对多---拆分中间表:设置外键连接
5.通过mysql指令如何控制事务
-- 开启事务:将mysql自动提交,切换手动提交事务
start transaction ;
-- 设置回滚命令
rollback;
-- 永久更新数据(保证数据的持久性)
commit ;
-- 设置隔离级别
set global transaction isolation level 级别名称;
-- 查看隔离级别
select @@tx_isolation ;
JDBC
本质:数据库厂商提供的一个普通java类,实现sun公司提供的接口(java.sql.Driver)得类
在对应的数据库官网下载对应的jar包
#入门操作
1. 导入驱动包:mysql-connector-java-5.1.25.jar或者mysql-connector-java-8.0.15.jar
打开idea,File-->Project Structure-->Mudoles-->Dependencies-->左边+号点第一个JAR..
2. //注册驱动
3. //准备sql语句
4. //获取数据连接对象
5. //通过数据库的连接对象获取执行对象
6. //执行对象执行sql
7. //释放资源
例子
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//准备sql语句
String sql=
" insert into test2 (id,name,age,address,number)values(2,'judy',20,'俄亥俄',13209879749);";
//获取数据连接对象
/* public static Connection getConnerction(
String url, 统一资源定位符:连接的具体库
String user, 用户名
String password 密码
)throws SQLException*/
Connection connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/sanbao",
"root",
"yisanbao19970808");
//通过数据库的连接对象获取执行对象
Statement sts = connection.createStatement();
//执行对象执行sql
int i = sts.executeUpdate(sql);
System.out.println("影响了"+i+"行");
//释放资源
sts.close();
connection.close();
}
}
sql中的结果:
id name age address number
1 mike 18 加利佛尼亚 132979877
2 kiki 18 佛罗里达 13243565465
3 joho 18 旧金山 132985764
4 cc 20 纽约 15387867
2 judy 20 俄亥俄 13209879749
需要不断创建对象 写参数 比较麻烦
例子(改良1)
package com.qf.jdbc_01;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* @author 高圆圆
* @date 2023/4/4 11:31
* jdbc操作DDL语句,创建一张表 student
* id int ,name varchar(10),age int,gender varchar(3),address varchar(50),
*
*/
public class JdbcDemo2 {
public static void main(String[] args) {
//捕获异常
//1)导包
//2)注册驱动
Connection conn = null ;
Statement stmt = null ;
try {
Class.forName("com.mysql.jdbc.Driver") ;
//3)获取数据库连接对象
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/myee2302_db_2",
"root",
"123456");
//4)准备sql
String sql = "create table student(" +
"id int primary key auto_increment," +
"name varchar(10)," +
"age int," +
"gender varchar(3)," +
"address varchar(50));";
//5)通过连接对象获取执行对象
stmt = conn.createStatement();
//6)执行更新操作 DDL语句 executeUpdate(String sql)
int count = stmt.executeUpdate(sql);
System.out.println(count);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
if(stmt!=null){
try {
stmt.close() ;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close() ;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
写工具类 把参数写src下的properties文件中
package com.qf.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 将jdbc步骤优化
* 自定义工具类,将获取连接对象,释放资源都放在静态方法中,方便去使用!
*/
public class JdbcUtils {
//统一资源定位符
private static String url = null ;
//用户名
private static String user = null ;
//密码
private static String password = null ;
//驱动类
private static String driverClassName = null ;
//定义静态代码块
static{
try {
//1)读取src下面的jdbc.properties文件
//创建一个属性集合列表
Properties prop = new Properties() ;
System.out.println(prop) ;
InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
//将字节输入流加载到属性集合列表中
prop.load(inputStream) ;
System.out.println(prop) ;
//2)通过key获取value
driverClassName = prop.getProperty("driverClassName");
url = prop.getProperty("url");
user = prop.getProperty("user");
password = prop.getProperty("password");
//3)注册驱动
Class.forName(driverClassName) ;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//对外私有,不让外界new
private JdbcUtils(){}
//定义公共的静态方法,返回值就是Connection
//public static Connection getConnection(String url,String user,String password){ //一会还得需要传入参数,
public static Connection getConnection(){ //一会还得需要传入参数,
Connection conn = null ;
try {
conn = DriverManager.getConnection(url,user,password) ;//url,user,password
return conn;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null ;
}
//释放资源
//主要针对DDL/DML语句操作释放资源
public static void close(Statement stmt,Connection conn){
if(stmt!=null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void main(String[] args) {
Connection conn = JdbcUtils.getConnection();
System.out.println(conn);
}
}
配置文件
# properties内:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/myee2302_db_2
user=root
password=123456
Statement执行对象
package com.qf.jdbc_03;
//将表内容打印控制台
import com.qf.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 使用Statment执行对象来操作DQL语句,并去将所有的结果集数据表打印在控制台上
*/
public class Statement_DQL {
public static void main(String[] args) {
Connection conn = null ;
Statement stmt = null ;
ResultSet rs = null ;
try {
//注册驱动并获取连接对象
conn = JdbcUtils.getConnection() ;//JdbcUtils来自上面的例子里的工具类
//准备sql语句
String sql = "select * from student;" ;
//通过连接对象获取执行对象,准备发送sql到数据库
stmt = conn.createStatement() ;
//执行通用的查询操作
rs = stmt.executeQuery(sql) ;
//第一次获取
System.out.println("编号\t姓名\t\t\t年龄\t性别\t地址") ;
//有下一行数据获取
//boolean next() ;
/* if(rs.next()){
//列的索引值获取
int id = rs.getInt(1) ;
String name = rs.getString(2) ;
int age = rs.getInt(3) ;
String gender = rs.getString(4);
String address = rs.getString(5);
System.out.println(id+"\t"+name+"\t\t"+age+"\t"+gender+"\t"+address);
}
//第二次获取
//通过列的名称获取
if(rs.next()){
int id = rs.getInt("id") ; //id名称
String name = rs.getString("name") ; //name名称
int age = rs.getInt("age") ; //age名称
String gender = rs.getString("gender") ; //gender
String address = rs.getString("address") ; //address
System.out.println(id+"\t"+name+"\t\t"+age+"\t"+gender+"\t"+address);
}
//第三次获取
//通过列的名称获取
if(rs.next()){
int id = rs.getInt("id") ; //id名称
String name = rs.getString("name") ; //name名称
int age = rs.getInt("age") ; //age名称
String gender = rs.getString("gender") ; //gender
String address = rs.getString("address") ; //address
System.out.println(id+"\t"+name+"\t\t\t"+age+"\t"+gender+"\t"+address);
}*/
//当不明确多少个结果,while循环
while(rs.next()){
//有数据,获取
int id = rs.getInt("id") ; //id名称
String name = rs.getString("name") ; //name名称
int age = rs.getInt("age") ; //age名称
String gender = rs.getString("gender") ; //gender
String address = rs.getString("address") ; //address
System.out.println(id+"\t"+name+"\t\t\t"+age+"\t"+gender+"\t"+address);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.close(rs,stmt,conn);
}
}
}
自己例子
package Utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class Jdbcutils {
private static String url=null;
private static String user=null;
private static String password=null;
private static String driverClassName=null;
//定义静态代码块
static {
try {
Properties prop = new Properties();
System.out.println(prop);
InputStream input = Jdbcutils.class.getClassLoader().getResourceAsStream("jdbc.properties");
prop.load(input);
System.out.println(prop);
driverClassName= prop.getProperty("driverClassName");
url=prop.getProperty("url");
user=prop.getProperty("user");
password=prop.getProperty("password");
Class.forName(driverClassName);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private Jdbcutils(){}
public static Connection getConnection(){
Connection conn=null;
try {
conn= DriverManager.getConnection(url, user, password);
return conn;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
public static void close(Statement stmt, Connection conn) {
if (stmt!=null) {
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
jdbc.properties内容:
driverClassName=com.mysql.jdbc.Driver
password=yisanbao19970808
user=root
url=jdbc:mysql://localhost:3306/sanbao
package Test1;
import Utils.Jdbcutils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Test {
public static void main(String[] args){
Connection conn = null;
Statement stm=null;
ResultSet rs=null;
try {
String sql="select*from student";
conn = Jdbcutils.getConnection();
stm = conn.createStatement();
rs=stm.executeQuery(sql);
System.out.println("编号\t姓名\t语文成绩\t数学成绩\t英语成绩");
while(rs.next()){
int id=rs.getInt("id");
String name=rs.getString("name");
int chinese=rs.getInt("chinese");
int math=rs.getInt("math");
int english=rs.getInt("english");
System.out.println(id+"\t"+" "+name+"\t"+" "+chinese+"\t"+" "+math+"\t"+" "+english);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
模仿例子
JdbcUtils
package com.qf.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* 将jdbc步骤优化
* 自定义工具类,将获取连接对象,释放资源都放在静态方法中,方便去使用!
*/
public class JdbcUtils {
//统一资源定位符
private static String url = null ;
//用户名
private static String user = null ;
//密码
private static String password = null ;
//驱动类
private static String driverClassName = null ;
//定义静态代码块
static{
try {
//1)读取src下面的jdbc.properties文件
//创建一个属性集合列表
Properties prop = new Properties() ;
//System.out.println(prop) ;
InputStream inputStream = JdbcUtils.class.getClassLoader().
getResourceAsStream("jdbc.properties");
//将字节输入流加载到属性集合列表中
prop.load(inputStream) ;
//System.out.println(prop) ;
//2)通过key获取value
driverClassName = prop.getProperty("driverClassName");
url = prop.getProperty("url");
user = prop.getProperty("user");
password = prop.getProperty("password");
//3)注册驱动
Class.forName(driverClassName) ;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//对外私有,不让外界new
private JdbcUtils(){}
//定义公共的静态方法,返回值就是Connection
//public static Connection getConnection(String url,String user,String password){ //一会还得需要传入参数,
public static Connection getConnection(){ //一会还得需要传入参数,
Connection conn = null ;
try {
conn = DriverManager.getConnection(url,user,password) ;//url,user,password
return conn;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null ;
}
//释放资源
//针对DQL语句操作释放资源
public static void close(ResultSet rs,Statement stmt,Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
//主要针对DDL/DML语句操作释放资源
public static void close(Statement stmt,Connection conn){
close(null,stmt,conn);
}
//测试类
public static void main(String[] args) {
Connection conn = JdbcUtils.getConnection();
System.out.println(conn);
}
}
jdbc.properties内容:
driverClassName=com.mysql.jdbc.Driver
password=yisanbao19970808
user=root
url=jdbc:mysql://localhost:3306/sanbao
Student
package Test2;
/*
id int(11) NULL
name varchar(20) NULL
chinese int(11) NULL
english int(11) NULL
math int(11) NULL*/
@SuppressWarnings("all")
public class Student {
private int id;
private String name;
private int chinese;
private int math;
private int english;
public Student() {
}
public int getId(int id) {
return this.id;
}
public String getName(String name) {
return this.name;
}
public int getChinese(int chinese) {
return this.chinese;
}
public int getMath(int math) {
return this.math;
}
public int getEnglish(int english) {
return this.english;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public void setMath(int math) {
this.math = math;
}
public void setEnglish(int english) {
this.english = english;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", chinese=" + chinese +
", math=" + math +
", english=" + english +
'}';
}
}
StudentDao
package Test2;
import java.util.List;
public interface StudentDao {
List<Student> findAll();
void add(Student s)throws Exception;
}
StudentImpl
package Test2;
import Utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("all")
public class StudentImpl implements StudentDao{
@Override
public List<Student> findAll() {
List<Student> list = null ;
Connection conn = null ;
Statement stt = null ;
ResultSet res = null ;
try {
list=new ArrayList<>();
conn= JdbcUtils.getConnection();
String sql="select * from student;";
stt=conn.createStatement();
res=stt.executeQuery(sql);
Student s=null;
while(res.next()){
s=new Student();
s.getId(res.getInt("id"));
s.getName(res.getString("name"));
s.getChinese(res.getInt("chinese"));
s.getMath(res.getInt("math"));
s.getEnglish(res.getInt("english"));
list.add(s);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return list;
}
@Override
public void add(Student s) throws Exception {
Connection connection = JdbcUtils.getConnection();
String sql="insert into student(id,name,chinese,english,math)values('\"+s.getId()+\"','\"+s.getName()+\"','\"+s.getChinese()+\"','\"+s.getEnglish()+\"','\"+s.getMath()');";
Statement statement = connection.createStatement();
int count=statement.executeUpdate(sql);
System.out.println(count);
JdbcUtils.close(statement, connection);
}
}
Test
package Test2;
import Utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("all")
public class Test2 {
public static void main(String[] args) {
List<Student> list = getStudents();
for(Student s:list){
System.out.println(s);
}
}
public static List<Student> getStudents() {
List<Student> list = null ;
Connection conn=null;
Statement stt=null;
ResultSet res=null;
try {
list=new ArrayList<>();
conn= JdbcUtils.getConnection();
String sql="select*from student;";
stt=conn.createStatement();
res=stt.executeQuery(sql);
Student s=null;
while(res.next()){
s=new Student();
s.setId(res.getInt("id"));
s.setName(res.getString("name"));
s.setChinese(res.getInt("chinese"));
s.setMath(res.getInt("math"));
s.setEnglish(res.getInt("english"));
list.add(s);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return list;
}
}
输出结果:
{}
{user=root, url=jdbc:mysql://localhost:3306/sanbao, password=yisanbao19970808, driverClassName=com.mysql.jdbc.Driver}
Student{id=1, name='行哥', chinese=89, math=90, english=78}
Student{id=2, name='潘金莲', chinese=67, math=95, english=53}
Student{id=3, name='凤姐', chinese=87, math=77, english=78}
Student{id=4, name='旺财', chinese=88, math=92, english=98}
Student{id=5, name='白小黑', chinese=82, math=67, english=84}
Student{id=6, name='白小黄', chinese=55, math=45, english=85}
Student{id=7, name='范蹦蹦', chinese=75, math=30, english=65}
单元测试
一个java语言的单元测试框架
程序测试分为白盒和黑盒,查询结果是否在范围内
黑盒测试
不需要写过多的代码(数据的录入集成..)
输入指定数据输出结果,技术含量低。一直录入数据 直到程 序出bug。
白盒测试(结构测试/透明盒测试)
懂各种后端语言的基础
例如给你一个计算机类 add(),sub(), mul(), div()提供加减乘除的功能,调用add(10,20)通过junit提供”断言“add方法的结果是否和预期值一致。需要自己书写代码。
需要使用:”junit “单元测试方法
提供的runner启动器可以编译和运行
1)导包,导入jar包,核心包(junit)和依赖包(hamcrest)
2)写单元测试类-->xxxTest
提供一个成员方法:没有参数 没有返回值!
成员方法上加一个注解@Test
测试功能
导入idea的方法和导入jdbc包一样。
例子
package JunitDemo1;
//计算器类
public class Calculator {
//加
public int add(int a, int b) {
return a + b;
}
//乘
public int mul(int a, int b) {
return a * b;
}
//除
public int div(int a, int b) {
return a / b;
}
//减
public int sub(int a, int b) {
return a - b;
}
}
package JunitDemo1;
//单元测试类
import org.junit.Assert;
import org.junit.Test;
public class CalculatorTets {
@Test//要写Test
public void testAdd(){
Calculator cal = new Calculator();
int sum= cal.add(10, 20);
Assert.assertEquals(30, sum);
//参数1:预期值,参数2:结果实际值,两个是否相等,相等,则断言成功;否则断言失败!
}
}
//此时的断言是成功的 10+20=30,符合预期值
当我们把与预期值改了或者把调用的计算器类的方法改了 再或者故意把add方法改为a-b,总之就是出问题了,程序断言错误:
java.lang.AssertionError:
Expected :50
Actual :0
<Click to see difference>
经典作业题
题目
1.使用Statement执行对象,完成针对员工进行添加,删除,修改,和查询操作
员工类Employee中有员工编号,姓名,员工年龄,员工性别,员工工资,员工出生日期 (根据今天有一个项目中代码分层进行操作)
com.qf.pojo
com.qf.dao
com.qf.dao.impl
com.qf.test--->里面提供单元测试的类以及单元测试方法
EmployeeDao接口提供以下功能
a)添加员工
b)修改员工
c)删除员工
d)查询所有员工
e)List<Employee> findEmpByName(String name); 模糊查询 举例"模糊查询姓王的员工"
f)List<Employee> findEmpByLimit(int currentPage,int pageSize) ;分页查询,已知当前页码和每页显示的条数
g)int totalCount() ;查询总记录数
h)通过id查询指定的员工信息 Employee findEmpById(int id)
在EmployeeDaoImpl中实现
在EmployeeTest中使用单元测试 针对功能进行测试! (工具类自己最好手写一遍,加深印象)
实体类
package com.number1.pojo;
public class Employee {
private int id;
private int age;
private String name;
private String gender;
private int salary;
private String birthday;
public Employee() {
}
public Employee(int id, int age, String name, String gender, int salary, String birthday) {
this.id = id;
this.age = age;
this.name = name;
this.gender = gender;
this.salary = salary;
this.birthday = birthday;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", salary=" + salary +
", birthday='" + birthday + '\'' +
'}';
}
}
接口类
package com.number1.dao;
import com.number1.pojo.Employee;
import java.sql.SQLException;
import java.util.List;
public interface EmployeeDao{
//添加
void add(Employee e) throws SQLException;
//删除
void delete(int d) throws SQLException;
//修改
void update(Employee e,int a) throws SQLException;
//查询
List<Employee> findall() ;
//模糊查询
List<Employee> findEmpByName(String name);
//分页查询
List<Employee> findEmpByLimit(int currentPage, int pageSize) ;
//查询总记录数
int totalCount() throws SQLException;
//通过id查询指定的员工信息
Employee findEmpById(int a) throws SQLException;
}
子实现类
package com.number1.dao.impl;
import JdbcUtils.JdbcUtils;
import com.number1.dao.EmployeeDao;
import com.number1.pojo.Employee;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("all")
public class EmployeeDaoImpl implements EmployeeDao{
//添加
@Override
public void add(Employee e) throws SQLException {
/* Connection conn = JdbcUtils.getConnection();
String sql =
"insert into employee2(id,name,gender,age,birthday,salary) values(' " + e.getId() +" ' , ' "+ e.getName()+ " ' , ' "+ e.getGender() + " ' ,' " + e.getAge() + " ' , ' " + e.getBirthday() + " ' , ' " + e.getSalary() +" ') ;";
Statement stt = conn.createStatement();
int i=stt.executeUpdate(sql);
System.out.println("影响了"+i+"行");
JdbcUtils.close(stt, conn);*/
}
//删除
@Override
public void delete(int d) throws SQLException {
/* Connection conn = JdbcUtils.getConnection();
String sql =
"delete from employee2 where id=' "+d+" ';";
Statement stt = conn.createStatement();
int i=stt.executeUpdate(sql);
System.out.println("影响了"+i+"行");
JdbcUtils.close(stt, conn);*/
}
//修改
@Override
public void update(Employee e,int a) throws SQLException {
/* Connection conn = JdbcUtils.getConnection();
String sql =
"UPDATE employee2 SET NAME=' "+e.getName()+" ' WHERE ID=' "+a+" ';";
Statement stt = conn.createStatement();
int j=stt.executeUpdate(sql);
System.out.println("影响了"+j+"行");
JdbcUtils.close(stt, conn);*/
}
//查询全部
@Override
public List<Employee> findall() {
List<Employee>list=null;
Connection conn=null;
Statement stt=null;
ResultSet rs=null;
try {
list=new ArrayList<>();
String sql="select * from employee2;";
conn=JdbcUtils.getConnection();
stt=conn.createStatement();
rs=stt.executeQuery(sql);
Employee e=null;
while(rs.next()){
e.setId(rs.getInt("id"));
e.setName(rs.getString("name"));
e.setAge(rs.getInt("age"));
e.setGender(rs.getString("gender"));
e.setBirthday(rs.getString("birthday"));
e.setSalary(rs.getInt("salary"));
list.add(e);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return list;
}
//模糊查询
@Override
public List<Employee> findEmpByName(String name) {
List<Employee>list=null;
Connection conn=null;
Statement stt=null;
ResultSet rs=null;
try {
list=new ArrayList<>();
String sql="select * from employee2 where name like' %" +name+"% ';";
conn=JdbcUtils.getConnection();
stt=conn.createStatement();
rs=stt.executeQuery(sql);
Employee e=null;
while(rs.next()){
e=new Employee();
e.setId(rs.getInt("id"));
e.setName(rs.getString("name"));
e.setAge(rs.getInt("age"));
e.setGender(rs.getString("gender"));
e.setBirthday(rs.getString("birthday"));
e.setSalary(rs.getInt("salary"));
list.add(e);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return list;
}
//分页查询
@Override
public List<Employee> findEmpByLimit(int currentPage, int pageSize) {
List<Employee>list=null;
Connection conn=null;
Statement stt=null;
ResultSet rs=null;
try {
list=new ArrayList<>();
String sql="select * from employee2 limit "+(currentPage-1)*pageSize+","+pageSize+";";
conn=JdbcUtils.getConnection();
stt=conn.createStatement();
rs=stt.executeQuery(sql);
Employee e=null;
while(rs.next()){
e=new Employee();
e.setId(rs.getInt("id"));
e.setName(rs.getString("name"));
e.setAge(rs.getInt("age"));
e.setGender(rs.getString("gender"));
e.setBirthday(rs.getString("birthday"));
e.setSalary(rs.getInt("salary"));
list.add(e);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return list;
}
//查询总记录数
@Override
public int totalCount() throws SQLException {
Connection conn = JdbcUtils.getConnection();
String sql =
"SELECT COUNT(id) FROM employee2;";
Statement stt = conn.createStatement();
ResultSet resultSet = stt.executeQuery(sql);
int count =0;//统计变量
while(resultSet.next()){
count=resultSet.getInt(1);
}
JdbcUtils.close(stt, conn);
return count;
}
//根据id查询信息
@Override
public Employee findEmpById(int a) {
Employee e=null;
Connection conn=null;
Statement stt=null;
ResultSet rs=null;
try {
conn=JdbcUtils.getConnection();
String sql="SELECT * FROM employee2 WHERE id="+a+";";
stt=conn.createStatement();
rs=stt.executeQuery(sql);
while(rs.next()){
int id=rs.getInt("id");
String name=rs.getString("name");
String gender=rs.getString("gender");
int age=rs.getInt("age");
String birthday=rs.getString("birthday");
int salary=rs.getInt("salary");
e=new Employee(id,age,name,gender,salary,birthday);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return e;
}
}
测试类
package com.number1.test;
import com.number1.dao.EmployeeDao;
import com.number1.dao.impl.EmployeeDaoImpl;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.sql.SQLException;
@SuppressWarnings("all")
public class Test1 {
private EmployeeDao ed;
@Before
public void init(){
System.out.println("执行单元测试方法之前执行了");
ed=new EmployeeDaoImpl();
System.out.println(ed);
}
//添加
@Test
public void testAdd() throws SQLException {
/* Employee ee=new Employee();
ee.setId(6);
ee.setName("董九");
ee.setAge(23);
ee.setBirthday("19970806");
ee.setSalary(5000);
ed.add(ee);*/
}
//删除
@Test
public void testDelete() throws SQLException {
/* ed.delete(1);*/
}
//修改
@Test
public void testUpdate() throws SQLException {
/* Employee ee=new Employee();
ee.setName("王五");
ed.update(ee,3);*/
}
//查询全部
@Test
public void testFindAll(){
/* List<Employee>list= ed.findall();
for(Employee e:list){
System.out.println(e);
}*/
}
//模糊查询
@Test
public void testfindEmpByName(){
/* List<Employee>list= ed.findEmpByName("董九");
for(Employee e:list){
System.out.println(e);
}*/
}
//分页查询
@Test
public void testfindEmpByLimit(){
/* List<Employee>list= ed.findEmpByLimit(2,2);
for(Employee e:list){
System.out.println(e);
}*/
}
//查询总记录数
@Test
public void testtotalCount() throws SQLException {
/* int count=ed.totalCount();
System.out.println("共有"+count+"条数据");*/
}
//根据id查询信息
@Test
public void findEmpById() throws SQLException {
System.out.println(ed.findEmpById(4));
}
@After
public void close(){
System.out.println("执行单元测试方法之后执行了");
}
}
1.jdbc的本质是什么?
Jdbc是一个普通的Java类,是数据库厂商提供的驱动jar包,可以实现sun提供一套接口规范!
java.sql.Driver:驱动接口---->驱动jar包--->实现了这个接口
java.sql.Connection:数据库的连接会话--->驱动jar包--->ConnectionImpl实现了这个接口
...
2.jdbc的7大操作步骤,代码体现
// 7大步骤 后期--->开源框架:就是对原生Jdbc代码的封装+一些配置文件
//1)导入驱动jar包 --mysql-connnecto-java驱动jar包
//2)注册驱动
Class.forName("com.mysql.jdbc.Driver") ;
//3)获取数据库的连接对象
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/库名",
"root",
"123456") ;
//4)准备sql语句:DDL语句或者DML语句
String sql = "insert into employee(name,age,gender,birthday,address) values(xxx,xx,xx,xx,xx,xx)" ;
//5)通过连接对象获取执行对象Statement
Statement stmt = conn.createStatement() ;
//6)执行sql,通用的更新
int count = stme.executeUpdate(sql) ;
//7)释放资源
stmt.close() ;
conn.close() ;
3.jdbc针对DQL语句,遍历结果集
// 7大步骤 后期--->开源框架:就是对原生Jdbc代码的封装+一些配置文件
//1)导入驱动jar包 --mysql-connnecto-java驱动jar包
//2)注册驱动
Class.forName("com.mysql.jdbc.Driver") ;
//3)获取数据库的连接对象
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/库名",
"root",
"123456") ;
//4)准备sql语句:DDL语句或者DML语句
String sql = "select 指定的字段列表 from 表名" ;
//5)通过连接对象获取执行对象Statement
Statement stmt = conn.createStatement() ;
//6)执行sql,通用的查询操作
ResultSet rs = stmt.executeQuery(sql) ;
//遍历结果集
while(rs.next()){
//获取数据
//通用的写,列的名称获取/列的索引值获取
XXX 变量= rs.getXXX("字段名称") ;
//自己封装数据...
}
//7)释放资源
stmt.close() ;
conn.close() ;
4.自定义工具类JdbcUtils的步骤
配置类文件:
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/库名
user=root
password=123456
class JdbcUtils{
private static String user = null ;
private static String password = null ;
private static String driverClass = null ;
private static String url = null ;
//定义static代码块
static{
//读取配置文件
Properties prop = new Properties() ;
//获取key对应的value,赋值给上面四个成员变量
InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties") ;
user = prop.getProperty("user") ;
password = prop.getProperty("password") ;
url = prop.getPrpperty("url") ;
driverClass = prop.getProperty("driverClass") ;
//注册驱动
Class.forName(driverClass) ;
}
private JdbcUtils(){}
public static Connnection getConnection(){
Connection conn = DriverManager.getConnection(url,user,password) ;
return conn ;
}
//释放资源
//带三个参数:ResultSet ,Statment,Connection---针对DQL语句操作
//带两个参数:Satement,Connection--->针对DML语句
}
5.junit单元测试的使用步骤
1)导入junit的核心包: 4.13.1以及依赖包
2)建立测试类---XXXTest
3)定义单元测试方法,在方法上加入@Test
4)方法中要么Assert断言,要么直接测试指定功能(XXXDao--->添加,删除,修改,查询的功能)
视图View
CREATE VIEW <视图名> AS <SELECT语句>
视图是一个虚拟表,非真实存在,其本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用视
图名称即可获取结果集,并可以将其当作表来使用。
数据库中只存放了视图的定义,而并没有存放视图中的数据。这些数据存放在原来的表中。
使用视图查询数据时,数据库系统会从原来的表中取出对应的数据。因此,视图中的数据是依赖于原来的表中的数据的。
一旦表中的数据发生改变,显示在视图中的数据也会发生改变
例子
-- 创建视图
CREATE VIEW employee2_view AS
SELECT
id,
NAME,
gender,
age,
birthday,
salary
FROM
employee2 ;
-- 查看视图内容
SELECT* FROM employee2_view;
-- 查看视图结构
DESC employee2_view;
-- 查询当前库中所有表以及视图名称
SHOW TABLES;
-- 查询当前库中所有表以及视图名称以及表类型
SHOW FULL TABLES;
-- 修改视图的内容
ALTER VIEW employee2_view
AS
SELECT
id,
NAME
FROM
employee2 ;
-- 更新视图(用的少)
UPDATE
employee2_view
SET
NAME = '何求军'
WHERE id = 2 ;
-- 删除视图(不会影响基础表,只是删除视图的定义)
DROP VIEW employee2_view ;
-- 重命名视图
RENAME TABLE employee2_view TO employee2_2_view;
使用Statement的弊端
1)sql注入
原因:sql语句的实际参数存在字符串拼接,导致语句出现漏洞;(不安全)
2)执行效率低
每一次将写的sql发送数据库,(写一个sql,发送一个次sql,频繁的操作库),高并发情况下,可能造成系统奔溃!
3)
开发中不会使用Statement去操作数据库,使用PreparedStatement预编译对象
就是以用户登录为例 最后无论输出的是密码和用户名正确还是不正确,都只输出登录成功或者登录失败两种结构。是一种不安全的方法
PreparedStatement(重点)
预编译对象
开发中使用:PreparedStatement---执行预编译sql语句
select * from user where username = ? and passwod=? ; //? 占位符符号
一条sql:insert into/update/delete /select--->有参数--->全部都是? 占位符号
登录注册PreparedStatement版本
//接口类
package UserTest2;
import java.sql.SQLException;
public interface UserDao2 {
boolean log(User2 user) throws SQLException;
}
//实体类
package UserTest2;
public class User2 {
private String username;
private String password;
public User2() {
}
public User2(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User2{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
//子实现类
package UserTest2;
import JdbcUtils.JdbcUtils;
import UserTest.User;
import java.sql.*;
public class UserDaoImpl2 implements UserDao2 {
@Override
public boolean log(User2 user) throws SQLException {
Connection conn = null;
PreparedStatement stt = null;
ResultSet rs = null;
String sql =
"select * from userr where username= ?and password=?";
conn = JdbcUtils.getConnection();
stt = conn.prepareStatement(sql);
stt.setString(1, user.getUsername());
stt.setString(2, user.getPassword());
rs = stt.executeQuery();
ResultSet resultSet = stt.executeQuery();
boolean next = resultSet.next();
JdbcUtils.close(rs, stt, conn);
return next;
}
}
//测试类
package UserTest2;
import java.sql.SQLException;
import java.util.Scanner;
public class UserTest2 {
public static void main(String[] args) throws SQLException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入您的用户名");
String username=scanner.nextLine();
System.out.println("请输入您的密码");
String password=scanner.nextLine();
UserDao2 ud2=new UserDaoImpl2();
User2 u=new User2();
u.setUsername(username);
u.setPassword(password);
boolean log = ud2.log(u);
if(log){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
}
}
PreparedStatement和Statement的区别?
1)共同点
都是发送sql到数据库,都是执行对象,前者继承后者
2)不同点
# 2-1)是否可造成sql注入,
Statement 永远执行的静态sql语句,语句存在'硬编码' 和sql的字符串拼接,造成sql注入,不安全
PreparedStatement永远执行参数化sql语句,参数都是“?”,占位符号。预防sql注入,提高sql的安全性
# 2-2)执行效率
Statement不会提高sql执行效率
获取执行对象,然后将sql语句发送数据库。频繁操作访问数据库
PreparedStatement 大大提高sql执行效率
参数化sql是在获取PreparedStatement,时已经发送数据库了
数据库连接池(重点)
c3p0
dbcp
druid:德鲁伊---->阿里巴巴提供的 (开源的)
druid.jar包
只是提供数据库连接池---不能连接数据库(要连接数据库---提供mysql驱动jar包)
JdbcUtils就需要优化了
模拟线程 ThreadLocal<T> : 每一个线程都有自己的Connection
set(T t):绑定内容
remove():解绑
T get() :获取指定的内容
步骤:
1)导包 druid-1.1.10.jar包
2)准备好连接池的配置文件
driverClassName=com.mysql.jdbc.Driver//连接数据库的驱动类
url=jdbc:mysql://localhost:3306/myee2302_db_2//连接数据库 的url地址:统一资源定位符
username=root//用户名
password=123456//密码
//连接池一旦创建 初始化5个数量
initialSize=5//初始化数量(可变) 默认值 0
maxActive=10//最大激活(连接)数量 默认值 8 和最大空闲数量maxIdel相等
maxWait=3000//最大等待时间 默认值 -1(无等待时间) 3000毫秒也就是3秒 如果创建的连接对象超过最大连接数量。等待3s报错
3)从连接池获取连接对象
提供jar包--->com.alibaba.druid.pool.DruidDataSource--->本质实现了一个接口javax.sql.DataSource
--->Connection getConnection()
例子
package DruridDemo;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
public class DruridDemo {
public static void main(String[] args) throws Exception {
//创建配置文件
Properties prop = new Properties();
//读取配置文件
InputStream input = DruridDemo.class.getClassLoader().getResourceAsStream("drurid.properties");
//加载字节输入流
prop.load(input);
//获取连接对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
System.out.println(dataSource.getConnection());
/*红字部分是日志: 四月 06, 2023 5:20:05 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited*/
for(int x=0;x<=11;x++){
Connection conn = dataSource.getConnection();
System.out.println(conn);
/*
com.mysql.jdbc.JDBC4Connection@71f2a7d5
com.mysql.jdbc.JDBC4Connection@2cfb4a64
com.mysql.jdbc.JDBC4Connection@5474c6c
com.mysql.jdbc.JDBC4Connection@4b6995df
com.mysql.jdbc.JDBC4Connection@2fc14f68
com.mysql.jdbc.JDBC4Connection@591f989e
com.mysql.jdbc.JDBC4Connection@66048bfd
com.mysql.jdbc.JDBC4Connection@61443d8f
com.mysql.jdbc.JDBC4Connection@445b84c0
com.mysql.jdbc.JDBC4Connection@61a52fbd
三秒后报错:Exception in thread "main" com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 3000, active 10, maxActive 10, creating 0*/
}
}
}
情况2:加条件if(x==3)
结果如下
/*
四月 06, 2023 5:31:52 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
com.mysql.jdbc.JDBC4Connection@71f2a7d5
com.mysql.jdbc.JDBC4Connection@2cfb4a64
closed-conn-88558700
com.mysql.jdbc.JDBC4Connection@4b6995df
com.mysql.jdbc.JDBC4Connection@2fc14f68
com.mysql.jdbc.JDBC4Connection@591f989e
com.mysql.jdbc.JDBC4Connection@66048bfd
com.mysql.jdbc.JDBC4Connection@61443d8f
com.mysql.jdbc.JDBC4Connection@445b84c0
com.mysql.jdbc.JDBC4Connection@61a52fbd
com.mysql.jdbc.JDBC4Connection@233c0b17*/
配置文件drurid.properties:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/sanbao
username=root
password=yisanbao19970808
initialSize=5
maxActive=10
maxWait=3000
连接池工具类
package JdbcUtils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javafx.beans.property.Property;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class DruridUtils {
//静态实例-->java.lang.ThreadLocal<T>模拟线程,每一个用户都有自己的Connection
private static ThreadLocal<Connection> t1 = new ThreadLocal<>();
//声明一个DataSource接口类型
private static DataSource ds;
//构造方法私有
private DruridUtils() {
}
static {
try {//读取德鲁伊配置文件,让其自我封装
InputStream input = DruridUtils.class.getClassLoader().getResourceAsStream("drurid.properties");
//创建属性列表
Properties prop = new Properties();
//加载属性列表
prop.load(input);
//创建连接池
ds = DruidDataSourceFactory.createDataSource(prop);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取DataSource数据源信息 (连接池的所有参数)
private static DataSource getDataSource() {
return ds;
}
//从连接池获取连接对象
public static Connection getConnection() {
//1)从本地线程中获取连接对象---ThreadLocal<T>--->T get():从当前线程中获取存储的内容
Connection conn = t1.get();
try {
//2)如果当前conn对象为null,说明当前线程中没有要操作的连接对象
if (conn ==null) {
//3)从数据源(连接池中)获取Connection
conn = ds.getConnection();
//4)将从数据源中获取到的conn连接对象,绑定当当前线程中
//ThreadLocal<T>--->public void set(T t):绑定
t1.set(conn);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return conn;
}
//释放资源
public static void close(ResultSet rs, PreparedStatement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
//从当前线程解绑
t1.remove(); //ThreadLocal<T> :从线程中移出
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
//主要针对DDL/DML语句操作释放资源
/* public static void close(Statement stmt,Connection conn){
close(null,stmt,conn);
}*/
public static void close (PreparedStatement stmt, Connection conn){
close(null, stmt, conn);
}
public static void main (String[]args){
System.out.println(DruridUtils.getDataSource());
System.out.println(DruridUtils.getConnection());
}
}
添加数据
package DruridDemo;
import JdbcUtils.DruridUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@SuppressWarnings("ALL")
public class DruridTest {
public static void main(String[] args) throws SQLException {
Connection conn = DruridUtils.getConnection();
String sql="insert into employee2(id,name,gender,age,birthday,salary)values(?,?,?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, 7);
ps.setString(2, "林冲");
ps.setString(3, "男");
ps.setInt(4, 33);
ps.setString(5, "19900807");
ps.setInt(6, 7000);
int i = ps.executeUpdate();
System.out.println(i);
DruridUtils.close(ps, conn);
}
}
Jdbc控制事务
常用方法
Jdbc控制事务:
public void setAutoCommit(boolean auto) ;参数为true,表示自动提交,如果是false,手动提交
void rollback():事务回滚,撤销之前所有更改,必须释放连接对象,连接对象需要从线程中解绑
void commit():提交事务,将更改数据永久保存,提交完毕,释放连接对象,需要从线程中解绑
什么是事务?
针对多个sql或者多张表的sql(增删改),要么同时执行成功,要么同时执行失败,应该将整个业务看成一个整体,一块执行!
事务的特点:
原子性,一致性,隔离性,持久性
需求:
转账业务:
account账户表中:id为3的用户给id为4的账户进行转账500
例子老师
public class TranserDemo {
public static void main(String[] args) {
Connection conn = null ;
PreparedStatement ps1= null ;
PreparedStatement ps2= null ;
try {
//获取连接池中的初始化连接数量中的连接对象
conn = DruidJdbcUtils.getConnection();
//开启手动提交模式(开启事务)
//public void setAutoCommit(boolean auto) ;参数为true,表示自动提交,如果是false,手动提交
conn.setAutoCommit(false) ;
//sql语句
String sql1 = "update account set balance = balance - ? where id = ?" ;
String sql2 = "update account set balance = balance + ? where id = ?" ;
//发送参数化的sql获取编译对象
ps1 = conn.prepareStatement(sql1) ;
ps2 = conn.prepareStatement(sql2) ;
//参数赋值
ps1.setInt(1,500) ;
ps1.setInt(2,3) ;
ps2.setInt(1,500) ;
ps2.setInt(2,4) ;
//在预编译对象中执行
int count = ps1.executeUpdate();
int i = 10/0 ; //明显给了异常,实际开发中可能其他系统监控代码出现bug了也会造成 前面sql执行了,后面没有执行1
int count2 = ps2.executeUpdate();
System.out.println(count+"----"+count2) ;
// void commit():提交事务,将更改数据永久保存,提交完毕,释放连接对象,需要从线程中解绑
conn.commit(); //事务提交
} catch (SQLException throwables) {
//事务回滚
// void rollback():事务回滚,撤销之前所有更改,必须释放连接对象,连接对象需要从线程中解绑
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
} finally {
DruidJdbcUtils.close(ps1,conn) ;
DruidJdbcUtils.close(ps2,conn) ;
}
}
}
dbutils步骤和常用方法
注意事项:实体类的属性名称和字段类型的名称必须一致 否则查询语句的时候输出的是null,
或者可以在查询的时候给字段别名但是别名也得和实体类属性名称一致;
也依赖德鲁伊工具类
步骤:
1)导包:
2)创建执行器 QueryRunner-->底层是PreparStatement
public QueryRunner(DataSource ds) 参数就是数据源--->自定义工具获取到了数据源 (自动提交)
public QueryRunner():创建执行器,手动提交
3)准备好sql语句
DML语句---添加/修改/删除
insert into
update
delete from...
QueryRunner提供通用的更新操作:
public int update(Connection conn, String sql, Object... params) throws SQLException :手动提交
public int update(String sql, Object... params):自动提交
DQL语句--- 查询语句
QueryRunner提供的通用查询操作
public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException
第一个参数:查询的sql语句
第二个参数:ResultSetHandler结果集的处理
它的子实现类:BeanHandler---->将查询的某一条记录封装到实体了中(JavaBean:是具体类,属性私有,对外提供setXXX()/getXXX)
public BeanHandler(Class<T> type) ---> 参数针对查询的记录--封装到类名.class中
子实现类:BeanListHandler<T> ---将查询的多条记录封装到List集合中,List集合都是当前类对象
public BeanListHandler(Class<T> type)
子实现类:
ScalarHandler:通过聚合函数(count(列名称),其他max(xx),avg(xxx))查询单行单的列的数据的结果封装到Object类中,第三个参数:就是赋值的实际参数params,没有参数可以不写
例子老师
接口类
package com.qf.dao;
import com.qf.pojo.Employee;
import java.sql.SQLException;
import java.util.List;
/**
* @author Kuke
* @date 2023/4/7 11:12
* 针对员工的数据访问接口(持久层)
*/
public interface EmployeeDao {
/**
* 查询所有员工
* @return 返回员工列表
*/
List<Employee> findAll() throws SQLException;
/**
* 根据员工编号查询员工
* @param id 员工编号
* @return 返回员工实体
*/
Employee findEmpById(int id) throws SQLException;
/**
* 查询总记录数
* @return 返回总条数
*/
int getTotalCount() throws SQLException;
}
实体类
package com.qf.pojo;
import java.util.Date;
/**
* @author 高圆圆
* @date 2023/4/7 11:10
* 员工实体
*/
public class Employee {
/**
*
id int(11) NOT NULL
name varchar(10) NULL
gender varchar(3) NULL
age int(11) NULL
salary double NULL
address varchar(20) NULL
birthday date NULL
*/
private int id ;
private String name ;
private String gender ;
private int age ;
private double salary ;
private String adderss ;
private Date birthday;
public Employee() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getAdderss() {
return adderss;
}
public void setAdderss(String adderss) {
this.adderss = adderss;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", salary=" + salary +
", adderss='" + adderss + '\'' +
", birthday=" + birthday +
'}';
}
}
子实现类
package com.qf.dao.impl;
import com.qf.dao.EmployeeDao;
import com.qf.pojo.Employee;
import com.qf.utils.DruidJdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.SQLException;
import java.util.List;
/**
* @author 高圆圆
* @date 2023/4/7 11:13
*/
public class EmployeeDaoImpl implements EmployeeDao {
/**
* 查询所有员工
* @return 返回员工列表
*/
@Override
public List<Employee> findAll() throws SQLException {
//使用apache提供开源工库实现
//创建QueryRunner
//public QueryRunner(DataSource ds)
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "select * from employee" ;
//将查询的多条记录封装List集合,集合List存储每一个员工对象
//public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
//子实现类:BeanListHandler<T> ---将查询的多条记录封装到List集合中,List集合都是当前类对象
List<Employee> list = qr.query(sql, new BeanListHandler<>(Employee.class));
return list;
}
/**
* 根据员工编号查询员工
* @param id 员工编号
* @return 返回员工实体
*/
@Override
public Employee findEmpById(int id) throws SQLException {
//创建执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "select * from employee where id = ?" ;
//执行查询: 将某一条记录封装到实体中
/**
* 它的子实现类:BeanHandler---->将查询的某一条记录封装到实体了中(JavaBean:是具体类,属性私有,对外提供setXXX()/getXXX)
* public BeanHandler(Class<T> type) ---> 参数针对查询的记录--封装到类名.class中
*/
Employee emp = qr.query(sql, new BeanHandler<>(Employee.class), id);
return emp;
}
/**
* 查询总记录数
* @return 返回总条数
*/
@Override
public int getTotalCount() throws SQLException {
//执行对象
QueryRunner qr = new QueryRunner(DruidJdbcUtils.getDataSource()) ;
//sql
String sql = "select count(id) from employee" ;
//将查询的结果:当行单例的数据封装到Object中
/**
* ScalarHandler:通过聚合函数(count(列名称),其他max(xx),avg(xxx))查询单行单的列的数据
* 的结果封装到Object类中
* //public ScalarHandler()
*/
Object object = qr.query(sql, new ScalarHandler<>());
//5----取出来
//前面学的万能转换法 字符串转int
String s = String.valueOf(object);
int totalCount = Integer.parseInt(s);
return totalCount;
}
}
测试类
package com.qf.test;
import com.qf.dao.EmployeeDao;
import com.qf.dao.impl.EmployeeDaoImpl;
import com.qf.pojo.Employee;
import org.junit.Before;
import org.junit.Test;
import java.sql.SQLException;
import java.util.List;
/**
* @author 高圆圆
* @date 2023/4/7 11:13
* 测试
*/
public class EmployeeTest {
private EmployeeDao ed ;
@Before
public void init(){
ed = new EmployeeDaoImpl() ;
}
//查询所有
@Test
public void testFindAll() throws SQLException {
List<Employee> all = ed.findAll();
if(all!=null){
for(Employee emp :all){
System.out.println(emp);
}
}
}
//查询执行员工
@Test
public void testFindEmpById() throws SQLException {
Employee emp = ed.findEmpById(6);
System.out.println(emp);
}
//查询总记录数
@Test
public void testTotalCount() throws SQLException {
int count = ed.getTotalCount();
System.out.println(count);
}
}
例子自己(无注释净化版)
接口类
package com.dao;
import com.pojo.Employee;
import java.sql.SQLException;
import java.util.List;
public interface EmployeeDao {
/**
* 查询所有员工
* @return 返回员工列表
*/
List<Employee> findAll() throws SQLException;
/**
* 根据员工编号查询员工
* @param id 员工编号
* @return 返回员工实体
*/
Employee findEmpById(int id) throws SQLException;
/**
* 查询总记录数
* @return 返回总条数
*/
int getTotalCount() throws SQLException;
/**
* 添加员工
* @param emp 员工实体
*/
void addEmployee(Employee emp) throws SQLException;
/**
* 根据员工id修改员工信息
* @param emp 员工实体
* @throws SQLException
*/
void updateEmployee(Employee emp) throws SQLException ;
/**
* 根据员工姓名模糊查询
* @param name 关键字员工名称
* @return 返回员工列表
*/
List<Employee> findEmpByName(String name) throws SQLException;
}
实体类
package com.pojo;
public class Employee {
private int id;
private String name;
private String gender;
private int age;
private String birthday;
private int salary;
public Employee() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Employee(int id, String name, String gender, int age, String birthday, int salary) {
this.id = id;
this.name = name;
this.gender = gender;
this.age = age;
this.birthday = birthday;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", birthday='" + birthday + '\'' +
", salary=" + salary +
'}';
}
}
子实现类
package com.dao.impl;
import com.dao.EmployeeDao;
import com.pojo.Employee;
import com.utils.DruidJdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.SQLException;
import java.util.List;
public class EmployeeDaoImpl implements EmployeeDao {
@Override
public List<Employee> findAll() throws SQLException {
QueryRunner qr=new QueryRunner(DruidJdbcUtils.getDataSource());
String sql="select * from employee2";
List<Employee> list = qr.query(sql, new BeanListHandler<>(Employee.class));
return list;
}
@Override
public Employee findEmpById(int id) throws SQLException {
QueryRunner qr=new QueryRunner(DruidJdbcUtils.getDataSource());
String sql="select * from employee2 where id=?";
Employee e = qr.query(sql, new BeanHandler<>(Employee.class), id);
return e;
}
@Override
public int getTotalCount() throws SQLException {
QueryRunner qr=new QueryRunner(DruidJdbcUtils.getDataSource());
String sql="select count(id) from employee2";
Object object = qr.query(sql, new ScalarHandler<>());
String s = String.valueOf(object);
int s1 = Integer.parseInt(s);
return s1;
}
@Override
public void addEmployee(Employee emp) throws SQLException {
QueryRunner qr=new QueryRunner(DruidJdbcUtils.getDataSource());
String sql = "INSERT INTO employee2(id,name,gender,age,birthday,salary)values(?,?,?,?,?,?)" ;
int add = qr.update(sql, emp.getId(), emp.getName(), emp.getGender(), emp.getAge(), emp.getBirthday(), emp.getSalary());
System.out.println("影响了"+add+"行");
}
@Override
public void updateEmployee(Employee emp) throws SQLException {
QueryRunner qr=new QueryRunner(DruidJdbcUtils.getDataSource());
String sql="update employee2 set name=? where id=?";
int j = qr.update(sql, emp.getName(), emp.getId());
System.out.println("影响了"+j+"行");
}
@Override
public List<Employee> findEmpByName(String name) throws SQLException {
QueryRunner qr=new QueryRunner(DruidJdbcUtils.getDataSource());
String sql="select * from employee2 where name like ?";
List<Employee> query = qr.query(sql, new BeanListHandler<>(Employee.class),name);
return query;
}
}
测试类
package com.test;
import com.dao.EmployeeDao;
import com.dao.impl.EmployeeDaoImpl;
import com.pojo.Employee;
import org.junit.Before;
import org.junit.Test;
import java.sql.SQLException;
import java.util.List;
public class EmployeeTest {
EmployeeDao ed;
@Before
public void init(){
ed=new EmployeeDaoImpl();
}
@Test
public void testadd() throws SQLException {
Employee e=new Employee();
e.setId(9);
e.setName("路飞");
e.setAge(18);
e.setGender("男");
e.setBirthday("20020304");
e.setSalary(5000);
ed.addEmployee(e);
}
@Test
public void testfindall() throws SQLException {
List<Employee> la = ed.findAll();
System.out.println(la);
}
@Test
public void testFindEmpById() throws SQLException {
Employee empById = ed.findEmpById(3);
System.out.println(empById);
}
@Test
public void testToutleCount() throws SQLException {
int totalCount = ed.getTotalCount();
System.out.println(totalCount);
}
@Test
public void testUpdate() throws SQLException {
Employee e=new Employee();
e.setName("特鲁路");
e.setId(2);
ed.updateEmployee(e);
}
@Test
public void testFindEmpByName() throws SQLException {
List<Employee> empByName = ed.findEmpByName("%飞%");
if(empByName!=null){
for (Employee e:empByName)
System.out.println(e);
}
}
}
TOMCAT安装办法
启动路径:TOMCAT安装路径下的bin目录的startup.bat
必须配置JDK和JRE的环境变量:
高级系统设置:下方的系统环境配置中新建:JAVA_HOME JRE_HOME 路径分别是jdk和jre的安装路径 PATH列表里加入%JAVA_HOME%\bin;和%MYSQL_HOME%\bin; 注意不要置顶 否则path会打不开列表
TOMECAT乱码解决
TOMCAT安装路径下的conf目录的logging.properties 改变里面的java.util.logging.ConsoleHandler.encoding = gbk 最后的编码格式是GBK 而不是UTF-8
开启tomcat服务后编辑: http://你自己的的端口号:8080
常见问题:
1)端口被占用(Erron running'Tomcat8.5.66';
Address localhost:1099 is already in use)解决:
netstat -aon|findstr 1099:查看被那个进程占用
taskkill -f -pid xxxx:杀死该进程 xxxx:被占用的端口号
2)local Falied 问题
试着改下端口号或者再Web项目下新建一个html 报错我感觉可能是没创建文件
3)404问题:
运行tomcat 404 在Web项目下新建Html文件些内容再运行 不能再WEB_INF里运行。默认index 的html文件(tmocat源代码就是这么写的)
Idea部署tomcate 创建web文件图解