#{}和${}
- #{}:先编译sql语句,再给占位符传值,底层是PreparedStatement实现。可以防止sql注入,比较常用
- ${}:先进行sql语句拼接,然后再编译sql语句,底层是Statement实现。存在sql注入现象,只有在需要sql语句关键字拼接的情况下才会用到。
两者分别执行如下的sql语句
select
id,
car_num as carNum,
brand,
guide_price as guidePrice,
produce_time as produceTime,
car_type as carType
from
t_car
where
car_type = #{carType}//以及${catType}
两者的运行日志如下所示
-
#{}传到mysql中执行的语句是
select id, car_num as carNum, brand, guide_proce as guidePrice, produce_time as produceTime, car_type as carType from t_car where car_type = ?
-
${}传到mysqk中执行的语句是
select id, car_num as carNum, brand, guide_proce as guidePrice, produce_time as produceTime, car_type as carType from t_car where car_type = 新能源
(新能源是后续传入的值),但是这句sql语句已经出现了语法错误,新能源都没加单引号
#{}和${}的区别:
- #{}:底层使用PreparedStatement,特点:先进行SQL语句的编译,然后给SQL语句的占位符问好?传值,可以避免SQL注入的风险。
- ${}:底层使用Statement,特点:先进行SQL语句的拼接,然后再对SQL语句进行编译,存在SQL注入的风险。
关于${}的使用时机
sql语句传入关键字
当往sql语句中传关键字,关键字不能被引号引起来,所以就得用${},直接将传入的关键字拼接到sql语句当中
拼接表名
现实业务当中,可能会存在分表存储数据的情况。
因为一张表存的话,数据量太大。查询效率比较低。
可以将这些数据有规律的分表存储,这样在查询的时候效率就比较高。因为扫描的数据变少了。
日志表:专门存储日志信息的。如果t_log只有一张表,这张表中每天都会产生很多log,慢慢的,这个表中数据会有很多
怎么解决这个问题?
- 可以每天生成一个新表。每张表以当天日期作为名称,例如:
t_log_20230701
t_log_20230702
t_log_20230703
t_log_20230704
and so on
如果想知道某一天的日志信息怎么办?
假设今天是20500101,那么直接查20500101的表就好了
而在查询关于表的时候就要输入日期这个数字,而表名又不需要加引号,所有就要使用${}
批量删除
批量删除的SQL语句有两种写法:
第一种or:delete from t_car where id=1 or id=2 or id=3;
第二种and:delete from t_car where id in(1,2,3);
应该采用 的方式: ‘ d e l e t e f r o m t c a r w h e r e i d i n ( {}的方式: `delete from t_car where id in( 的方式:‘deletefromtcarwhereidin({ids});`
模糊查询
模糊查询like
需求:根据汽车品牌进行模糊查询
select * from t_car where brand like '%奔驰%';
select * from t_car where brand like '%比亚迪%';
第一种方案:
'%${brand}%'
第二种解决方案:concat函数,这个是MySQL数据库当中的一个函数,专门进行字符串拼接
concat('%',#{brand},'%')
第三种方案:比较鸡肋,可以不算
concat('%',${brand},'%')
第四种方案
"%"#{brand}"%"
别名机制
在mybatis-config.xml文件中的configuration根标签中
<typeAliases>
<!--
type:指定给哪个类型起别名
alias:指定别名
注意:1、别名不区分大小写
2、如果省略alias之后,别名就是类的简名
比如com.powernode.mybatis.pojo.Car的别名就是car/Car/CAr/CaR,不区分大小写
-->
<typeAlias type="" alias="" />
<!--
会将这个包下的所有的类全部自动起别名,别名就是类简名,不区分大小写
-->
<package name="com.powernode.mybatis.pojo"/>
</typeAliases>
可以把又长又臭的resultType路径什么的改简单一些,但是namespace不能起别名
mapper配置
mybatis-config.xml文件中的mapper标签
<mapper resource=" "/>
<mapper url=" "/>
<mapper class=" "/>
mapper标签的属性可以有三个:
- resource:这种方式是从类的根路径下开始查找资源。采用这种方式的话,你的配置文件需要放到类路径当中才行。
- url:这种方式是一种绝对路径的方式,这种方式不要求配置文件必须放到类路径当中,哪里都行,只要提供一个绝对路径就行。这种方式使用极少,因为移植性太差
- class:这个位置提供的mapper接口的全限定接口名,必须带有包名的
思考:mapper标签的作用是指定SqlMapper.xml文件的路径,指定接口名有什么用呢?
<mapper class="com.powernode.mybatis.mapper.CarMapper">
如果你class指定的是com.powernode.mybatis.mapper.CarMapper
那么mybatis框架会自动去com/powernode/mybatis/mapper目录下查找CarMapper.xml文件
注意:也就是说,如果拟采用这种方式,那么就必须要保证CarMapper.xml文件和CarMapper接口必须是在同一个目录下的,并且名字一致。(可以在resource中创建同样的一个目录)
<mapper resource="CarMapper.xml "/>
要求类的根路径下必须有:CarMapper.xml
<mapper url=" file:///d:/CarMapper.xml"/>
要求在d:/下有CarMapper.xml文件
<mapper class=" "/>
在IDEA的resource目录下新建多重目录的话,必须是这样建
com/powernode/mybatis/mapper
不能这样
com.powernode.mybatis.mapper
配置模板文件
可以在文件->设置->编辑器->代码样式->文件和代码模板中加入MyBatis的核心配置文件和SQL映射文件的模板
<!-- MyBatis核心配置文件-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resources="" />
<typeAliases>
<package name="">
</typeAliases>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="">
</mappers>
</configuration>
<!-- SQL映射文件 -->
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
</mapper>
使用自动生成的主键
需要我们在插入数据的同时获取到mysql自动生成的主键值,虽然先插入再查询获取也可以,但是这样是分步了。
<insert id="insertCarUseGeneratedKeys" userGeneratedKeys="ture" keyProperty="id">
insert into t_car values(null,#{carNum},#{brand},#{produceTime},#{carType})
</insert>
userGeneratedKeys
是是否开启自动生成的主键keyProperty
是将自动生成的主键赋值到何处,这里就是赋值到Car类car对象的id属性名里面去