1.#{}和${}使用
Interger类型的参数可以看到这里显示的语句是:select username,password,age,gender,phone from userinfo where id=? 输入的参数并没有在后面进行拼接,,id的值是使用?进行占位,这种sql称之为"预编译sql".这里,把#{}改成${}观察情况:
这里可以看到select username,password,age,gender,phone from userinfo where id=5,参数是直接拼接在sql语句中了.接下来是String类型的参数.
观察日志,这里还是使用的占位符,进行预编译.
将#{}改成${}之后,观察
会报下面的错误
这里参数还是直接拼接在sql语句中,但是字符串作为参数传递时,需要添加' ',使用${}不会拼接引号,导致程序报错,既然${}是直接拼接的,就直接在${}上面加上' '即可.
从这两个例子可以看出,#{}是使用预编译SQL,通过?占位的方式,提前对SQL进行编译,然后把参数填充到SQL语句中.#{}会根据参数类型,自动拼接引号' '. ${}会直接进行字符产替换,一起对SQL进行编译.如果参数为字符串,需要加上引号''.
2.#{}和${}的区别
#{}和${}的区别就是预编译SQL和即时SQL的区别.一个即时SQL的流程:1.解析语法,检验SQL语句是否正确. 2.优化SQL语句,指定执行计划 3.执行并返回结果. #{}比${}的性能更高,绝大多数情况下,某一条SQL语句会被反复调用执行,或是每次执行的时候只有个别的值不同,如果每次都要经过语法解析,SQL优化,SQL编译等,则效率就明显不行了.预编译SQL,在编译一次之后会将编译后的SQL语句缓存起来,后面再次执行这条语句时,不会再次编译,省去了解析优化的等过程,以此来提高效率. #{}比${}更加安全,可以防止SQL注入,SQL注入是指:是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法.由于${}是直接进行拼接的,因此会有sql注入的风险,尽量使用#{}与查询的方式.
3.${}的使用场景:排序功能
如果使用#{},由于是预编译,会主动补充"",但是这个不需要"",所以会报错.
4.数据库连接池
数据库连接池负责分配,管理和释放数据库连接,允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个.没有数据库连接池的情况:每次执行sql语句,都要先创建一个新的连接对象,然后执行SQL语句,SQL语句执行完,再关闭连接对象释放资源,这种重复的创建链接,销毁连接比较消耗资源.使用数据库连接池的情况:程序启动时,会在数据库连接池中创建一定数量的Connection对象,当客户请求数据库连接池,会从数据库连接池中获取Connection对象,然后执行SQL,SQL语句执行完,再把Connection归还给连接池.使用数据库连接池的优点:1.减少了网络开销 2.资源重用 3.提升了系统的性能.SpringBoot默认使用的数据库连接池是HiKari.
5.动态SQL:动态SQL在Mybatis中用于不同条件下的sql拼接.
5.1 if标签,针对前端一些可能为空的字段,可以使用if标签来进行接收.动态sql推荐使用xml配置的写法,使用注释的写法较为不便.下面是性别这一项,可以为空,用动态sql来进行接收.如果这里添加的时候,不设置gender的值,sql语句如下:
设置gender的值,sql语句如下:
可以看到这里会根据是否设置gender的值,来进行sql语句的设置.这里test中的gender,是传入对象中的属性,不是数据库字段.
5.2这里是只有一个属性的情况下,那如果是有多个gender字段,一般考虑使用标签结合标签,对这多个字段都采用动态生成的方式.这个动态sql的本质,就是对字段是否为空,进行判断,然后把不为空的字段进行拼接,为了使拼接后的sql语句符合语法,<tirm>标签有下面的属性.prefix:表示整个语句块,以prefix的值作为前缀. suffix:表示整个语句块,以suffix的值作为后缀 prefixOverrids:表示整个语句块要去掉的前缀 suffixOverrids:表示整个语句块要去除掉的后缀.如果将上面的五个属性都设置为可选填的,则Mapper.xml的插入语句为:在上面的sql动态解析时,会做下面的处理,基于prefix配置,开始时加上( 基于suffix配置,结束时加上)基于suffixOverrides配置会在语句的最后去掉,(如果有的话).这里还是要注意<if test='username!=null'>中的username是传入对象的属性. 5.3<where标签> 根据年龄,性别,是否删除这属性中的某几项插叙用户信息.
这里并没有类似<tirm>标签中,去除前缀和后缀的选项,原因是<where>只会在子元素有内容的情况下才会插入where子句,而且会自动去除子句开头的AND或OR. 5.4<set>标签:这里根据对象属性来更新用户属性
5.5<foreach>标签:对集合进行遍历时可以使用该标签,属性如下: collection:绑定方法参数中的集合,如:List,set,map或数组对象. item:遍历时的每一个对象 open:语句块开头的字符串 close:语句块结束时的字符串 separator:每次遍历之间间隔的字符串5.6<include>标签:在xml映射文件中的SQL,有时可能会存在很多的重复片段,此时就会存在很多的冗余代码.,我们可以对重复的代码片段进行抽取,将<sql>标签封装到一个SLQ片段,然后可以通过<include>标签进行引用.<sql>:定义可重用的SQL片段 <include>:通过属性refid,指定包含的SQL片段.