掘金 后端 ( ) • 2024-04-07 16:46

theme: Chinese-red

请描述转发和重定向的区别?

1.请求次数:转发一次,重定向两次 2.浏览器地址:转变不变,重定向改变 3.使用request域共享数据:转发是一次请求可以共享数据,重定向浏览器发起两次请求,不能共享数据 4.相对路径:转发地址不变会造成转发后的页面的相对路径发生改变引起相对路径失效,重定向不会 5.效率:转发浏览器一次请求效率高,重定向效率低 5.WEB-INF下资源:转发可以访问,重定向不可以

Http 常见的状态码有哪些?

  • 200 OK  //客户端请求成功

  • 301  Moved Permanently(永久移除),请求的 URL 已移走。Response 中应该包含一个 Location URL, 说明资源现在所处的位置

  • 302  found 重定向

  • 400  Bad Request //客户端请求有语法错误,不能被服务器所理解

  • 401  Unauthorized //请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用

  • 403  Forbidden //服务器收到请求,但是拒绝提供服务

  • 404  Not Found //请求资源不存在,eg:输入了错误的 URL

  • 500  Internal Server Error //服务器发生不可预期的错误

  • 503  Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

Servlet生命周期

Servlet 加载—>实例化—>服务—>销毁。

生命周期详解:

init():

在Servlet的生命周期中,仅执行一次init()方法。它是在服务器装入Servlet时执行的,负责初始化Servlet对象。可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init()。

service(): 它是Servlet的核心,负责响应客户的请求。每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能。

destroy():

仅执行一次,在服务器端停止且卸载Servlet时执行该方法。当Servlet对象退出生命周期时,负责释放占用的资源。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成。

如何与Tomcat 结合工作步骤

(1)Web Client 向Servlet容器(Tomcat)发出Http请求

(2)Servlet容器接收Web Client的请求

(3)Servlet容器创建一个HttpRequest对象,将Web Client请求的信息封装到这个对象中。

(4)Servlet容器创建一个HttpResponse对象

(5)Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象作为参数传给HttpServlet 对象。

(6)HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息。

(7)HttpServlet调用HttpResponse对象的有关方法,生成响应数据。

Servlet是单实例的吗?

servlet是单实例的[单例多线程]

service是多线程方法

Servlet是线程安全的吗?为什么?

Servlet对象并不是一个线程安全的对象。

Servlet第一次被调用的时候,init()方法会被调用,然后调用service() 方法,从第二次被请求开始,就直接调用service()方法。

因为servlet是单实例的,所以后面再次请求同一个Servlet的时候都不会创建Servlet实例,

而且web容器会针对每个请求创建一个独立的线程,这样多个并发请求会导致多个线程同时调用 service() 方法,这样就会存在线程不安全的问题。

如何解决Servlet线程不安全的问题?

(1)不要在servlet中使用成员变量。

(2)可以给servlet中的方法添加同步锁,Synchronized,但是不提倡,数据并发访问会造成阻塞等待。

(3)可以实现 SingleThreadModel 接口,如下。这样可以避免使用成员变量的问题,但是也不提倡,原因同上。

Public class Servlet1 extends HttpServlet implements SingleThreadModel{ ……

}

谈谈过滤器的作用?

过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,

然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,

如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符

Request对象的主要方法有哪些?

Request对象的主要方法:

setAttribute(String name,Object):设置名字为name的request 的参数值

getAttribute(String name):返回由name指定的属性值

getAttributeNames():返回request 对象所有属性的名字集合,结果是一个枚举的实例

getCookies():返回客户端的所有 Cookie 对象,结果是一个Cookie 数组

getCharacterEncoding() :返回请求中的字符编码方式

getContentLength() :返回请求的 Body的长度

getHeader(String name) :获得HTTP协议定义的文件头信息

getHeaders(String name) :返回指定名字的request Header 的所有值,结果是一个枚举的实例

getHeaderNames() :返回所以request Header 的名字,结果是一个枚举的实例

