java的框架中各层级的初步理解

层级关系图

在这里插入图片描述**dao层:**用于定义操作数据库的接口方法,需要怎么调数据库就定义什么方法在这
**mapper层:**用于直接对数据库进行操作,sql语句就写这
**service层:**用于定义业务实现的接口方法,需要实现什么业务就定义什么方法在这
**serviceImpl层:**用于实现业务接口,可以操作管理dao层获取想要的数据
**其他几个层:**如controller,view,model,entity就简单过一过,分别负责数据的处理,展示,存储和封装。就不详细说了,我新学的主要是上面四个。
根据上图我们知道,其实对于实现一个功能来说,只需要model,view,controller层就行了,那为啥还要在model到controller之间插入dao层和service层呢? 让我们带着这个问题,去看一下使用ssm框架实现一个view渲染的现实路径映射吧。
在这里插入图片描述
可以看到啊,view层和controller层,controller层和service层,serivce层和dao层,都是多对多的关系。而service层和serviceImpl层,dao层和mapper层,mapper层和model层则是一对一的关系。
问题就出在这对应关系上!
为啥还要在model到controller之间插入dao层和service层? 目的就是为了解耦,提高代码的开发效率。这也就是刚才我们提到的多对多关系的由来。
实际上,如果我们把service层与dao层合起来,在面对一些小型业务量的场景时,是完全没有问题的。起初我也搞不懂,为啥要用service的接口方法调用另外一个接口的方法去实现。可当业务量上去后,才发现这是一个多么明智的选择。
我认为建立service层和dao层最直接的好处就是单一职责化,这也是SOLID原则中的单一职责原则(Single Responsiblity Principle),非常经典的体现,service只用考虑业务如何实现,不考虑数据如何获取。dao层和mapper只用考虑数据如何获取,不用考虑数据要被拿去干什么。在多人协作开发与业务高复杂度场景中这种思想十分好用。

另一种解释

在这里插入图片描述
为什么要有Service层,是为了减少DAO层的压力,DAO层只负责从数据库获取数据和存储数据即可,从数据库获取数据的处理交给Service层即可。所谓的业务逻辑,就是对数据库获取数据的处理,比如从数据库获取score=99,逻辑操作是+1,那么这个+1操作就交给Service层来完成。
一 Controller层
控制器,controller层负责接收前端传过来的数据和请求并调用service层中定义的方法进行业务操作。
二 Model实体层(或者叫Entity层,或者Bean层)
用于各个层(DAO、Mapper、Service、Controller)之间对象数据的封装和传递
三 Dao层
数据访问层,和数据库的一张表相对应
四 Mapper层
直接对数据库进行操作,写入的是sql语句。
mapper层=dao层
五 Service层
对DAO层或者Controller这样的上层获取的数据进行处理,再传递给Controller这样的上层或者DAO层。
服务层,对一个或多个DAO层进行封装,使用一个方法对外表现为实现一个功能。
service层=service接口+servicelmpl实现类
当项目的业务逻辑简单时,可选择service层=service类;
当项目的业务复杂时,可选择service层=service接口+serviceImpl实现类;

entity,model,domain区别

(1)、entity(实体)

entity的意思就是实体的意思,所以也是最常用到的,entity包中的类是必须和数据库相对应的,比如说:数据库有个user表,字段有long类型的id,string类型的姓名,那么entity中的user类也必须是含有这两个字段的,且类型必须一致。不能数据库存的是long类型,user类里的属性是string类型。这样做的好处是保持实体类和数据库保持一致,另外,当用到hibernate或是mybatie框架来操作数据库的时候,操作这个实体类就行,写sql文之前不需要再做数据格式处理。

(2)、model(模型)

