数据库
数据库设计
六个阶段
数据库设计通常分为6个阶段: 主要在软件开发的概要设计阶段完成
1、需求分析:分析用户的需求,包括数据、功能和性能需求;依据是软件开发中的需求分析阶段的里程碑—需求说明书
2、概念结构设计:主要采用E-R模型进行设计,包括画E-R图;
在需求中查找名词,并且进行分类----定义模式
学生(姓名、年龄、班级、家庭关系、…)
课程(课程编号、名称、…)
学生可以进行选课
使用软件绘制对应的ER图,用于说明结构设计----用于沟通
Sybase公司的PowerDesigner:绘制ER图(不是标准ER图)、可以根据ER图生成对应的建表语句、可以自动生成对应的测试数据、同时支持反向工程
定义实体
注意:在ER图的绘制过程中,没有PK和FK
3、逻辑结构设计:通过将E-R图转换成表,实现从E-R模型到关系模型的转换;
数据库选型: MySQL Oracle db2 SQLServer
数据库选型:
注意:物理数据模型中则会出现主外键
4、数据库物理设计:主要是为所设计的数据库选择合适的存储结构和存取路径;
针对开发人员而言,具体的数据存放是透明的。但是作为运维管理人员则需要针对物理存放进行规划
5、数据库的实施:包括编程、测试和试运行;
/*==============================================================*/
/* DBMS name: MySQL 5.0 */
/* Created on: 2021/3/18 星期四 上午 10:23:20 */
/*==============================================================*/
drop table if exists Entity_1;
drop table if exists Entity_2;
/*===========================================================*/
/* Table: Entity_1 */
/*==========================================================*/
create table Entity_1
(
Attribute_1 char(10) not null,
Attribute_2 char(10),
primary key (Attribute_1)
);
/*===========================================================*/
/* Table: Entity_2 */
/*===========================================================*/
create table Entity_2
(
Attribute_3 char(10) not null,
Attribute_1 char(10),
Attribute_4 char(10),
primary key (Attribute_3)
);
alter table Entity_2 add constraint FK_Relationship_1 foreign key (Attribute_1)
references Entity_1 (Attribute_1) on delete restrict on update restrict;
生成测试数据对应的sql文件
6、数据库运行与维护:系统的运行与数据库的日常维护。
数据库设计的方法:
试凑法:完全依赖于DBA的工作经验
规范化法: 范式和反范式
CAD法
规范化法:
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。一般数据库设计中最多采用的是3NF。如果不满足某个范式则采用分表的方式解决。
1NF: 列不可分原则
2NF:不允许部分依赖
3NF:不允许传递依赖
具体开发设计中可能处于查询效率的考虑降低对范式的要求,以数据冗余为代价减少表的数量,提高查询效率
如何定义标识属性【主键】
使用所有属性构成第一个候选键可以充当主键【聚簇索引】,减少其中某个属性再检查是否具备唯一标识的特性,如果可以则候选,如果不行继续查找减少其他属性。不断减少属性个数找到的最小的属性集合候选键就是主键
连接池
使用连接池的目的在于:以浪费内存为代价,以重用为手段,减少连接的创建和销毁次数,达到减少使用连接的平均成本的目标
真正开发中一般会选择使用成品连接池,例如ali的druid或者号称世界上性能最好的连接池HikariCP,另外还有Apache的DBCP等
设计模式:模板模式
意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
JDBC操作
IBaseDao接口的具体实现类,实际上就是模板模式中的父类,固化了分页查询中不可变的部分,通过定义抽象方法要求某些方法子类必须提供实现
针对auto_increment列要求插入数据后返回对应生成的id值
不合适的方法:
insert数据,然后遍历表获取max(id)
应该使用的方法:
JDBC中实际上还提供了可滚动结果集的支持
分页查询可以使用硬分页和软分页,所谓的硬分页是指需要显示多少数据就获取多少数据,节约内存的使用;软分页一般指指内存分页。
JDBC中提供的结果集ResultSet可以双向滚动,可以直接定位
其中后两个参数
考虑执行效率问题,一般不允许使用敏感和可修改
@Override
public List<ClzBean> selectByDeptId(Long deptId, PageBean pages) throws Exception {
List<ClzBean> res = new ArrayList<>();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = js.getConnection();
String sql = "select c.*,d.name dname from t_clz c inner join t_dept d on c.dept_id=d.id";
//where c.dept_id=" + deptId;
// 参数2表示结果集是可滚动不敏感的,参数3表示不允许同时修改
ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
rs = ps.executeQuery();
if (pages != null && pages.getRowsPerPage() > 0) {
if (pages.getMaxPage() < 1) {
int rowsNum = 0;
// rs.last()将行指针移动到最后一行 rs.first()将行指针移动到第一行.另外还有rs.afterLast()和rs.beforeFirst();
if (rs.last())
rowsNum = rs.getRow();// 获取最后一行的行数
if (rowsNum < 1)
return res;
int maxPage = rowsNum / pages.getRowsPerPage();
if (rowsNum % pages.getRowsPerPage() != 0)
maxPage++;
pages.setMaxPage(maxPage);
pages.setRowsNum(rowsNum);
}
if (pages.getPageNum() < 1)
pages.setPageNum(1);
if (pages.getPageNum() > pages.getMaxPage())
pages.setPageNum(pages.getMaxPage());
int begin = (pages.getPageNum() - 1) * pages.getRowsPerPage();
rs.absolute(begin);// 将行指针移动到指定行
}
int count = 0;
// rs.next() 行指针后移 rs.previous()行指针前移
while (rs.next()) {
ClzBean tmp = getBean(rs);
res.add(tmp);
if (pages != null && pages.getRowsPerPage() > 0)
if (++count > pages.getRowsPerPage())
break;
}
} finally {
js.close(rs, ps, conn);
}
return res;
}