getInputStream() :返回请求的输入流,用于获得请求中的数据

getMethod() :获得客户端向服务器端传送数据的方法

getParameter(String name) :获得客户端传送给服务器端的有 name指定的参数值

getParameterNames() :获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实

request.getAttribute()和 request.getParameter()有何区别?

getParameter 得到的都是 String 类型的。或者是 http://a.jsp?id=123 中的 123,或者是某个表单提交过去的数据。

getAttribute 则可以是对象。

getParameter()是获取 POST/GET 传递的参数值;

getAttribute()是获取对象容器中的数据值;

getParameter:用于客户端重定向时,即点击了链接或提交按扭时传值用,即用于在用表单或 url 重定向传值时接收数据用。

getAttribute:用于服务器端重定向时,即在 sevlet 中使用了 forward 函数,或 struts 中使用了 mapping.findForward。 getAttribute 只能收到程序用 setAttribute 传过来的值。

getParameter()是获取 POST/GET 传递的参数值;

getAttribute()是获取 SESSION 的值;

另外,可以用 setAttribute,getAttribute 发送接收对象.而 getParameter 显然只能传字符串。

setAttribute 是应用服务器把这个对象放在该页面所对应的一块内存中去,当你的页面服务器

重定向到另一个页面时,应用服务器会把这块内存拷贝另一个页面所对应的内存中。这样

getAttribute 就能取得你所设下的值,当然这种方法可以传对象。 session 也一样,只是对象在内存中的生命周期不一样而已。 getParameter 只是应用服务器在分析你送上来的 request页面的文本时,取得你设在表单或 url 重定向时的值。

getParameter 返回的是 String, 用于读取提交的表单中的值;

getAttribute 返回的是 Object,需进行转换,可用 setAttribute 设置成任意对象,使用很灵活,可随时用;

什么是Tomcat?

Tomcat简单的说就是一个运行JAVA的网络服务器,底层是Socket的一个程序,它也是JSP和Serlvet的一个容器。

详细描述MVC!

基于java的web应用系统采用MVC设计模型,即用Model(模型)、View(视图)和Controller(控制)分离设计,这是目前web应用服务系统的主流设置方向。

Model:处理业务逻辑的模块。

View:负责页面显示,显示Model的处理结果给用户,主要实现数据到页面的转换过程。

Controller:负责每个请求的分发,把Form数据传递给Model进行处理,处理完成后,把处理结果返回给相应的View显示给用户。

Http请求由哪三部分组成?

http协议报文

1.请求报文(请求行/请求头/请求数据/空行)

请求行

求方法字段、URL字段和HTTP协议版本

例如:GET /index.html HTTP/1.1

get方法将数据拼接在url后面,传递参数受限

请求方法:

GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT

请求头(key value形式)

User-Agent:产生请求的浏览器类型。 Accept:客户端可识别的内容类型列表。

Host:主机地址

请求数据

post方法中,会把数据以key value形式发送请求

空行

发送回车符和换行符,通知服务器以下不再有请求头

2.响应报文(状态行、消息报头、响应正文)

状态行

消息报头

响应正文

请说下在后台Servlet代码中如何获取前端form表单提交的属性?

可以使用request.getParameter();

也可以使用request.getParameterMap(),在使用beanutils.populate()方法

说说Promise有什么特别?

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。

npm常用命令?

1.项目初始化  npm init

2.安装依赖  npm install 包名 或者 npm install 包名@版本号/npm install -g 包名/npm install

3.升级依赖  npm update 包名

4.卸载依赖  npm uninstall 包名

5.查看依赖  npm ls查看项目依赖   npm list -g查看全局依赖

ES6模块化有几种暴露方式,分别作出解释?

1.分别暴露  // 模块想对外导出,添加export关键字即可!

2.统一暴露   // 模块想对外导出,export统一暴露想暴露的内容!

3.默认暴露   // 默认暴露语法  export default sum默认暴露相当于是在暴露的对象中增加了一个名字为default的属性

请描述get请求 和 post请求的区别?