model大家不陌生,都知道是模型的意思,当用model当包名的时候,一般里面存的是实体类的模型,一般是用来给前端用的。比如:前端页面需要显示一个user信息,user包含姓名,性别,居住地,这些信息存在数据库的时候,姓名直接存姓名,但是性别和居住地一般会用数据字典的编号存到数据库,比如:111代表男,222代表女,数据库存的就是111或222,如果用entity的话,把111、222前端都不知道是什么玩意,就算前端知道111代表男,222代表女,写了一个js判断数据处理。后来数据库变动了,111代表女,222代表男,前端的js又需要重新写,很显然这样不利于维护。所以就需要model来解决,后台从数据库取了数据转化为前端需要的数据直接传给前端,前端就不需要对数据来处理,直接显示就行了。还有一种情况,数据库里面的user表字段有十个,包含姓名,qq,生辰八字乱七八糟的等,但是前台页面只需要显示姓名,如果把entity全部传给前台,无疑传了很多没用的数据。这时候model就很好的解决了这个问题,前台需要什么数据,model就包含什么数据就行了

(3)、domain(域)

domain这个包国外很多项目经常用到,字面意思是域的意思。范围有点广了,比如一个商城的项目,商城主要的模块就是用户,订单,商品三大模块,那么这三块数据就可以叫做三个域,domain包里就是存的就是这些数据,表面上这个包和entity和model包里存的数据没什么区别,其实差别还是挺大的,特别是一些大型的项目。比如一个招聘网站的项目,最重要的对象就是简历了,那么简历是怎么存到数据库的呢,不可能用一张表就能存的,因为简历包含基本信息和工作经验,项目经验,学习经验等。基本信息可以存在简历表,但是涉及到多条的就不行,因为没人知道有多少条工作经验,项目经验,所以必须要单独建工作经验表和项目经验表关联到简历基本信息表。但是前台页面是不关心这些的,前台需要的数据就是一个简历所有信息,这时就可以用到domain来处理,domain里面的类就是一个简历对象,包含了简历基本信息以及list的工作经验,项目经验等。这样前端只需要获取一个对象就行了,不需要同时即要获取基本信息,还要从基本信息里面获取工作经验关联的简历编号,然后再去获取对应的工作经验了。
当然,如果用model的话也是可以达到domain的效果的。这个完全是看个人喜好和项目的整体架构,因为创建不同的package的作用本来也就是想把项目分成不同的层,便于管理和维护。如果你乐意,你可以创建entity包,然后在里面存图片,创建images文件夹,里面存js。你已经看懂就行,前提是如果是团队开发的话能保证别人不打你。这个和语言一个道理,你在200面前和英国人说:private void set(int age),人家说:滚犊子;现在你这样说,人家就知道是java语言了。能被人们通用的才叫语言,你说的别人听不懂那只能算是鸟语。所以开发的时候,建类建包的命名规则规范性还是很重要的。
那么三句话总结下entity、model、domain的不同:
1.entity字段必须和数据库字段一样
2.model前端需要什么我们就给什么
3.domain很少用,代表一个对象模块

在Entity实体中添加临时字段

当我们使用spring data jpa开发的时候,会将实体类中的成员变量与表中的字段一一对应,当我们在实体类中加上一个不与数据库表一一对应的成员变量的时候,此时我们只要在这个成员变量上加上注解@Transient

@Transient表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.
如果一个属性并非数据库表的字段映射,务必将其标示为@Transient,否则,ORM框架默认其注解为@Basic
比如现在有实体类Message,但是我想在使用它时想要多用一个字段来接收未读消息的数量 unReadCount,此时只要在字段前加上@Transient注解就可以了。记住要引入 import javax.persistence.Transient;
数据库表字段与result不一致时用@Column注解

package com.ms.base.domain;
 
import lombok.Data;
 
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.Date;
import java.util.List;
 
@Table(name = "department")
@Data
public class Department {
    @Id
    private Long id;
 
    @Column(name = "created_time")
    private Date createdTime;
 
    @Column(name = "updated_time")
    private Date updatedTime;
 
    /**
     * 部门名称
     */
    private String name;
 
    /**
     * 企业id
     */
    @Column(name = "enterprise_id")
    private Long enterpriseId;
 
    /**
     * 上级部门id
     */
    @Column(name = "parent_id")
    private Long parentId;
 
 
    //企业部门下 用户列表
    private List<User> userList;
 
    //部门人数
    @Transient
    private Integer personNum;
 
}

【1】https://blog.csdn.net/qq_43920456/article/details/127321090
【2】https://blog.csdn.net/qq_41375318/article/details/120677629
【3】https://www.cnblogs.com/yadongliang/p/13043254.html

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值