系列文章目录
第一章 JAVA集中学习第一周学习记录(一)
第二章 JAVA集中学习第一周项目实践
第三章 JAVA集中学习第一周学习记录(二)
第四章 JAVA集中学习第一周课后习题
第五章 JAVA集中学习第二周学习记录(一)
第六章 JAVA集中学习第二周项目实践
第七章 JAVA集中学习第二周学习记录(二)
第八章 JAVA集中学习第二周课后习题
第九章 JAVA集中学习第二周学习记录(三)
第十章 JAVA集中学习第二周学习记录(四)
第十一章 JAVA集中学习第三周学习记录(一)
第十二章 JAVA集中学习第三周小组项目开发
第十三章 JAVA集中学习第四周学习记录(一)
文章目录
前言
以员工管理系统举例,介绍了数据库,如何在java中对数据库进行操作,如何进行多表查询,如何提取对数据库的操作成为DBHelper类,如何实现分页。
一、员工管理系统
1. 创建数据库、表,添加测试数据:
2. 熟记每张表中每个字段的意思
emp员工表
empno:4位整数的员工编号(自增)
ename:汉字(四个)
job:岗位名称
mgr:经理编号(也是经理员工编号)
hiredate:入职时间
sal:工资
comm:奖金
deptno:部门编号
dept部门表:
deptno:部门编号
dname:部门名称
loc:部门所在地
salgrade工资等级表:
grade:工资等级
losal:同等级的最低工资
hisal:同等级的最高工资
bonus局部信息表(封装数据):
ename:员工名字
job:岗位名称
sal:工资
comm:奖金
3. 创建java项目
导入连接数据库的jar包
4. 介绍sql语句:
sql结构化(面向过程)查询语言
作用: 对数据库里的数据做管理
sql组成部分: DQL、DML、TCL、DCL、DDL
4.1 DQL数据查询语言(查询)
select 字段名1, 表名.字段名2, (所有数据为*(不能用索引)一般不用)
from 表名1, 表名2
where 字段1 = 值 and/or 字段2 = 值(分组前的删选条件)
group by 字段名
having 字段 = 值 and/or 字段2 = 值(分组后的筛选条件)
order by 字段名 [desc/不写为正序] 排序
4.2 DML数据管理语言(增删改)
4.2.1 新增
一次增加多行:不常用
一次增加一行:
insert into 表名(列1, 列2, 列3) values(值1, 值2, 值3)
1、列允许为空,添加的时候可以不给值;不允许为空,必须给值
2、列设为自增:values(null, )自动增加一
3、列设置为默认值:values(default, )
4、如果给表里的所有字段都添加,可以写成insert into 表 values(值1, 值2, 值3)
4.2.2 删除
delete from 表名 where empno = ?
4.2.3 修改
update 表 set 列 = 值, 列 = 值 where 主键 = ?
4.3 TCL事务的控制语言
java程序中的TCL,主要学习什么是事务
4.4 DCL数据控制语言
授予、撤回权限、角色
4.5 DDL数据的定义语言
创建、删除、修改一切数据库对象
5. PreparedStatement执行对象:
executeQuery():执行查询语句,返回类型为ResultSet
executeUpdate():执行增删改语句,返回类型为int(受影响的行数,0为没有受影响)
execute():执行sql语句,返回类型为boolean(sql语句是否正确执行)
原来叫Statement,有隐患“sql注入”,现在都用PreparedStatement
CallableStatement()方法:执行存储过程
为sql命令的?参数赋值:set[类型]
preparedStatement.setString(1, dname);
6. ResultSet结果集对象:
对象.next():判断是否有数据
对象.getString():获取属性值
7. 多表查询的不同种类
1、任务:使用dname查询该部门下员工的所有信息(全部字段)
2、分析字段所处的表:
…dname在dept表
…8个字段在emp表
3、多表查询:
3.1 普通查询:
select e.*, d.dname
from emp e, dept d
where e.deptno = d.deptno and dname = ‘SALES’
3.2 内连接多表查询:
select e.*, d.dname
from emp e inner join dept d on e.deptno = d.deptno(inner join内连接,on表关联)
where dname = ‘SALES’
内连接的两张表,没有主次之分,
所有数据根据关联字段进行判断显示
3.3 外连接多表查询
外连接的两张表有主次之分
主表的数据一定会都显示出来
次表的数据只会显示值对等的
外连接
再查询语句里,出现的第一个表名为左表,第二本表为右表
左外连接:左表是主表,左表数据全显示,右表显示值相等的数据
select e., d.dname
from emp e left join dept d on e.deptno = d.deptno
右外连接:右表是主表,右表数据全显示,左表显示值相等的数据
select e., d.dname
from emp e right join dept d on e.deptno = d.deptno
3.4 关联
关联表中,关联列名字要相同才可以用:
select e.*, d.dname
from emp e inner join dept d using (deptno)
where dname = ‘SALES’
3.5 自然关联
关联表中,关联列名字要相同、类型要相同、字段长度要相同才可以用:
select e.*, d.dname
from emp e natural join dept d
where dname = ‘SALES’
8.Java程序中的对象
实体类对象:entry(不叫pojo了)包里的类,都是对应数据库表的
业务类对象:做参数封装与结果集封装,放在dto包下
dto包下只放业务类对象
9. DBHelper的反射
当我们需要一个对象,但有可能是不同类型时;
当我们需要调用对象的属性,为属性赋值时;
当我们需要调用对象的方法,执行方法时;
我们使用反射,把代码向上提取成一套通用的模板对象
在DBHelper中,我们可能对不同表进行操作,为了不用每个表都要写一个DBHelper方法,我们使用反射来实现DBHelper的多态
1. 使用反射的原理
字节码文件可以视为Class类的对象
我们可以对这个对象进行操作
获得变量类型的4种方式:
Class.forName("全局限定名");
类名.Class;
对象名.getClass();
利用加载器
获得对象: 变量类型对象.newInstance();
获得方法: 变量类型对象.newInstance(方法名);
使用方法: 方法名.invoke(o);
2. 使用全局限定名拿到Class类型对象
Class classOne = Class.forName("entry.Emp");
System.out.println(classOne);
Class classTwo = Emp.class;
System.out.println(classOne==classTwo);
Class classThree = new Emp().getClass();
ClassLoader classLoader = Test.class.getClassLoader();
Class ClassFour=classLoader.loadClass("entry.Emp");
System.out.println(classOne == classTwo);
System.out.println(classTwo == classThree);
System.out.println(classThree == ClassFour);
3. 获得classOne的构造器
Constructor[] constructors = classOne.getConstructors();
Constructor[] declaredConstructors = classOne.getDeclaredConstructors();
Constructor constructor = classOne.getConstructor();
Constructor declaredConstructor = classOne.getDeclaredConstructor();
for (Constructor c :
constructors) {
System.out.println(c);
}
for (Constructor c :
declaredConstructors) {
System.out.println(c);
}
System.out.println(constructor);
System.out.println(declaredConstructor);
Constructor declaredconstructor = classOne.getDeclaredConstructor(Integer.class);
declaredconstructor.setAccessible(true);//暴力破解
Object o1 = declaredconstructor.newInstance(6);
System.out.println(o1);
//如果只想使用共有的无参构造
Object o2 = classOne.newInstance();
System.out.println(o2);
4. 获得classOne的变量
Class classOne = Class.forName("entry.Emp");
Field[] declaredFields = classOne.getDeclaredFields();
System.out.println(Arrays.toString(declaredFields));
Field empno = classOne.getDeclaredField("empno");
System.out.println(empno.getType());
System.out.println(empno.getModifiers());
System.out.println(empno.getName());
empno.setAccessible(true);//告诉虚拟机不用检查修饰符
Object object = classOne.newInstance();
empno.set(object, 3355);
System.out.println(object);
5. 获得classOne的方法
Class classOne = Class.forName("entry.Emp");
Method[] methods = classOne.getMethods();
for (Method m :
methods) {
System.out.println(m);
}
Method toString = classOne.getMethod("toString");
System.out.println(toString.invoke(classOne.newInstance()));
6. 做出通用任何表的DBHelper
//12
public Connection getConcection() {
Connection connection = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3308/employee?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
String username = "root";
String password = "";
connection = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
//e.printStackTrace();
System.out.println("mysq1 驱动类地址不对,没有导入jar,ur1路径不对");
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//7
public void closeAll(ResultSet resultSet, PreparedStatement preparedStatement, Connection connection){
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//45(1-7汇总)传入3,返回6
public ArrayList selectInfo(String sql, Class classOne, Object... objects){
ArrayList list = new ArrayList();
try {
Connection connection = getConcection();
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < objects.length; i++) {
preparedStatement.setObject(++i, objects[i]);
}
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
//根据classOne获得该字节码的对象
Object o = classOne.newInstance();
//给所有对象属性赋值
Field[] declaredFields = classOne.getDeclaredFields();
for (Field f :
declaredFields) {
f.setAccessible(true);
f.set(o, resultSet.getString(f.getName()));
}
list.add(o);
}
return list;
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return null;
}
}
模糊查询:
select * from emp where ename like ‘%M%’
%表示前面可以有,后面也可以有
select * from emp where ename like ‘__M%’
_表示前面有一位,M排在第三位
单行函数: 不做介绍
多行函数:(求总和sum()、求平均数avg()、求最大值max()、求最小值min()、求总个数count()),聚合函数,分组函数
10. 分页查询
1. 分页的方法介绍
sql语句:
SELECT e.*, d.dname FROM emp e NATURAL JOIN dept d where 1 = 1 LIMIT 3, 3
重点是LIMIT 3, 3:第一个3代表从下标为3的元素开始,第二个3表示只显示三个 (其实不是分页的作用,但能实现分页功能)
五要素:
1、每页显示几条数据
2、一共多少条数据
3、一共能分几页
4、当前是第几页
5、当前页的显示的数据集合
2. 分页的代码实现
PageHelper分页工具类:
public class PageHelper {
private Integer showData = 3;//每页显示几条数据
private Integer countData;//一共有多少条数据,需要查数据库
private Integer countPage;//一共能分多少页
private Integer indexPage = 1;//当前是第几页,默认为第一页
private ArrayList<EmpDname> list;//当前页的数据集合
public PageHelper(Integer showData, Integer countData, Integer countPage, Integer indexPage, ArrayList<EmpDname> list) {
this.showData = showData;
this.countData = countData;
this.countPage = countPage;
this.indexPage = indexPage;
this.list = list;}
public PageHelper() {}
public Integer getShowData() {return showData;}
public void setShowData(Integer showData) {this.showData = showData;}
public Integer getCountData() {return countData;}
public void setCountData(Integer countData) {
this.countData = countData;//直到总条数之后,立刻能知道总页数了
getCountPage();}
public Integer getCountPage() {
countPage = countData % showData == 0 ?
countData / showData :
countData / showData + 1;
return countPage;}
/* public void setCountPage(Integer countPage) {
this.countPage = countPage;
}*/
public Integer getIndexPage() {return indexPage;}
public void setIndexPage(Integer indexPage) {this.indexPage = indexPage;}
public ArrayList<EmpDname> getList() {return list;}
public void setList(ArrayList<EmpDname> list) {this.list = list;}
}
Dao层应用(动态查询):
@Override
public ArrayList<EmpDname> getEmpsByDname(QueryEmpDept queryEmpDept, PageHelper pageHelper) {
//根据部门名称,查询该部门下所有员工信息
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
StringBuffer sql = new StringBuffer("select e.*, d.dname from emp e natural join dept d where 1 = 1");
ArrayList list = new ArrayList();
if (queryEmpDept.getEmpno() != null){
sql.append(" and empno = ?");
list.add(queryEmpDept.getEmpno());
}if (queryEmpDept.getEname() != null){
sql.append(" and ename like ?");
list.add("%" + queryEmpDept.getEname() + "%");
}if (queryEmpDept.getDname() != null){
sql.append(" and dname = ?");
list.add(queryEmpDept.getDname());
}if (queryEmpDept.getBegindate() != null){
sql.append(" and ? <= hiredate");
list.add(sdf.format(queryEmpDept.getBegindate()));
}if (queryEmpDept.getEnddate() !=null){
sql.append(" and hiredate <= ?");
list.add(sdf.format(queryEmpDept.getEnddate()));
}
sql.append(" limit ?, ?");
list.add((pageHelper.getIndexPage() - 1) * pageHelper.getShowData());
list.add(pageHelper.getShowData());
return (ArrayList<EmpDname>) dbHelper.selectInfo(sql.toString(), EmpDname.class, list.toArray());
}
Service层应用:
@Override
public ArrayList<EmpDname> getEmpsByDname() throws ParseException {
QueryEmpDept queryEmpDept = getQuery();
PageHelper pageHelper = new PageHelper();
pageHelper.setCountData(empDao.selectEmpsSize(queryEmpDept));
ArrayList<EmpDname> empsByDname1 = empDao.getEmpsByDname(queryEmpDept, pageHelper);
Iterator<EmpDname> iterator1 = empsByDname1.iterator();
while (iterator1.hasNext())
System.out.println(iterator1.next());
int i = 1, a;
while (i != 0){
System.out.println("是否显示下一页,输入0退出");
a = scanner.nextInt();
if (a != 0){
pageHelper.setIndexPage(i);
ArrayList<EmpDname> empsByDname = empDao.getEmpsByDname(queryEmpDept, pageHelper);
Iterator<EmpDname> iterator = empsByDname.iterator();
while (iterator.hasNext())
System.out.println(iterator.next());
i++;
}
else break;
}
return null;
}
总结
本文以员工管理系统为例,介绍了数据库SQL语言的组成部分、基础使用,介绍了如何进行多表查询,如何使用反射构建所有表通用的DBHelper类,如何构建PageHelper类实现分页功能。想要去ൠ♄§星的人抓紧定票,不要赶不上200年后ൠ♄§星与地球之间的首次通车。