当前位置: 首页 > article >正文

【Mybatis】预编译/即时sql 数据库连接池

回顾

  •  Mybatis是一个持久层框架.
  • 有两种方式(这两种方式可以共存)

   1.注解

   2.xml

一.传递参数

以使用#{} 来接受参数为例

(以上两种方式一样适用的)

1)传递单个参数

#{} 可以为任意名称

2)多个参数

默认的参数名称就是接口方法声明的形参

3)参数为对象

默认给每个对象的每个属性都有一个参数 , 以对象的属性名为参数名.

重命名

可以用@Param注解给参数重命名  , 引用的时候需要使用#{对象名.属性名}

结果映射

Mybatis会自动把mysql返回的数据和Java对象进行映射(根据名称)
如果mysql字段和Java对象的属性名不一致

注解有三种方式

1.给mysql字段设置别名

2.通过@Results映射

3.通过配置自动将mysql字段转驼峰

xml也有三种方式

1.给mysql字段设置别名

2.通过<resultMap>标签

3.通过配置自动将mysql字段转驼峰

二.多表查询

工作中尽量避免多表查询,尤其是对性能要求非常高的项目.

SQL中直接查询多个表,把查询的结果放在一个对象即可.

Mybaits不分单表还是多表.

三.#{} 和 ${} 的区别

这是mybatis赋值的两种方式.

3.1Integer类型的参数

1.使用#查询

可以发现sql语句的参数使用的 ? 进行占位.

2.使用$查询

使用$, 会直接拼接.

3.2字符串类型的参数

1.使用#查询

会自动加上' '

2.使用$查询

直接拼接, 不会自动加上' ' ;

因此如果参数是字符串,需要加上单引号 ' '

参数是数字类型,也可以加上,查询结果不变,但是可能会导致索引失效,性能失效.

其实上述#{}和${}的区别也就是预编译sql和即使sql的区别

即使sql

一条sql语句执行的顺序的大致流程如下:

1.解析语法和语义

2.优化sql

3.执行sql

如果一条sql执行了上述流程,就称之为 即时sql

预编译sql

大多数情况下,某一条sql会被反复执行(只有一些参数的变化),如果每次都经过上述的三个完整的步骤,势必会影响到效率.

如果编译一次之后就将编译后的sql语句缓存起来,后面再次执行这条语句的时候,不会再次编译,省去了解析优化的过程,以此来提交效率.  这种sql语句就叫预编译sql.

对于#和$,他们有不同的使用场景.有的情况下,使用#是正确的,而有的情况下,使用#却会报错.

比如

select * from user where username= #{ xxx }

这条语句需要一个字符串参数,此时使用# , sql会自动加上' ' ,此时sql语句是正确的.

但是比如排序查询

 select * from user order by #{ xxx }

这条语句是排序, 需要传入参数asc或者desc. 同样也是字符串,

如果使用#,,会给参数加上' ' , 这反倒多此一举了.

还有like模糊查询

select * from user where username=' #{aa}% '

自动加上' '后,无法查询

这种情况下,如果换成$ { },它不会自动加上'' ,看似可以很好的解决问题 .

但是$存在的一个严重的漏洞:SQL注入

正确的解决方法是使用mysql的内置函数concat . 

SQL注入

通过操作输入的数据来修改实现定义好的sql语句,来对服务器进行攻击.

由于没有对用户的输入进行严格的检查,而sql又是拼接而成,当在参数中添加了一些关键字,就可以达到改变sql运行结果的目的.

比如将 ' or 1 = '1 注入到这条sql中

select * from user where username = '${ name } ' 

最后显示的sql就是

select * from user where username ='  ' or 1 = '1 '

此时一定会将所有的行都查询出来,改变了原来的目的.

为什么${}会sql注入

为什么#和$都要加上' ',只有$会存在sql注入问题呢

这是因为#是预编译sql. 预编译sql使用占位符代替字段值,它会被交由数据库预处理,后面传入的值都会被当作值来看待,而不会出现非编译时候的查询 !

$是即时sql.即时sql每次都会经历语法解析,优化和执行的过程,每次传入的值会直接拼接成sql语法,重新解析和执行.

总结注意事项

1.排序                                  不能使用#

2.表名/字段名作为参数        也不能能用#

3.模糊查询                           如果使用# , 使用mysql的内置函数concat函数

