分页查询:
假分页/逻辑分页/内存分页
一次性查询出所有的数据,存放到内存中(集合),每次翻页的时候,都是从内存中取出的指定条数
特定:翻页比较快.如果数据量过大,可以回造成内存溢出
真分页/物理分页/数据库分页
每次翻页都是从数据库中截取指定的条数,
假设每页10条数据,
第一页查询0-9条 ,第二页 10-19 ....
分页:
语法:select * from 表名 LIMIT ? , ?;
第一个参数 ? (当前页数 -1) * 当前页数要显示的数据条数
第二个参数 ? 代表的是实际页数要显示的数据条数(这一页要显示多少数据)
第一页SELECT * FROM product LIMIT 0, 3 --> 0,1,2
第二页SELECT * FROM product LIMIT 3, 3 --> 3,4,5
第三页SELECT * FROM product LIMIT 6, 3 --> 6,7,8
9, 3 ---> 9,10,11
12, 3 ---? 12,13,14
书写循序: select -- from -- where -- group by -- [having -- order by] -- limit
ps:执行循序:
from --> where -->group by --> having --> select ---> order by --> limit
------------------------------------------------------------------------------------------------
统计函数
操作一组数据,并返回一个值
COUNT 统计结果记录数
MAX 统计最大值
MIN 统计最小值
SUM 求和
AVG 平均值
需求: 查询所有商品的平均零售价格
select AVG(salePrice) from product;
需求:查询所有商品记录
select COUNT(id) from product;
需求:查询分类为2的商品总数
select COUNT(id) from product where dir_id=2;
需求:查询产品的最小零售价格,最高零售价格及所有商品的总零售价格
select MIN(salePrice),MAX(salePrice),SUM(salePrice) from product;
-----------------------------------------------------------------------------------
多表查询
单表查询:从一张表中查询所有数据
多表查询:从多张表中连个查询出数据
为什么要进行多表查询:
例如:当前这个商品表中dir_id描述当前商品信息,通过dir_id将所有的商品详细信息查询出来
多表查询-->联合查询
ps:多表查询最多就是2张表查询
语法:
select 列 from 表A,表B;
多表联合查询会出现的问题
出现一个问题
通过select * from product ,productdir
查询两个表数据时,实际应该显示的条数应该是24条 因为商品表中20条 商品详细信息中 4条件
实际显示的数据 80条 , 20条数据和4数据没有都展示了一遍
这个80条数据其实是错误--> 笛卡尔积
数学中的定义: A={a,b} b={0,1,2} 两个集合的笛卡尔积;
{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}
ps:所谓的笛卡尔积就是包含集合中任意取出两个元素进行组合
避免笛卡尔积的出现
等值赋值 --> 等值连接
两个表中相关联的两个列,彼此作为等值连接即可以避免笛卡尔积
----------------------------------------------------------------------------------------------
外键约束:
主键(PRIMARY KEY):约束当前表中指定的类非空唯
外键(FOREIGN KEY):A表中的外键列的值必须是B表中的主键类的值
dir_id --> id 要产生关系 --> 外键约束
若数据库中的表要支持外键,那么就需要当前表中使用存储引擎InnoDB
更改两个变量中存储引擎
alter table product ENGINE='innodb'; / 'myisam'
alter table productdir ENGINE='innodb';
通过工具dir_id 和 id 进行外键约束关联
product这张表中可以看到
外键名称 外键 约束
CONSTRAINT `product_ibfk_1` FOREIGN KEY (`dir_id`) REFERENCES `productdir` (`id`)
ps:
一般开发在定义外键时习惯使用 表名和列名作为外键的名称
引用表_引用的类名 dir_id --> 外键(个人习惯)
开发中一般我们为了高性能会故意删除外键约束,此时我们可以通过java代码进行合理性约
多表查询:
内连接查:是相对于外练级诶
内连接查询分为两种
隐式内连接查询
select 列 from 表A,表B where A表.列 = B表.列
显示内连接查询
select 列 from 表A JOIN 表B ON A表.列=B表.列
#需求: 查询货品id,货品名称,货品所属分类名称
SELECT product.id,productName,dirName
FROM product,productdir
WHERE product.dir_id = productdir.id;
#可以使用别名的方式来
SELECT p.id,p.productName,pd.dirName
FROM product AS p,productdir AS pd
WHERE p.dir_id = pd.id;
#需求: 查询零售价大于200的无线鼠标
SELECT productName,salePrice,dirName
FROM product,productdir
WHERE product.dir_id = productdir.id AND product.salePrice>= 200 AND productdir.dirName = '无线鼠标';
#需求: 查询零售价大于200的无线鼠标(使用表的别名)
SELECT productName,salePrice,dirName
FROM product AS p,productdir AS pd
WHERE p.dir_id = pd.id AND p.salePrice>= 200 AND pd.dirName = '无线鼠标';
#需求: 查询每个货品对应的分类以及对应的库存
SELECT productName,salePrice,dirName,storeNum
FROM product,productdir,productstock
WHERE product.dir_id = productdir.id AND product.id = productstock.product_id;
#需求: 如果库存货品都销售完成,按照利润从高到低查询货品名称,零售价,货品分类(三张表)
SELECT productName,salePrice,dirName,(salePrice - costPrice)*storeNum
FROM product,productdir,productstock
WHERE product.dir_id = productdir.id AND product.id = productstock.product_id
ORDER BY (salePrice - costPrice)*storeNum DESC;
------------------------------------------------------------------------------------------------
Mysql的自身备份
1.通过cmd --> dos窗口
1.导出数据库
mysqldump -u用户名 -p密码 数据库名称 > 磁盘路径
2.导入数据库
mysql -u用户名 -p密码 数据库名称 < 路径
ps:一般备份的数据库都是以.sql作为结尾的(根据不同的数据库有可能不同)
2.使用工具
-------------------------------------------------------------------------------------------
JDBC概述:
持久化:将数据保存到内存或磁盘中
数据保存到:
内存中:断电之后,数据没了
磁盘中:断了了点 ,数据依旧存在
ps:只要是磁盘读写操作就会产生IO-->就会出现时间的损耗
大多数情况下,特别是企业级医用数据持久化都是将数据存储到硬盘上
还有一种轻量级数据固化: --> XML 配置文件
ps:Hibernate --> 数据库的框架 就是使用了 XML 和 注解进行配置
在Java中数据库可以用代码进行存取操作需要通过一个技术来完成JDBC
通过JDBC访问数据的
1.直接使用JDBC的API取访问数据库服务器
2.直接的使用JDBC的API 取访问数据库服务器,但是JDBC会被封装到第三方工具中
Hibernate, MyBatis(依旧是JDBC)
JDBC:是一种用于执行SQL语句的java API,可以为多种关系型数据库提供统一的访问方式
它由一组java语言编程的类和接口注册,JDBC提供了一种标准,据此可以构建更高级的工具
和接口,使数据库开发人员能够更加便捷的开发数据库应用程序
ps:图解释,因为JDBC本身就是java连接数据库的一个标准,进行数据库的连接,因为市面上有很多不同的
数据库厂商 ,为了宝成JDBC可以对其数据库进行操作,厂商需要提供字节的驱动程序来帮组JDBC对数据库的连接
JDBC版本:
JDBC隶属于JavaSE范畴,伴随着JavaSE的升级而升级
Java6开始JDBC4.0 -->无序加载注解驱动
Java7开始JDBC4.1
JDBC5.1.36
JDBC是可以在javaAPI中查找到了,封装JDBCAPI的包是java.sql包
我们运用的API全部来源于java.sql包下,绝对不能出现来来自于驱动包的数据
千万不要引入 coom.mysql.xxx类 ---> 都是驱动包的
------------------------------------------------------------------------------------------
获取数据的连接:
1.将Mysql的驱动包拷贝到项目中
2.build path 将jar加载到当前工程中
先找到jar通过鼠标右键,build path --> add to build path
DriverManager类 获取当前数据库的连接
getConnection("jdbc:mysql://IP地址:3306/数据库名", "数据库用户名", "密码");
静态方法 得到一个Connection对象
Connection接口 --> JDBC和数据库之间执行SQL语句
完成代码书写
看ConnDome包
/** * */ package com.qfedu.Day27_JDBC.ConnDome; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * Description: 完成数据库的连接操作<br/> * Copyright (c) , 2018, JK <br/> * This program is protected by copyright laws. <br/> * Program Name:ConnectionJDBCDemo.java <br/> * * @author 千锋智哥 * @version : 1.0 */ public class ConnectionJDBCDemo { public static void main(String[] args) { try { //虽然在JDBC4.0之后可以不再使用驱动加载,直接用类来获,但是为了规范建议大家还是书写加载驱动 //ps:为什么要加载驱动就是为了将当前驱动添加到JVM中 //1.加载驱动 Class.forName("com.mysql.jdbc.Driver"); //2.建立连接 /* * 1.连接数据库路径 url: jdbc:mysql://本地安装mysql的IP:3306/3307/数据库 * 2.用户名 * 3.密码 */ Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "123456"); System.out.println(conn); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
--------------------------------------------------------------------------------------------
完成JDBC的相关操作
操作步骤:
1.加载注册驱动
2.获取连接对象
3.创建/获取语句对象
4.执行SQL
5.释放资源
DDL操作:
通过JDBC对数据库的操作完成建表
SQL:
create table t_student(
id BIGINT PRMARY KEY AUTO_INCREMENT,
name varchar(50),
age INT
);
1.获取连接对象 2.通过这个连接对象创建一个student 3.关闭连接
DML操作
DQL操作
看CRUD包
/** * */ package com.qfedu.Day27_JDBC.CRUD; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import org.junit.Test; /** * Description:测试类<br/> * Copyright (c) , 2018, JK <br/> * This program is protected by copyright laws. <br/> * Program Name:CRUDDemo.java <br/> * * @author 千锋智哥 * @version : 1.0 */ public class CRUDDemo { /** * 建表语句 DDL */ @Test public void testCreateTable()throws Exception{ //1.需要写入一个SQL 创建一张表student表 字段有id 主键自增长 name age String sql = "create table t_student(id BIGINT PRIMARY KEY AUTO_INCREMENT,name varchar(50),age INT)"; //加载当前注册驱动 Class.forName("com.mysql.jdbc.Driver"); //获取连接对象 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "123456"); //通过连接对象创建数据库中建表语句对象 Statement st = conn.createStatement(); //执行SQL 参数是字符串 --> SQL语句 //返回值是若是0时没有实际返回的建表语句 , 行数 insert update delete返回行数 int rows = st.executeUpdate(sql); System.out.println(rows); //释放资源 st.close(); conn.close(); } /** * *DML向Student表中进行插入,修改和删除学生信息 *需要向student插入一套数据名字是 提莫,28 / 伊芙蕾雅 18 *更新id为2的名字和年龄 *删除 id为1的数据 */ @Test public void testZSG()throws Exception{ //插入语句 String Isql_1 = "insert into t_student(name,age)values('提莫',28)"; String Isql_2 = "insert into t_student(name,age)values('伊芙蕾雅',18)"; //更新语句 String Usql = "update t_student set name='小苍',age=34 where id=2"; //删除 String Dsql = "delete from t_student where id=1"; //加载注册驱动 Class.forName("com.mysql.jdbc.Driver"); //获取连接对象 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "123456"); //创建操作SQL语句对象 Statement st = conn.createStatement(); //执行SQL //执行插入的 int rows = st.executeUpdate(Isql_1); //执行更新 // int rows = st.executeUpdate(Usql); //执行删除 // int rows = st.executeUpdate(Dsql); System.out.println(rows); //释放对象 st.close(); conn.close(); } /** * DQL操作 * 查询表中有多少条数据 * * ResultSet 接口可以表示数据库的结果集,通过执行查询语句才能获取这个对象 * * ResultSet对象会将光标放在数据的第一行 * 通过next方法将光标向下移动 * 若查询结果中还有值 就会返回true * 若查询结果中没有值 就会返回false * * * * * * */ @Test public void testgetCount()throws Exception { //SQL语句 String sql = "select COUNT(id) as count from t_student"; //加载驱动 Class.forName("com.mysql.jdbc.Driver"); //获取数据库连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "123456"); //创建执行SQL语句对象 Statement st = conn.createStatement(); //通过SQL执行语句对象此时可以获取一个{结果集}对象 ResultSet rs = st.executeQuery(sql); if(rs.next()) { //这里会有一套对应的方法-->若向获得大数据就需要调用getXXX方法 //当前列的数据类型是什么 get后面就是什么 BIGINT --> Long varchar --> String INT --> int // long totalCount = rs.getLong(1);//第一列 long totalCount = rs.getLong("count");//列的名字 System.out.println(totalCount); } //释放 rs.close(); st.close(); conn.close(); } /** * 查询id为2的学生信息 */ @Test public void testGetStudentInfos()throws Exception{ //SQL语句 String sql = "select * from t_student where id=2"; //加载驱动 Class.forName("com.mysql.jdbc.Driver"); //获取数据库连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "123456"); //创建执行SQL语句对象 Statement st = conn.createStatement(); //通过SQL执行语句对象此时可以获取一个{结果集}对象 ResultSet rs = st.executeQuery(sql); //若查询的表中有多条数据,此时就不能使用if作为条件,其实这个位置最常用就是while while(rs.next()) { //获取值时对应的列式什么类型就转换为什么类型 //get方法获取数据时最好的而方法就是传入对应的列 long id = rs.getLong("id"); String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println(id+","+name+","+age); } //释放 rs.close(); st.close(); conn.close(); } }
---------------------------------------------------------------------------------------------
件生命周期:
软件生命周期: 软件的产生直到报废的整个过程.
软件生命周期内有:问题定义, 可行性分析, 总体描述, 系统设计,编码, 调试和测试, 验收与运行, 维护升级到废弃等阶段
1):问题的定义及规划: 此阶段是软件开发方与需求方共同讨论,主要确定软件的开发目标及其可行性。
2):需求分析: 在确定软件开发可行的情况下,对软件需要实现的各功能进行详细分析。需求分析阶段是一个很重要的阶段,这一阶段做得好,将为整个软件开发项目的成功打下良好的基础。
3):软件设计: 此阶段主要根据需求分析的结果,把整个软件系统划分为大大小小的多个模块,设计出每一个模块的具体结构。如系统框架设计,数据库设计等。软件设计一般分为总体设计和详细设计。
4):程序编码: 此阶段是将软件设计的结果转换成计算机可运行的程序代码。在程序编码中必须要制定统一,符合标准的编写规范。以保证程序的可读性,易维护性,提高程序的运行效率。
5):软件测试: 在软件设计完成后要经过严密的测试,以发现软件在整个设计过程中存在的问题并加以纠正。整个测试过程分单元测试(白盒)、集成测试(黑盒,功能测试、强度性能测试)以及系统测试三个阶段进行。测试的方法主要有白盒测试和黑盒测试两种。在测试过程中需要建立详细的测试计划并严格按照测试计划进行测试,以减少测试的随意性。
6):运行维护: 安装部署软件系统,修复软件中存在的bug和升级系统。在软件开发完成并投入使后,由于多方面的原因,软件不能继续适应用户的要求。要延续软件的使用寿命,就必须对软件进行维护。软件的维护包括纠错性维护和改进性维护两个方面。
-----------------------------------------------------------------------------------------------
软件设计原则:
为了提高软件的开发效率,降低软件开发成本,一个优良的软件系统应该具有以下特点:
1,可重用性:遵循DRY原则,减少软件中的重复代码。
2,可拓展性:当软件需要升级增加新的功能,能够在现有的系统架构上方便地创建新的模块,而不需要改变软件现有的结构,也不会影响以及存在的模块。
3,可维护性:当用户需求发生变化时,只需要修改局部的模块中的少量代码即可。
如何让软件系统达到上述的特点,我们对模块的要求:
1):结构稳定性:在软件设计阶段,把一个模块划分为更小的模块时,设计合理,使得系统结构健壮,以便适应用户的需求变化。
2):可拓展性:当软件必须增加新的功能时,可在现有模块的基础上创建出新的模块,该模块继承了原有模块的一些特性,并且还具有一些新的特性,从而实现软件的可重用和可拓展性。
3):可组合性:若干模块经过组合,形成大系统,模块的可组合性提高软件的可重用和可维护性,并且能简化软件开发过程。
4):高内聚性:内聚,强调一个模块内的功能联系,每个模块只完成特定的功能,不同模块之间不会有功能的重叠,高内聚性可以提高软件的可重用性和可维护性。
5):低耦合性:耦合,强调的是多个模块之间的关系,模块之间相互独立,修改某一个模块,不会影响到其他的模块。低耦合性提高了软件的可维护性。
DAO思想:
为什么需要DAO包,出现的作用什么?
正常情况下一个用户对数据库进行访问,其实是没有必要使用DAO
不可能是一个用户对当前数据库进行访问
例子:
客户端存了200行操作数据库的代码
客户端存了200行操作数据库的代码
客户端存了200行操作数据库的代码
客户端存了200行操作数据库的代码
需要访问数据库 这200行代码的操作其实都是相同,出现大量相同重复性代码,破坏一个原则DRY原则
通过一种方式将这些相同代码进行一个封装,对外提供统一的接口,这样操作数据的接口统一命名为 DAO
数据的分离处理可以很好的体现 MVC设计模式的结构
DAO包主要的作用:
其实就是完成对数据库的增删改查(CRUD)
DAO(Data Access Object)
DAO就是和数据完成数据交互的业务逻辑 --> 对应着MCV中M层
DAO包的设计:
DAO的设计规范:
DAO包是有DAO接口和DAO实现类和描述类组成,在开发中会多件一个包测试DAO包
DAO的命名:
公司域名倒写.项目名.DAO --> 主包
例子:
com.qfedu.项目名称.domain --> 存储到是domain文件
com.qfedu.项目名称.dao --> 存储dao的接口 -->封装了处理数据库的方法
com.qfedu.项目名称.dao.impl --> 存储dao包下的实现类
com.qfedu.项目名称.test --> 存储的是测试文件 --> 项目开发完成必须删除
简单解释一下对应包存储的文件:
domain包 --> 存描述类会以英文单词描述 例如Student --> JAVABEAN规范
dao包 --> 接口接口中的名称 I+ domain下的描述类名称+DAO IStudentDAO -->IXXXDAO
dao包的实现 impl--->名称 XXXDAOImpl --> 接口的实现了 domain下的描述类名称
test包 --> 名称 XXXDAOTest --> domain下描述类的名称
ps:java项目其实是不安全,可以通过反编译jar包拿到项目原码
实际上传java项目时,会对项目中所有类,接口,变量进行加密
DAO封装
1. 创建domian包中的描述了
2. 创建当前dao包封装CRUD方法
3. 创建当前dao包的实现类来完成这些方法
ps:测试这个逻辑需要将表中的数据id重新设置成Long , 从新创建一个表
代码中的表使用t_student所有这里需要注意一下Student这个类中id
package com.qfedu.Day27_JDBC.domain; /** * Description: domain包存储的都是描述类 <br/> * Copyright (c) , 2018, JK <br/> * This program is protected by copyright laws. <br/> * Program Name:Student.java <br/> * * @author 千锋智哥 * @version : 1.0 */ //这个类的设计原则是根据表来完成的 ,表中提供哪些列,那么就需要在这个类中描述出来 public class Student { private String name; private int age; private long id; public Student() { super(); // TODO Auto-generated constructor stub } public Student(String name, int age, long id) { super(); this.name = name; this.age = age; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public long getId() { return id; } public void setId(long id) { this.id = id; } } package com.qfedu.Day27_JDBC.dao; import java.util.List; import com.qfedu.Day27_JDBC.domain.Student; /** * Description: 定义对数据库中的数据访问方法<br/> * Copyright (c) , 2018, JK <br/> * This program is protected by copyright laws. <br/> * Program Name:IStudentDAO.java <br/> * * @author 千锋智哥 * @version : 1.0 */ public interface IStudentDAO { /** * 将学生对象保存到数据库中 * @param student 需要保存的学生对象 */ void save(Student student); /** * 删除指定学生对象 * @param id 被删除学生对象在数据库中的主键 */ void delete(int id); /** * 修改指定id学生对象的信息 * @param id 学生对象在数据库中主键 * @param student 新的学生对象 */ void update(int id,Student student); /** *查询所有学生对象 *@return 获取所有学生对象信息并存储到集合中 */ List<Student> list(); /** * 通过指定id查出对应的学生 * @param id 指定id * @return 如果存在返回该id对应的学生对象,不存在就返回null */ Student get(int id); } /** * */ package com.qfedu.Day27_JDBC.dao.Impl; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import com.qfedu.Day27_JDBC.dao.IStudentDAO; import com.qfedu.Day27_JDBC.domain.Student; /** * Description: 就是对整个业务的实现逻辑CRUD<br/> * Copyright (c) , 2018, JK <br/> * This program is protected by copyright laws. <br/> * Program Name:StudentDAOImpl.java <br/> * * @author 千锋智哥 * @version : 1.0 */ public class StudentDAOImpl implements IStudentDAO{ /* * 插入 插入数据 */ @Override public void save(Student student) { // TODO Auto-generated method stub } /* * 删除 */ @Override public void delete(int id) { // TODO Auto-generated method stub } /* * 更新 */ @Override public void update(int id, Student student) { // TODO Auto-generated method stub } /* * 查询 */ @Override public List<Student> list() { // TODO Auto-generated method stub return null; } /* * 单独查询 */ @Override public Student get(int id) { String sql = "select * from t_student where id="+id; Connection conn = null; Statement st = null; ResultSet rs = null; try { //加载驱动 Class.forName("com.mysql.jdbc.Driver"); //获取连接对象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "123456"); //创建SQL语句执行对象 st = conn.createStatement(); //执行SQL rs = st.executeQuery(sql); //将结果集中的对象取出来 while(rs.next()) { Student stu = new Student(); stu.setId(rs.getInt("id")); stu.setName(rs.getString("name")); stu.setAge(rs.getInt("age")); return stu; } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { if(rs != null) { try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(st != null) { try { st.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn !=null) { try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //没有渠道值就是空对象 return null; } }