① 浏览器和表单的默认提交方式是get,get请求效率比post高

② get请求参数在url地址后拼接,所以有以下特点:

请求报文没有请求体

少了和请求体相关的请求头参数

参数在url地址中拼接,上传参数大小有限制,不能用来上传文件,相对post请求不安全

③ post请求参数在请求报文的请求体中携带,有以下特点:

请求报文有请求体,相对安全

请求头多了和请求体相关的参数

请求体数据没有大小限制可以用来上传文件**

async await的基本使用

async 表示这是一个async函数, await只能用在async函数里面,不能单独使用

async 返回的是一个Promise对象,await就是等待这个promise的返回结果后,再继续执行

await 如果右边的是一个Promise对象,后面必须跟一个Promise对象,但是不必写then(),直接就可以得到返回值,如果await右边是一个普通数据  返回的就是普通数据

await必须在async函数中使用

session 和 cookie 有什么区别?

Cookie:主要用在保存客户端,其值在客户端与服务端之间传送,不安全,存储的数据量有限。

Session:保存在服务端,每一个session在服务端有一个sessionID作一个标识。存储的数据量大,安全性高。占用服务端的内存资源

cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,相当重要的数据,应该使用session保存到服务端。

session会在一定时间内保持在服务器上,但是会占用内存资源,当访问的用户过多,会加重服务器的负载,考虑到减轻服务器的压力,可以将不重要的数据放在cookie中持久的保存。

单个cookie保存的数据不能超过4k,很多浏览器都限制站点最多保存20个cookie。

由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。

这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。

集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。

这个时候Cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。

简述响应式数据和非响应式数据?

响应式

1. 当Vue组件的实例初始化的时候已有的数据就是响应式数据

2. 响应式属性的值发生改变会触发视图更新

非响应式:

1. 当Vue组件的实例初始化的时候没有,后期添加的属性

2. 非响应式属性的值发生改变不会触发视图更新

请说下Vue 有哪些指令,并简述其作用(5个以上)?

v-html:用于渲染HTML标签

v-show:用于类似双大括号语法渲染数据

v-if:渲染数据的时候,也可以用于条件判断

v-for:遍历集合或者数组,用于页面渲染数据

v-bind:绑定属性,注意冒号后面跟标签的属性,属性后面的等号指向数据,它可以简写为 :class, :href。

V-model:数据双向绑定

简述JS中var let const声明变量的区别?

Let 和 var的区别

1、let 不能重复声明

2、let有块级作用域,非函数的花括号遇见let会有块级作用域,也就是只能在花括号里面访问。

3、let不会预解析进行变量提升

4、let 定义的全局变量不会作为window的属性

const和var的差异

1、新增const和let类似,只是const定义的变量不能修改

2、并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

Maven项目依赖中作用范围scope?

当一个Maven工程添加了对某个jar包的依赖后,这个被依赖的jar包可以对应下面几个可选的范围,默认是compile。

图片1.png

Maven项目之间的三种关系及其特征?

  • 依赖关系(兄弟关系、朋友关系):

- 项目A依赖项目B,项目A可以访问项目B中某些依赖,避免重复提供

- 缺点:但是只有范围为compile时可以访问

  • 继承关系(父子关系,并列关系):

- 使用继承时,需要定义父项目和子项目

- 继承关系是单向关系:子项目指定父项目,父项目不用指定子项目

- 父项目的所有的依赖(compile、test、provided等)子项目都可以自动使用

- 父项目中可以通过dependencyManagement来管理依赖,子项目如果需要必须手动声明

- 缺点:彼此间是并列关系,父项目、子项目需要分别逐个手动进行clean、compile操作

  • 聚合关系(父子关系,包含关系):

- 首先是继承关系,并且比继承关系更进一步

- 在聚合关系中, 子项目明确父项目, 但是父项目明确子项目,是双向关系

- 其实是一个大项目包含多个子项目,对父项目进行clear、compile等命令,

