1) 集合框架 :
常见的接口和类,以及方法;
Collection
List(有序,可以重复):
ArrayList LinkedList Vector
Set(无序,不能重复):
HashSet TreeSet
Map:键和值
HashMap:
简单的泛型: ArrayList
Iterator: 迭代器
Arrays.sort() ;
2) 数据库:MySQL,数据库有关概念;数据库软件的安装,创建库,表操作;常见的SQL(结构化查询语言)语句 ;重点要掌握的是: 查询语句(基本查询,带条件的查询,排序,分组,分组后的筛选,表联结,模糊查询)
3) 应用程序+数据库: java语言中有一种操作数据库的技术,JDBC;
4) JDBC有关的常见接口和类:
Java.sql.DriverManager:
驱动管理器.创建连接对象; DriverManager.getConnection(url,user,password);
Java.sql.Connection:
连接对象,用来创建[预]处理对象:[ PreparedStatement] conn.prepareStatement(sql语句);
Java.sql.PreparedStatement:
用来执行实际的数据库访问操作:
setXX(index,value) ;// 设置参数,index =>1开始
int n=executeUpdate(); //执行 增加 删除 修改
ResultSet rs=executeQuery(); //执行 查询操作
释放资源:
PreparedStatement => close();
Connection =>close()
1) 设计一个网吧计费系统设计(用户表 计算机表 上机记录表),同时模拟添加(用户注册)用户,计算机(添加设备),用户上机,换机,下机操作,用sql完成. [电子版作业发我邮箱]
修改后的表结构: (参考 ,感谢佩琪的友情提供
用户表cybercafeUser netbar
列名 類型 說明
cyber_userid int 用戶編號,自动增长,主键
cyber_username varchar(20) 用戶姓名
cyber_password varchar(32) 用户密码
cyber_regDate datetime 用户注册时间
cyber_balance double 用户余额
计算机表cybercafePC
列名 類型 說明
cyber_pcid int 電腦編號,自动增长,主键
cyber_pcdesc varchar(50) 電腦描述
cyber_pcstatus int 电脑的状态,0 空闲,1使用中
上机记录表 cybercafeRecord
列名 類型 說明
cyber_recid int 紀錄編號,自动增长,主键
cyber_pcid int 使用的電腦編號,关联的是pc表中的pcid
cyber_userid int 用戶編號,关联的是用户表中的 userId
cyber_beginTime datetime 用戶上机時間
cyber_endTime datetime 用戶下机時間
cyber_fee Double 上机的费用
-- 添加(用户注册)用户
select * from cyberusers;
insert into cyberusers values(null,'admin','123456',now(),10);
insert into cyberusers values(null,'user01','qqqqqqq',now(),100);
insert into cyberusers values(null,'user02','qqqqq',now(),1000);
insert into cyberusers values(null,'user03','qq',now(),150);
insert into cyberusers values(null,'user04','qqqq',now(),50);
insert into cyberusers values(null,'user05','12qwqwq',now(),70);
-- 计算机(添加设备),
select * from cyberpc;
insert into cyberpc values(null,'512固态,16G内存,飞一般的享受',0);
insert into cyberpc values(null,'512固态,8G内存,飞一般的享受',0);
insert into cyberpc values(null,'512固态,4G内存,飞一般的享受',0);
insert into cyberpc values(null,'512固态,2G内存,飞一般的享受',0);
insert into cyberpc values(null,'512固态,1G内存,飞一般的享受',0);
-- 用户上机,换机,下机操作
-- 谁? 使用哪台机器? 增加了一条记录?
-- admin (1)这个用户 编号为 1 那台机器 ,上机时间应该为 now()
-- ①验证这个人是否存在 [验证密码]
select * from cyberusers where cyber_username = 'admin'; --1
-- ② 要使用的是1台机器 ,要验证一下这台机器是否有人使用
select cyber_pcstatus from cyberpc where cyber_pcid = 1 ;
-- ③ 插入记录
select * from cyberrecord
insert INTO cyberrecord values(null,1,1,now(),null,2); -- 2表示的上机就要记录2元,但是还没有扣钱,等结账的时候才扣钱
-- ④ 插入记录表之后,明确,第一台电脑已经被admin使用了,所以pc表中的记录状态要发生改变
update cyberpc set cyber_pcstatus = 1 where cyber_pcid = 1;
-- 换机 admin用1号机器 不爽,我要换到5号机器,
-- ① 要使用的是5台机器 ,要验证一下这台机器是否有人使用
select cyber_pcstatus from cyberpc where cyber_pcid = 5 ;
-- 修改记录表 pcId
update cyberrecord set cyber_pcid = 5 where cyber_recid =1;
-- 或者 pcId =1 and endtime is null
update cyberrecord set cyber_pcid = 5 where cyber_pcid =1 and cyber_endtime is null;
-- 修改我们计算机表 pcid为1的状态为0 5的状态为1
update cyberpc set cyber_pcstatus = 0 where cyber_pcid = 1;
update cyberpc set cyber_pcstatus = 1 where cyber_pcid = 5;
select * from cyberrecord;
select * from cyberpc;
select * from cyberusers;
-- 下机操作
-- 下机 admin用5号机器用完了,要去约会了,下机
-- 扣钱 (按小时来扣钱 1小时2元)
-- ① 修改下机记录 为当前时间
update cyberrecord set cyber_endtime = now() where cyber_recid =1;
-- ② 计算一下 本次上机 上机时间 下机时间差值 ->小时 *2
-- 思考问题 解决问题(mysql 计算两个时间的差值?)
-- 直接做计算 减法 得到是秒差值 不好计算为小时
select cyber_endtime - cyber_begintime from cyberrecord;
-- mysql 计算两个时间的差值 用到mysql中的函数
select TIMESTAMPDIFF(HOUR,'2018-01-01','2018-01-01 12:01')
select TIMESTAMPDIFF(HOUR,cyber_begintime,cyber_endtime) from cyberrecord where cyber_recid = 1;
-- 如果计算差值 hour 为0 表示不满1小时 ;如果不满1小时,我们什么都不做(不用再更新record表)
-- ③ 将计算的结果 写入记录表(更新)
-- ④ 扣钱 用户表中的balance -
select cyber_userId,cyber_fee from cyberrecord where cyber_recid = 1;
update cyberusers set cyber_balance = cyber_balance - 2 where cyber_userid = 1;
select * from cyberusers;
-- ⑤ 计算机表中的状态要变 5号=>1 =>0
update cyberpc set cyber_pcstatus = 0 where cyber_pcid =5 ;
-- 扩展 MySQL 的函数
select now();
select ABS(-1);
-- datediff 得到的是两个时间之间差值(天数的部分) 第一个参数 - 第二个参数
select DATEDIFF('2018-01-01',now());
select DATEDIFF(now(),'2018-01-01');
-- unit year ,month,day ,HOUR 等等
-- datetime_expr1 第一个时间的值 小
-- datetime_expr2 第二个时间的值 大
select TIMESTAMPDIFF(HOUR,'2018-01-01','2018-01-01 12:01')
2) 回去完成 员工的添加,删除,修改操作; 从控制台输入进来;
package testJdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;
/**
* 删除操作的代码
*
* @author Administrator
*
*/
public class TestDeleteDept {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
// ① : 创建url user password
String url = "jdbc:mysql://localhost:3306/companydb";
String user = "root";
String password = "root";
// ② 建立一个连接
// 两个对象 Connection DriverManager
// url - jdbc:subprotocol:subname 形式的数据库 url
Connection conn = DriverManager.getConnection(url, user, password);
// 使用conn
// System.out.println(conn);
// 使用conn对象得到一个 执行sql语句的对象 statement/preparedstatement
// ③ 编写sql语句 这里我们要操作MySQL数据库
// 控制台输入
Scanner input = new Scanner(System.in);
System.out.println("请输入部门编号");
// 这列deptNo写什么类型?
// 最好写和表中列类型一致 int->int varchar->String
// 此时 也可以写成String =->sql语句在执行的时候要拼接
// String deptNo = input.next();
int deptNo = input.nextInt();
// 方式2 字符串拼接
String sql = "delete from dept where deptno =?";
// ④ 通过连接对象得到 PreparedStatement
PreparedStatement pstmt = conn.prepareStatement(sql);
// 用输入进来的值和我们的 ?匹配 推荐使用
// 匹配 ,注意注意注意,索引从1开始
pstmt.setInt(1, deptNo);
// ⑤ 执行增删改 ,并处理结果
int n = 0;
try {
n = pstmt.executeUpdate();
} catch (MySQLIntegrityConstraintViolationException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
System.out.println("数据库表关联关系异常(外键),请联系管理员");
} finally {
// ⑥ 释放资源
if (null != pstmt)
pstmt.close();
// 连接放在最后来释放
if (null != conn)
conn.close();
}
if (n > 0)
System.out.println("删除成功");
else
System.out.println("删除失败");
}
}
修改操作代码:
package testJdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;
/**
* 修改操作的代码
*
* @author Administrator
*
*/
public class TestUpdateDept {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
// ① : 创建url user password
String url = "jdbc:mysql://localhost:3306/companydb";
String user = "root";
String password = "root";
// ② 建立一个连接
// 两个对象 Connection DriverManager
// url - jdbc:subprotocol:subname 形式的数据库 url
Connection conn = DriverManager.getConnection(url, user, password);
// ③ 编写sql语句 这里我们要操作MySQL数据库
// 控制台输入
Scanner input = new Scanner(System.in);
System.out.println("请输入要修改的部门编号");
// 这列deptNo写什么类型?
// 最好写和表中列类型一致 int->int varchar->String
// 此时 也可以写成String =->sql语句在执行的时候要拼接
// String deptNo = input.next();
int deptNo = input.nextInt();
System.out.println("要修改哪一项(1 部门名称 2 部门描述 3 名称+描述)");
// 要修改什么? 部门名称,部门描述
String choice = input.next();
String deptName = null, deptDesc = null;
String sql = "update dept set deptName=? where deptNo = ?";
switch (choice) {
case "1":
System.out.println("请输入部门名称");
deptName = input.next();
break;
case "2":
System.out.println("请输入部门描述");
deptDesc = input.next();
sql = "update dept set deptDesc=? where deptNo = ?";
break;
case "3":
System.out.println("请输入部门名称和描述");
deptName = input.next();
deptDesc = input.next();
sql = "update dept set deptName=?,deptDesc=? where deptNo = ?";
break;
}
// ④ 通过连接对象得到 PreparedStatement
PreparedStatement pstmt = conn.prepareStatement(sql);
// 用输入进来的值和我们的 ?匹配 推荐使用
// 匹配 ,注意注意注意,索引从1开始
if (null != deptName && null == deptDesc) // 用户输入了deptName ,deptDesc为空
{
pstmt.setString(1, deptName);
pstmt.setInt(2, deptNo);
} else if (null == deptName && null != deptDesc) // 用户输入了deptDesc,deptName 为空
{
pstmt.setString(1, deptDesc);
pstmt.setInt(2, deptNo);
} else if (null != deptName && null != deptDesc) {
pstmt.setString(1, deptName);
pstmt.setString(2, deptDesc);
pstmt.setInt(3, deptNo);
}
// 题外话: 如果觉得以上的判断太多了,就直接写一条sql
// ⑤ 执行增删改 ,并处理结果
int n = 0;
try {
n = pstmt.executeUpdate();
} catch (MySQLIntegrityConstraintViolationException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
System.out.println("数据库表关联关系异常(外键),请联系管理员");
} finally {
// ⑥ 释放资源
if (null != pstmt)
pstmt.close();
// 连接放在最后来释放
if (null != conn)
conn.close();
}
if (n > 0)
System.out.println("修改成功");
else
System.out.println("修改失败");
}
}
3) 回去预习 查询的操作;
在Navicate 中数据库上点击右键->转储sql [结构和数据 ;结构] -> 生成一个.sql文件:
继承了Statement接口; 预编译的sql对象;所以可以更高效执行sql; 提供了setxx的方法来设置参数;它更安全; 可以避免sql注入
Statement
是PreparedStatement对象的父接口;静态的非预编译;比较低效率;因为静态,不能提供 ?参数写法,只能用字符串的拼接方式,无法避免sql的注入,相对不够安全;
高版本的Mysql驱动:例如:
就可以省略Class.forName这个加载驱动的动作;
去看看我们加载到项目中的那个jdbc驱动包;
下载jdbc驱动的源码包:
Com.mysql.jdbc.Driver: 的源码
所以,我们只要让我们的静态代码段能执行,就可以
Mysql驱动包的高版本和低版本的不同:
5.1.5
5.1.18 :我们发现,5.1.5多了个services录;java.sql.Driver文件
在jdk中有个特性: SPI(服务提供接口) => 所以JVM会将 jar包Meta-Inf\Services\某个接口中所定义的那个类自动加载到JVM;
所以,高版本的jdbc驱动不需要写 Class.forName(…);
部门增加 删除和修改操作; 如果删除部门的时候,有关联的那个部门(有员工)信息,提醒用户该部门下有员工,是否删除?如果用户输入是,我们就先删除员工表的对应记录,然后将部门表对应那个信息删除;
重点代码段:
/**
* 查询代码
* @author Administrator
*
*/
public class TestQuery01 {
public static void main(String[] args) {
// 加载驱动(5.1.18 可以省略)
// url user password
// /jdbc:mysql://localhost:3306/mydb?useunicode=true&characterEncoding=utf-8....
String url = "jdbc:mysql://localhost:3306/companydb";
String user = "root";
String password = "root";
// 准备sql语句
String sql = "select deptNo,deptName,deptDesc from dept";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
// 通过DriverManager类得到Connection对象
try {
conn = DriverManager.getConnection(url, user, password);
// 通过connection对象得到PreparedStatement
pstmt = conn.prepareStatement(sql);
// 通过preparedStatement对象执行sql
rs = pstmt.executeQuery();
// 遍历 next getxx
// 得到结果要做处理?
while (rs.next()) {
// 一行记录拼接在info中
// getXX(查询语句列名) getXX(索引)
String info = rs.getInt("deptNo") + "," + rs.getString(2) + "," + rs.getString(3);
System.out.println(info);
}
// executeUpdate() executeQuery
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
// 释放资源
// result
if (null != rs)
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// preparedstatement
if (null != pstmt)
try {
pstmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// connection
if (null != conn)
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
getInt(列索引或者列名称); //参数应该是我们查询语句中对应的那个列
1) 查询部门表中的所有数据
2) 查询员工表中的某个部门中的数据(dept 1)
package query;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
/**
* 查询代码
*
* @author Administrator
*
*/
public class TestQuery_Employee {
public static void main(String[] args) {
// 加载驱动(5.1.18 可以省略)
// url user password
// /jdbc:mysql://localhost:3306/mydb?useunicode=true&characterEncoding=utf-8....
String url = "jdbc:mysql://localhost:3306/companydb";
String user = "root";
String password = "root";
// 准备sql语句
String sql = "select empno,empName,salary as sal,status from employee where deptno = ?";
System.out.println("请输入您要查询的部门编号(列出这个部门下的员工信息)");
Scanner input = new Scanner(System.in);
int deptNo = input.nextInt();
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
// 通过DriverManager类得到Connection对象
try {
conn = DriverManager.getConnection(url, user, password);
// 通过connection对象得到PreparedStatement
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, deptNo);
// 通过preparedStatement对象执行sql
rs = pstmt.executeQuery();
// 遍历 next getxx
// 得到结果要做处理?
while (rs.next()) {
// 一行记录拼接在info中
// getXX(查询语句列名) getXX(索引)
String info = rs.getInt("empno") + "," + rs.getString("empName") + "," + rs.getString("sal") + ","
+ rs.getString("status");
System.out.println(info);
}
// executeUpdate() executeQuery
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
// 释放资源
// result
if (null != rs)
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// preparedstatement
if (null != pstmt)
try {
pstmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// connection
if (null != conn)
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
3) 查询部门表和员工表中的数据
员工姓名 部门
小a 行政部
我们的代码的问题是: 所有的执行都在一个main中,这样一定是不行的;
所以需要拆开,我们以query-Employee为案例:
1. 根据表结构创建一个实体类
package com.etc.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.etc.entity.Employee;
/**
* 数据库的访问操作 增 删 修改 查 ,这个dao还不是最终的dao,明天再优化,要体会这种分层的思想
*
* @author Administrator
*
*/
public class EmployeeDao {
// 暂时放在这里
String url = "jdbc:mysql://localhost:3306/companydb";
String user = "root";
String password = "root";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
// 查询 的结果要返回
public List queryAll() {
List list = new ArrayList<>();
String sql = "select empno,empName,deptNo,salary as sal,status from employee";
try {
conn = DriverManager.getConnection(url, user, password);
// 通过connection对象得到PreparedStatement
pstmt = conn.prepareStatement(sql);
// 通过preparedStatement对象执行sql
rs = pstmt.executeQuery();
// 遍历 next getxx
// 得到结果要做处理?
Employee emp = null;
while (rs.next()) {
// 一行记录拼接在info中
// getXX(查询语句列名) getXX(索引)
int empNo = rs.getInt("empno");
String empName = rs.getString("empName");
double salary = rs.getDouble("sal");
int status = rs.getInt("status");
int deptNo = rs.getInt("deptNo");
// 构造一个Employee对象
emp = new Employee(empNo, empName, deptNo, salary, status);
// 将emp对象添加到集合中来
list.add(emp);
}
// executeUpdate() executeQuery
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
// 释放资源
// result
if (null != rs)
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// preparedstatement
if (null != pstmt)
try {
pstmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// connection
if (null != conn)
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return list;
}
}
package com.etc.test;
import java.util.List;
import com.etc.dao.EmployeeDao;
import com.etc.entity.Employee;
public class TestQueryEmployee {
public static void main(String[] args) {
// TODO Auto-generated method stub
EmployeeDao empdao = new EmployeeDao();
List list = empdao.queryAll();
for (Employee employee : list) {
System.out.println(employee);
}
}
}
1) 回顾中:模拟一些网吧业务;jdbc加载驱动;
2) JDBC的接口和类: java.sql.ResultSet ; 常见属性和方法: next() getXX的方法
3) 分层思想: 数据库的访问集中到一个类中 Dao
将今天的Dao 部分再优化和简单的封装;