4.实际开发中,尽量使用# ;    使用$时,一定要考虑sql注入

预编译sql和即时sql的区别

1.预编译sql的性能更高(有缓存)

2.预编译sql 不存在sql 注入的问题

四.数据库连接池

负责分配,管理,释放数据库连接,避免频繁的创建,销毁连接.它允许应⽤程序重复使⽤⼀个现有的数据库连接,⽽不是再重新建⽴⼀个.

如果不适用数据库连接池,每次执行sql语句,都要先创建一个连接,然后再执行sql语句,执行完还要关掉连接对象释放资源,这种重复的创建连接,销毁连接会比较消耗资源.

而使用数据库连接池,程序启动时,会再数据库连接池中创建一定数量的Connection对象,当客户请求数据库连接,会从数据库连接池中获取Connection对象,然后执行sql,执行完毕之后再把Connection归还给连接池.

优点

1. 减少了⽹络开销

2. 资源重⽤

3. 提升了系统的性能

常⻅的数据库连接池

• C3P0

• DBCP

• Druid

• Hikari

SpringBoot默认使用的数据库连接池Hikari

启动程序的时候就可以看到

目前比较流行的数据库连接池是Durid 和 Hikari

• Druid连接池是阿⾥巴巴开源的数据库连接池项⽬

• 功能强⼤,性能优秀,是Java语⾔最好的数据库连接池之⼀


如果想要切换数据库连接池为druid , 直接引入依赖即可

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.17</version>
</dependency>


总结

1.表名, 字段名使⽤⼩写字⺟或数字, 单词之间以下划线分割. 尽量避免出现数字开头或者两个下划线

中间只出现数字. 数据库字段名的修改代价很⼤, 所以字段名称需要慎重考虑。

MySQL 在 Windows 下不区分⼤⼩写;

在 Linux 下默认是区分⼤⼩写. 因此, 数据库名, 表名, 字段名都不允许出现任何⼤写字⺟

2. 表必备三字段: id, create_time, update_time

id 必为主键, 类型为 bigint unsigned, 单表时⾃增, 步⻓为 1

create_time, update_time 的类型均为 datetime 类型, create_time表⽰创建时间,update_time表⽰更新时间

3. 在表查询中, 避免使⽤ * 作为查询的字段列表, 标明需要哪些字段

4.#{} 和${} 区别

4.1 #{}:预编译处理, ${}:字符直接替换

4.2 #{} 可以防⽌SQL注⼊, ${}存在SQL注⼊的⻛险, 查询语句中, 可以使⽤ #{} ,推荐使⽤ #{}

4.3但是⼀些场景, #{} 不能完成, ⽐如 排序功能, 表名, 字段名作为参数时, 这些情况需要使⽤${}

4.4模糊查询虽然${}可以完成, 但因为存在SQL注⼊的问题,所以通常使⽤mysql内置函数concat来完成


http://www.kler.cn/a/148284.html

相关文章:

  • 准确率调整研究中心
  • PostgreSQL分区表:基础语法与运维实践
  • 前端框架大比拼:React.js, Vue.js 及 Angular 的优势与适用场景探讨
  • 密码学的基本原理
  • uniapp+vue2 设置全局变量和全局方法 (兼容h5/微信小程序)
  • webpack loader全解析,从入门到精通(10)
  • linux进入telnet和推出telnet
  • 零基础在ubuntu上搭建rtmp服务器-srs
  • 关于Redis底层的两个问题
  • 18、Android 组件化
  • C++中的map和set的使用
  • 【Spark入门】基础入门
  • facebook引流软件需要具备什么功能
  • 相关性分析和作图
  • php高级工程师范文模板
  • 完美解决:Nginx访问PHP出现File not found.
  • 逆向扒cocosjs安卓包教程-破解加密的js源码
  • vue+elementUI的tabs与table表格联动固定与滚动位置
  • 【JUC】十二、CompletableFuture(上)
  • Java 之 lambda 表达式(二)---- Stream 操作 API
  • C语言—什么是数组名
  • 5种主流API网关技术选型,yyds!
  • Python基础语法之学习print()函数
  • JAVA 使用stream流将List中的对象某一属性创建新的List
  • ubuntu中root和普通用户切换方法
  • LeetCode Hot100 20.有效的括号