目录
一、实现多表查询
二、#{}和${}
1、#{}和${}的使用
2、#{}和${}的区别
3、${}的使用场景
三、数据库连接池
1、数据库连接池概念
2、常见数据库连接池
3、修改连接池为Hikari
四、动态sql语句--xml
1、if标签
2、tirm标签
3、where标签
4、set标签
5、foreach标签
6、include标签
五、动态sql语句--注解
一、实现多表查询
1、准备两张表
userinfo表:
对应实体类:
articleinfo表:
对应实体类:
2、执行sql语句
若要查articleinfo表中id为1的书信息和用户信息,则需要进行多表查询。
多表查询的sql语句:select ta.id,ta.title,ta.content,ta.uid,tb.username,tb.age,tb.gender,tb.phone from articleinfo ta left join userinfo tb on ta.uid = tb.id where ta.id=1.
这时需要增加ArticleInfo类的属性,从而来接收多表查询的结果。
3、代码实现
4、测试
运行结果:
二、#{}和${}
#{}和${}都可以用于取参数值
1、#{}和${}的使用
(1)Integer类型的参数--根据id查询用户
#{}:
${}:
发现#{}是预编译sql,有?进行占位;${}是即时sql。
(2)String类型的参数--根据username查询用户
#{}:
${}:
当参数是字符串时,${}接收参数时,无法加引号,导致无法识别。
接收参数时将引号加上:
2、#{}和${}的区别
(1)#{}是预编译sql,性能更高;${}是即时sql。
即时sql的步骤:①解析语法和语义,检验sql语法是否正确;②优化sql语句,制定执行计划;③执行并返回结果。
预编译sql与即时sql的区别:一个sql语句若被反复执行或只是参数改变的,每一次执行若都需要经过以上步骤的话,则效率就会下降。此时预编译sql就会进行优化,编译一次sql语句后,就会将sql语句缓存起来,后面再执行这条语句时,不会再次编译,省去了解析优化等过程,直接执行,以此来提高效率。
(2)#{}更安全,${}有sql注入的风险。
sql注入:通过操作输入的参数,从而修改定义好的sql语句,已达到执行代码对服务器的攻击。
eg:根据username查询用户
正常输入username就会查询,但若进行sql注入的话:
'or 1='1一直为真,导致查询到所有结果。此时就是sql注入问题。
3、${}的使用场景
(1)排序功能
查询所有用户,并根据id升序
sql语句:select id,username,'password',age,gender,phone,delete_flag,create_time,update_time from userinfo order by id asc
#{}:
运行结果:
?处不应该有引号,所以不能使用#。
${}:
但需要考虑sql注入的问题,可以考虑升序和降序对应两个url,获取到url后由后台处理参数,客户端不输入参数。
(2)模糊匹配
查询姓名是‘l’开头的用户
sql语句:select id,username,'password',age,gender,phone,delete_flag,create_time,update_time from userinfo where username like '%l%';
#{}:
?处不应该有引号,所以不能使用#。
${}:
但需要考虑sql注入的问题,可以进行字符串拼接:
三、数据库连接池
1、数据库连接池概念
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
没有使用数据库连接池:每次在执行sql语句时,都需要重新进行数据库连接,建立一个新的连接对象,然后执行sql语句,语句执行完成后,再关闭连接释放资源。再次执行语句时,重复操作。这种重复的创建连接、释放资源比较消耗资源。
使用数据库连接池:程序启动时,会在数据库连接池创建一定数量的连接对象。每次在执行sql语句时,从线程池中拿连接对象,然后执行sql语句,语句执行完成后,再将连接对象放回连接池。减少了资源利用。
2、常见数据库连接池
C3P0、DBCP、Druid、Hikari。
springboot默认使用连接池为Druid
3、修改连接池为Hikari
引入相关依赖即可:
四、动态sql语句--xml
1、if标签
对于有一些属性,有默认值,比如userInfo中的gender的默认值为0,若该属性为非必填字段,如何使得不填值时为默认值,而不是为空值,此时可以使用if标签
(1)不使用if标签,gender不填值效果:
运行结果:
(2)使用if标签,gender不填值效果:
运行结果:
(3)if标签存在的问题
eg:
增加一个phone为空的userInfo对象,运行结果:
既然这样不行,那将逗号移到前面:
增加一个username为空的userInfo对象,运行结果:
我们发现,将逗号移到后面时,当最后一个属性为空时会报错;将逗号移到前面时,当第一个属性为空时会报错。有没有什么方法可以使得第一个属性为空时前面不会多一个逗号,最后一个属性为空时后面不会多一个逗号。考虑trim标签
2、tirm标签
(1)4个属性
(2)使用tirm标签解决上述问题
使用prefixOverrides删除前面多余逗号,使用suffixOverrides删除后面多余逗号;
可以使用prefix加'(',使用suffix加')'。
此时就可以很好的解决逗号问题了。
3、where标签
(1)不使用where标签存在的问题
根据username和age查询用户:
根据姓名为空的userInfo对象进行查询:
和逗号一样的问题,前一个属性为空,导致多出一个and,可以使用where标签解决问题。为什么不使用trim标签解决and问题???因为当属性都为空时,where也需要删除,但trim标签只能规定删除and,不能删除where,而where标签可以做到。
(2)where标签解决问题
此时就可以解决上述问题了。
4、set标签
可以解决在进行update操作时,删除可能多出的逗号,当然trim标签也可以。
5、foreach标签
对集合进行遍历时可以使用该标签。
例如:当需要删除多个用户时,传入的用户id就是一个集合,就需要遍历集合,根据id找到信息,从而进行删除。
运行结果:
6、include标签
可以对重复的代码片段进行抽取,降低冗余性。通过sql标签封装到一个SQL片段,然后再通过include标签进行引用。
代码实现:
include标签使用:
五、动态sql语句--注解
注解方法不推荐使用,单引号问题比较繁琐,且注解和xml的做法大同小异,以delete举个例子就能明白如何写了。
主要是在xml基础上加script标签,但要考虑单引号,不建议使用。