数据库设计的三大范式
1第一范式:做到每列不可拆分,(一列数据中不要出现可以拆分的数据)
2.第二范式:确保一个表只做一件事情(不要让一个表保存的数据可以做多个事情)
3.第三范式:在满足范式二时,消除表的传递依赖。(比如说,表A里的数据可以通过表A的其他数据得到。产生了多余列,应为完全可以在代码中得到)
数据库设计的反三范式
反三范式就是在以满足上述三个范式的基础上,为了满足客户的特殊需求,在满足三大范式的基础上又加了多余字段,我们称之为反三范式。
如:客户在一张表中有单价,数量,需要我们给一个总价 我们设立一行总价的列就是反三范式
分散计算思想(一般都写在service层)
如:有两张表,一张A(总金额表),一张B(单个商品总价表),当客户访问数据时,客户想要在A中看到总金额,我们这里就需要遍历表B的总价,再相加,最后赋值给表A,这样的话会造成数据加载迟缓,针对这种情况,我们可以在每次修改增加删除表B的数据时,只要操作一次就把总价格传给表A 进行加减,实时维护数据,这样客户再查看总金额是就增强了加载速度,。而这种过程就是分散计算思想。
案例:保存 修改 新增数据时 既要修改自己的总金额,还要修改最大的表的总金额
public void saveOrUpdate(ContractProduct entity) {
//1.先判断是新增,还是修改,等于id=null为新增,
if(UtilFuns.isEmpty(entity.getId())){//新增
double amount=0.0;//2.先把货物表的总金额设为0.
if(UtilFuns.isNotEmpty(entity.getPrice())&&UtilFuns.isNotEmpty(entity.getCnumber())){ //3.再在其单价和数量都是新增的情况下,,,,让其相乘,得到货物的总价
amount=entity.getPrice()*entity.getCnumber();
}
//4.将获得的总价赋值给货物总价,
entity.setAmount(amount);
//5.通过销售合同的ID 查到销售合同的数据
Contract contract = contractDaoimpl.findOne(entity.getContract().getId());
//6.通过数据给总金额赋值 总金额+新的货物总价
contract.setTotalAmount(amount+contract.getTotalAmount());
//7.保存修改销售合同的总金额后的数据
contractDaoimpl.save(contract);
}else{ //修改
//1.获取当前货物的总价
Double amount = entity.getAmount();
//2.把修改后的货物总价设为0
Double amount1=0.0;
if(UtilFuns.isNotEmpty(entity.getPrice())&&UtilFuns.isNotEmpty(entity.getCnumber())){ //3.再在其单价和数量都是新增的情况下,,,,让其相乘,得到货物的总价
amount1=entity.getPrice()*entity.getCnumber();
}
//4.判断修改后的货物总价与原先是否相等,是就不修改了,不是则继续修改
if(amount1!=amount){
//5.用计算出的新的货物总价 为货物总价赋值
entity.setAmount(amount1);
//5.通过销售合同的ID 查到销售合同的数据
Contract contract = contractDaoimpl.findOne(entity.getContract().getId());
//6.通过数据给总金额赋值 总金额+新的货物总价-原来的货物总价
contract.setTotalAmount(contract.getTotalAmount()+amount1-amount);
//7.保存修改销售合同的总金额后的数据
contractDaoimpl.save(contract);
}
}
//保存货物数据
ContractProductdao.save(entity);
}
打断设计思想:
定义:在一方的表中加入冗余字段,用于保存多方的主键,并用指定的字符进行分隔。
应用场景:一般在一对一,一对多是使用,多对多不推荐使用
好处:当关联层级大于4级时,最好考虑打断设计,能够优化查询速度
案列:有两张表使用的打断设计 entity :运单表(一) ,contract :合同表(多), ContractIds :他们之间的打断设计的字段 ,当保存一张表时,需要把打断
public void saveOrUpdate(Export entity) {
//UtilFuns.isEmpty(entity.getId())判断是否为null null 为新增数据
if(UtilFuns.isEmpty(entity.getId())){//先判断是不是新增的,
//更具运单表获取中间表ContractIds,由于是用字符拼接的这里我们需要使用split切割下
String[] ContractIds = entity.getContractIds().split(", ");
//new StringBuffer 以便存放数据
StringBuffer ab = new StringBuffer();
for (String con : ContractIds) {
//更具ID查询合同表的数据
Contract contract = contractDaoimpl.getOne(con);
//用append 存放数据,并使用空格进行分隔
ab.append(contract.getContractNo()).append(" ");
}
exportdao.save(entity);//调用保存方法
}
设计的冗余字段进行更新