是对所有子项目进行clear、compile命令。但是如果对一个子项目进行maven操作,不影响其他子项目

Maven中A依赖B,B依赖C,那么A可以使用C中的类吗?

此时要看B依赖C时的范围,如果是compile范围则A可以使用C,如果是test或provided范围则A不能使用C。

通过Maven下载jar包,下载失败了怎么办?(提示:分*.lastUpdated和内部损坏两种情况说明)

lastUpdated情况:将lastUpdated文件删除,重新下载。如果*.lastUpdated这样的文件很多,则使用专门的批处理脚本统一清理。

内部损坏情况:删除损坏的jar包重新下载。

面依赖信息对应的jar包在Maven仓库根目录下的路径是什么?

<dependency>

<groupId>org.apache.commons</groupId>

<artifactId>commons-lang3</artifactId>

<version>3.1</version>

</dependency>

答案:Maven本地库根目录/org/apache/commons/commons-lang3/3.1/commons-lang3-3.1.jar

Maven仓库之间的关系以及优先级?(须简单介绍三个仓库)

Maven仓库是用来存储和管理Maven项目所需依赖和插件的地方。通常情况下,Maven仓库可以分为三个层次:本地仓库、中央仓库和远程仓库。

本地仓库:是位于本地计算机上的一个目录,用于存储Maven项目构建所需的依赖和插件。当第一次构建项目时,Maven会自动从中央仓库下载所需的依赖到本地仓库。本地仓库具有最高的优先级,即当构建项目时,Maven会首先在本地仓库中查找依赖,如果找到则直接使用,否则才会去远程仓库或中央仓库下载。

远程仓库:是自定义的仓库,用于存放特定的依赖和插件。远程仓库可以是私有的,也可以是公共的。当本地仓库没有找到所需的依赖时,Maven会去远程仓库下载。

中央仓库:是Maven官方维护的仓库,包含了大量的开源Java项目依赖和插件。当Maven构建项目时,如果本地仓库和远程仓库都没有找到所需的依赖,就会去中央仓库下载。

仓库的优先级顺序为:本地仓库>远程仓库> 中央仓库。也就是说,如果本地仓库中已经存在所需依赖项,Mavern 将直接使用本地仓库中的该依赖项,而不会再去远程仓库或中央仓库下载。

总之,Maven 的仓库机制提供了依赖项和插件管理的核心支持,使得项目的构建和部署更加便捷和高效,理解和掌握 Maven 的仓库机制对于 Maven 的使用和开发至关重要

图片2.png

如何理解框架framework?

  • 生活案例:不需要自己盖房,直接购买毛坯房即可,自己来装修,质量户型有保证,还节省了建房的时间。

在开发过程中使用的框架就好比毛坯房。

  • 框架= jar(大量最佳实践基础上的对特定问题的固定解决方案进行封装并提供相应的API)

+ 配置文件(个性化定制,配置变化的内容,比如数据库连接参数、端口号、接口的具体实现类等)

  • 作用1:可以保证减少开发时间、降低开发难度,并且还保证设计质量。好比和世界上最优秀的软件工程师是

一个项目的,并且他们完成的还是基础、全局的工作。想想是不是很嗨的一件事情。

  • 作用2:框架还有一个作用是约束,统一了代码流程和风格。同样的技术解决同样的问题会产生不同流程和

风格的解决方案,而采用一种框架其实就是限制用户必须使用其规定的方案来实现,可降低程序员

之间沟通以及日后维护的成本。

  • 常用的基于JavaEE的三大开源框架,已经从SSH、SSH2过渡到了SSM:SpringMVC、Spring、MyBatis。

  • 总之,框架是一个半成品,已经对基础的代码进行了封装并提供相应的API,开发者在使用框架是直接调用

封装好的API可以省去很多代码编写,从而提高工作效率和开发速度,并统一了风格(这一点不要忽略掉)。

如何理解ORM

  • JDBC的缺点:需要手动的完成面向对象的Java语言、面向关系的数据库之间数据的转换,代码繁琐无技术含量,

