Mybatis
#{}与${}的区别
-
区别
-
{}解析为一个JDBC的预编译语句(prepared statement)的参数标记符,一个#{}被解析为一个参数占位符;而¥{}仅仅是一个纯粹的String替换,在动态Sql语句解析阶段会进行变量替换。mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
-
{}解析后会将String类型的数据自动加上引号,其他类型的数据不会;而${}解析后是什么就是什么,不会当字符串处理
-
{}很大程度上可以防止Sql注入(Sql注入是发生在编译的过程中,因为恶意注入了某些特殊字符,最后被编译成恶意的执行操作);而${}主要用于Sql拼接的时候,有很大的Sql注入隐患。
- 在某些场合下只能用{id}
,如果使用#{id},则会被解析为
ORDER BY "id"`,这显然是错误的写法
-
-
联系
它们都是在Sql中动态的传入参数
collection与association的区别
association用于一对一或者多对一的关系,collection用于一对多的关系
User.java
public class User{
private Card card_one;
private List<Card> card_many;
private Set<Kaike> kaikes= new HashSet<Kaike>();
}
Card.java
public class Card implements Serializable{
private Integer id;
private String code;
//省略set和get方法.
}
映射card_one
属性时属于一对一用 association 标签
映射card_many
属性是一个list
集合时属于一对多用 collection标签
连接池
连接池就是用于储存连接的一个容器。容器其实就是一个集合对象,该集合必须是线程安全的,不能两个线程拿到同一个连接,该集合必须实现队列的特性:先进先出
真正连接打开的时间点,只是在我们执行SQL语句时,才会进行。其实这样做我们也可以 进一步发现,数据库连接是我们最为宝贵的资源,只有在要用到的时候,才去获取并打开连接,当我们用完了就再 立即将数据库连接归还到连接池中。
POOLED和UNPOOLED
POOLED从连接池中取出一个连接使用
UNPOOLED每次创建一个新的连接
延迟加载
延时加载就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载
好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快
坏处:因为只有用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,可能造成用户等待时间变长,造成用户体验下降。
开启延迟加载:mybatis
官方文档中说明了
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
缓存
使用缓存我们可以避免频繁的与数据库进行交互,尤其是在查询多、缓存命中率高的情况下,使用缓存对性能的提高更明显。默认情况下mybatis
只开启一级缓存(一级缓存是对同一个SqlSession而言的)
-
一级缓存
- 在同一个
SqlSession
中,mybatis会把执行的方法和参数通过算法生成缓存的键值并存放在一个Map中,如果后续的键值一样,则直接从Map中获取数据; - 不同的
SqlSession
之间的缓存是相互隔离的; - 用同一个
SqlSession
,可以通过配置使得在查询前清空缓存; - 任何的
UPDATE,INSERT,DELETE
语句都会清空缓存。
- 在同一个
-
二级缓存
在mybatis中,二级缓存有总开关和分开关,总开关在
mybatis-config.xml
中配置<settings> <!--全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。 --> <setting name="cacheEnabled" value="true"/> </settings>
分开关就是在
*Mapper.xml
中开启或关闭二级缓存,默认是关闭的,需要在*Mapper.xml
中加入<cache>
标签<mapper namespace="com.itheima.dao.IUserDao"> <!-- 开启二级缓存的支持 --> <cache></cache> </mapper>
二级缓存中储存的是数据而不是对象。
实体类中的属性名和表中的字段名不一样怎么办
-
在查询的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>
-
通过
<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是如何将sql执行结果封装为目标对象并返回的?有哪些映射方式?
- 第一种是通过resultMap标签,将数据库列名与对象属性名之间一一映射
- 第二种是根据sql列的别名,将列的别名书写为对象的属性名
有了列名和属性名的映射关系后,MyBatis通过反射创建对象,使用反射给对象的属性逐一赋值并返回,找不到映射关系的属性是无法赋值的。
动态SQL
Mybatis动态sql可以在Xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值 完成逻辑判断并动态拼接sql的功能。
Mybatis提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。
Spring
控制反转
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类于类之间高度耦合。有了IoC容器后,把创建和查找依赖对象的控制权交给了容器(控制反转),由容器进行注入组合对象(依赖注入)。传统应用程序下,缺少jar包不能通过编译,在采用IoC思想后,可以完成编译但无法正常完成功能。
DI--Dependency Injection,依赖注入:由容器动态的将某个依赖关系注入到组件中。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁住入谁,注入了什么”
- 谁依赖谁:应用程序依赖于IoC容器;
- 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
- 谁诸如谁:IoC容器注入应用程序某个对象,应用程序依赖的对象;
- 注入了什么:注入某个对象所需要的外部资源
本质上IoC和DI是同一思想下不同维度的表现,IoC是bean的注册,DI是bean的初始化
AOP
aop可以将业务流程中重复的流程抽取出来,单独的编写功能代码。在业务流程执行的过程中,Spring框架hi根据业务流程要求,自动把独立编写的功能代码切入到流程的合适位置。
AOP相关术语
-
Joinpoint(连接点)
所谓连接点就是那些到拦截到的点。在Spring中,这些点指的是方法,因为Spring只支持方法类型的连接点
-
Pointcut(切入点)
所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
-
Advice(通知/增强)
所谓通知就是拦截到Joinpoint之后要做的事情。
通知的类型:前置通知、后置通知、异常通知、最终通知、环绕通知 -
Introduction(引介)
引介是一种特殊的通知在不修改类代码的前提下,Introduction可以在运行期间为类动态地增加一些方法或Field
-
Target(目标对象)
代理的目标对象
-
Weaving(织入)
是指把增强应用到目标对象来创建新的代理对象的过程
Spring采用动态代理织入,而Aspect J采用编译期间织入和类装载期织入 -
Proxy(代理)
一个类被AOP织入增强后,就产生一个结果代理类
-
Aspect(切面)
是切入点和通知(引介)的结合
Spring容器、BeanFactory和ApplicationContext
spring容器可以理解为生产对象的地方,它负责了对象的整个生命周期--创建、装配、销毁。这些对象的创建管理的控制权都交给了Spring容器。
BeanFactory和ApplicationContext之间的关系
- BeanFactory和ApplicationContext是Spring的两大核心接口,而其中ApplicationContext是BeanFactory的子接口。它们都可以当作Spring的容器
- BeanFactory并不常用,是最简单的容器,只能提供基本的DI功能
- ApplicationContext是继承了BeanFactory后派生出来的,它能提供更多的企业级的服务,例如解析配置文本信息等,这也是ApplicationContext最常见的应用场景
@Scope注解
默认是单例模式,即scope = singleton
,另外还有prototype,request,session,global session
-
singleton单例模式
全局仅有一个实例
-
prototype原型模式
每次获取bean的时候会有一个新的实例
xml和注解选择的问题
springMVC
springMVC执行流程
-
前端控制器DispatcherServlet:
作用:接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其他组件之间的耦合度。
用户请求到达前端控制器,由它进行调度。 -
处理器映射器HandlerMapping:
作用:根据请求的url查找Handler
Handler其实就是Controller。处理器映射器根据url找到相应的controller并返回一个执行链。Handler是对Controller的bean本身和请求method的包装。而HandlerExecutionChain是handler的二次包装,将handler与拦截器关联到一起。然后在DisaptcherSerlet中完成拦截器对handler的过滤。 -
处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
-
处理器Handler
Handler是继DispatcherServlet前端控制器之后的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Hanler涉及到具体的用户业务请求,所以一般情况需要工程师根据业务需求开发Handler -
视图解析器ViewResolver
作用:进行视图解析,根据配置拼接前后缀,解析成视图具体的页面地址,在生成view视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
注解
@PathVariable和@RequestParam的区别
PathVariable只能用于接收url路径上的参数,而RequestParam只能用于接收请求带的params
@GetMapping("/books/{username}")
public Object testPathVariable(@PathVariable String username)
@PostMapping("/books2")
public Object testRequestParam(@RequestParam("name") String name,
@RequestParam("author") String author,
@RequestParam("isbn") String isbn)
例如路径为/books/zfz testPathVariable可以接收username的值为zfz @RequestParam注解则不能接收
@RequestParam 通过这样的路径接收数据 ***books2?name=java in action&author=ric&isbn=dsdas2334
参考:https://blog.csdn.net/u012062455/article/details/80960200
@GetMapping、@PostMapping和@RequestMapping的区别
@RequestMapping相当于@GetMapping和@PostMapping的父类。
@GetMapping
用于将HTTP GET请求映射到特定处理程序方法的注释。具体来说,@GetMapping是一个作为快捷方式的组合注释
@RequestMapping(method = RequestMethod.GET)。-
@PostMapping
用于将HTTP POST请求映射到特定处理程序方法的注释。具体来说,@PostMapping是一个作为快捷方式的组合注释@RequestMapping(method = RequestMethod.POST)。
@ResponseBody
将controller方法返回对象转换为json响应给客户端
GET和POST的区别
GET | POST | |
---|---|---|
POST | 无害 | 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。 |
书签 | 可收藏为书签 | 不可收藏为书签 |
缓存 | 能被缓存 | 不能缓存 |
编码类型 | application/x-www-form-urlencoded | application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。 |
历史 | 参数保留在浏览器历史中。 | 参数不会保存在浏览器历史中。 |
对数据长度的限制 | 是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 | 无限制。 |
对数据类型的限制 | 只允许 ASCII 字符。 | 没有限制。也允许二进制数据。 |
安全性 | 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET ! | POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。 |
可见性 | 数据在 URL 中对所有人都是可见的。 | 数据不会显示在 URL 中。 |