影响了开发效率(查询时需要手动的将结果集ResultSet的列数据转换为Java对象的属性;

而添加操作时需要手动将Java对象的属性转换为数据库表的列字段)。

  • 关于面向对象的Java语言、面向关系的数据库之间数据的转换必须要做,问题在于这个转换是否可以不由开

发者来做。可以的。ORM框架就是专门来做这个问题的,相当于在面向对象语言和关系数据库之间搭建一个桥梁。

  • ORM,Object-Relationl Mapping,对象关系映射,它的作用是在关系型数据库和对象之间作一个映射, 这样我们在具体的操作数据库的时候,只要像平时操作对象一样操作它就可以了,

ORM框架会根据映射完成对数据库的操作,就不需要再去和复杂的SQL语句打交道了。

Hibernate是一个全自动的ORM框架。因为Hibernate创建了Java对象和数据库表之间的完整映射,

可以完全以面向对象的思想来操作数据库,程序员不需要手写SQL语句。MyBatis中还需要手写SQL语句,

所以是半自动化的。但是最终MyBatis却战胜了Hibernate,主要还是因为MyBatis可以更加精确的定义SQL,

更加灵活,也便于优化性能。

Mybatis 结果集的映射方式有几种,并分别解释每种映射方式如何使用?

自动映射 ,通过resultType来指定要映射的类型即可。

自定义映射 通过resultMap来完成具体的映射规则,指定将结果集中的哪个列映射到对象的哪个属性。

ybatis中#{}和${}的区别是什么?

#{}是预编译处理,${}是字符串替换。

Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;

Mybatis在处理${}时,就是把${}替换成变量的值。

使用#{}可以有效的防止SQL注入,提高系统安全性。

Mybatis中当实体类中的属性名和表中的字段名不一样 ,怎么办 ?

第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。

<select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”>

        select order_id id, order_no orderno ,order_price price form orders where order_id=#{id};

</select>

第2种: 通过<resultMap>来映射字段名和实体类属性名的一一对应的关系

<select id="getOrder" parameterType="int" resultMap="orderresultmap">

         select * from orders where order_id=#{id}

</select>

<resultMap type=”me.gacl.domain.order” id=”orderresultmap”>

        <!–用id属性来映射主键字段–>

       <id property=”id” column=”order_id”>

       <!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–>

       <result property = “orderno” column =”order_no”/>

       <result property=”price” column=”order_price” />

</reslutMap>

MyBatis如何获取自动生成的(主)键值?如何完成MySQL的批量操作

在标签中使用 useGeneratedKeys   和  keyProperty 两个属性来获取自动生成的主键值。

例如:

<insert id="insertname"  usegeneratedkeys="true" keyproperty="id">  
    insert into names (name) values (#{name})  
</insert>

MyBatis完成MySQL的批量操作主要是通过标签来拼装相应的SQL语句。

例如:

    <insert id="insertBatch" >  
    insert into tbl_employee(last_name,email,gender,d_id) values  
    <foreach collection="emps" item="curr_emp" separator=",">  
        (#{curr_emp.lastName},#{curr_emp.email},#{curr_emp.gender},#{curr_emp.dept.id})  
    </foreach>  
</insert>

简述MyBatis的单个参数、多个参数如何传递及如何取值

1、MyBatis传递单个参数,如果是普通类型(String+8个基本)的,取值时在#{}中可以任意指定,如果是对象类型的,则在#{}中使用对象的属性名来取值

2、MyBatis传递多个参数,默认情况下,MyBatis会对多个参数进行封装Map. 取值时

在#{}可以使用012 .. 或者是param1 param2..

3、MyBatis传递多个参数,建议使用命名参数,在Mapper接口的方法的形参前面使用

@Param() 来指定封装Map时用的key. 取值时在#{}中使用@Param指定的key.

方法一:顺序传参

public User select(String name,int id);

<select id="select" resultMap="UserResultMap">

select * from user where name=#{0} and id=#{1}

</select>

#{}里面的数字代表你传入参数的顺序。

这种方法不建议使用,sql层表达不直观,且一旦顺序调整容易出错。

方法二:@Param注解传参

public User select(@Param("paramName") String name,@Param("paramId") int id);

<select id="select" resultMap="UserResultMap">

select * from user where name=#{paramName} and id=#{paramId}

</select>

#{}里面的名称对应的是注解 @Param括号里面修饰的名称。

这种方法在参数不多的情况还是比较直观的,推荐使用。

方法三:Map传参

Map<String,Object> map = new HashMap<String, Object>();

map.put("mapName","zhangsan");

map.put("mapId",2);

public User select(Map<String,Object> map);

<select id="select" parameterType="java.util.Map" resultMap="UserResultMap">

select * from user where name=#{mapName} and id=#{mapId}

</select>

#{}里面的名称对应的是 Map里面的key名称。

这种方法适合传递多个参数,且参数易变能灵活传递的情况。

讲述下MyBatis多表映射中association与collection区别

在MyBatis多表映射中,association和collection是两种不同的映射类型,用于处理关联关系和一对多的关系。

association: association用于描述两个表之间的一对一关系。它表示一个复杂类型(Java对象)在另一个表中的外键关联。在映射文件中,我们可以使用association来定义关联关系,指定外键列和关联的结果映射。

例如,假设我们有两个表:Order(订单)和User(用户),一个订单只对应一个用户。我们可以在Order的映射文件中使用association来描述订单和用户之间的关联关系:

<resultMap id="OrderResultMap" type="Order">

    <id property="orderId" column="order_id" />

    <result property="orderName" column="order_name" />

    <association property="user" javaType="User">

        <id property="userId" column="user_id" />

        <result property="username" column="username" />

        <result property="email" column="email" />

    </association>

</resultMap>

这里,association指定了外键列order_id以及关联的结果映射User。

collection: collection用于处理一对多的关系,表示一个表中的一条记录关联多个另一个表的记录。在映射文件中,我们可以使用collection来定义一对多的映射关系。

例如,假设我们有两个表:Department(部门)和Employee(员工),一个部门拥有多个员工。我们可以在Department的映射文件中使用collection来描述部门和员工之间的关系

<resultMap id="DepartmentResultMap" type="Department">

    <id property="deptId" column="dept_id" />

    <result property="deptName" column="dept_name" />

    <collection property="employees" ofType="Employee">

        <id property="empId" column="emp_id" />

        <result property="empName" column="emp_name" />

        <result property="empEmail" column="emp_email" />

    </collection>

</resultMap>

这里,collection指定了关联的结果集类型(Employee)以及关联的结果映射。

区别:

association用于一对一的关系,而collection用于一对多的关系。

association关联的结果类型是复杂类型(Java对象),而collection关联的结果类型是集合类型(List、Set等)。

在association中,外键列必须在当前表中存在;而在collection中,外键列可以在当前表或关联表中存在。

association使用的是resultMap,而collection使用的是collection标签。

请写出Mybatis中常用的动态标签,并简单介绍其作用?

if 标签

if 标签通常用于 WHERE 语句、UPDATE 语句、INSERT 语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。

foreach 标签

foreach 标签主要用于构建 in 条件,可在 sql 中对集合进行迭代。也常用到批量删除、添加等操作中。

choose 标签

有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis 提供了 choose 元素,按顺序判断 when 中的条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when的条件都不满则时,则执行 otherwise 中的 sql。类似于 Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。

where 标签

当 if 标签较多时,如果标签返回的内容是以 AND 或 OR 开头的,则它会剔除掉.

set 标签

使用 set 标签可以将动态的配置 set关键字,和剔除追加到条件末尾的任何不相关的逗号。

trim 标签

格式化输出,也可以通过 trim 标签设定或忽略前后缀来实现

** 配置关联关系**

collection 标签    配置一对多

association 标签    配置一对一

sql 标签

当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。为求 结构清晰也可将 sql 语句分解。