一、#{}和${}的区别
1、演示代码
(1)准备实体类 Account
package com.powernode.bank.pojo; public class Account { private Long id ; private String actno; private Double balance; ....
(2)准备 AccountMapper.xml文件
<?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="account"> <select id="selectByActno" resultType="com.powernode.bank.pojo.Account"> select * from t_act where actno = #{actno} </select> </mapper>
(3)测试类
public class Test { @org.junit.Test public void test1(){ SqlSession sqlSession = SqlSessionUtil.openSqlSession(); Account account = sqlSession.selectOne("account.selectByActno", "act001"); System.out.println(account.toString()); } }
先测试 #{} 语法,运行结果如下:
17:03:22.973 default [main] DEBUG o.a.i.t.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@71ba6d4e] 17:03:22.978 default [main] DEBUG account.selectByActno - ==> Preparing: select * from t_act where actno = ? 17:03:23.026 default [main] DEBUG account.selectByActno - ==> Parameters: act001(String) 17:03:23.080 default [main] DEBUG account.selectByActno - <== Total: 1 Account{id=1, actno='act001', balance=10004.0}
在测试 ${}语法,运行结果如下:
17:04:15.335 default [main] DEBUG o.a.i.t.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1cf6d1be] 17:04:15.342 default [main] DEBUG account.selectByActno - ==> Preparing: select * from t_act where actno = act001 17:04:15.414 default [main] DEBUG account.selectByActno - ==> Parameters: org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column 'act001' in 'where clause'
2、区别描述
1、#{}:底层使用PreparedStatement。特点:先进行SQL语句的编译, 然后给SQL语句的占位符问号?传值。可以避免SQL注入的风险。 2、${}:底层使用Statement。特点:先进行SQL语句的拼接, 然后再对SQL语句进行编译。存在SQL注入的风险。优先使用#{},这是原则。 避免SQL注入的风险。
二、什么时候使用 ${}
1、当需要往sql语句中,传入关键字时,可以是使用${},比如 前端传递排序字段值 asc或者 desc
案例场景:前台传入排序字段值,该值为mysql关键字,我们分别使用#{}和${}来处理:
#{}的执行结果,将关键字加了单引号 ,造成语法错误: select car_num as carNum, brandfrom t car order by produce_time 'asc'
${}的执行结果,相当于拼接了关键字: select car_num as carNum, brandfrom t car order by produce_time asc
2、或者想先进行sql语句拼接,然后再对sql语句进行编译,再执行时,也可以使用 ${}
三、拼接表名
场景: 现实业务当中,可能会存在分表存储数据的情况。因为一张表存的话,数据量太大。查询效率比较低。可以将这些数据有规律的分表存储,这样在查询的时候效率就比较高。因为扫描的数据量变少了。 日志表:专门存储日志信息的。如果t_log只有一张表,这张表中每一天都会产生很多log,慢慢的,这个表中数据会很多。 怎么解决问题? 可以每天生成一个新表。每张表以当天日期作为名称,例如: t_log_20220901 t_log_20220902 .... 你想知道某一天的日志信息怎么办? 假设今天是20220901,那么直接查:t_log_20220901的表即可。 所以 ,向SQL语句当中拼接表名,就需要使用${}
四、批量删除
1、批量删除:一次删除多条记录。 2、批量删除的SQL语句有两种写法: 第一种or: delete from t car where id=1 or id=2 or id=3 第二种int: delete from t car where id in(1,2,3); 应该采用 ${} 的方式: delete from t_car where id in(${ids}); 代码如下:
<?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="account"> <delete id="deleteBatch"> delete from t_act where id in (${ids}) </delete> </mapper>
@Test public void testDelete(){ SqlSession sqlSession = SqlSessionUtil.openSqlSession(); int deleteBatch = sqlSession.delete("deleteBatch", "1,2"); System.out.println(deleteBatch); sqlSession.commit(); sqlSession.close(); }
运行结果
22:20:06.304 default [main] DEBUG account.deleteBatch - ==> Preparing: delete from t_act where id in (1,2) 22:20:06.376 default [main] DEBUG account.deleteBatch - ==> Parameters: 22:20:06.380 default [main] DEBUG account.deleteBatch - <== Updates: 2 2
五、模糊查询
模糊查询: like
需求:根据汽车品牌进行模糊查询 select * from t car where brand like'%奔驰%'; select * from t car where brand like'%比亚迪%'; 在mybatis的xml文件中有如下写法: 第一种方案: '%${brand}%' 第二种方案:concat函数,这个是mysql数据库当中的一个函数,专门进行字符串拼接 concat('%' ,#{brand},'%') 第三种方案:比较鸡肋了。可以不算。 concat('%','${brand}', '%') 第四种方案: "%"#{brand} "%"
六、起别名
1、核心配置文件mybatis-config.xml 增加typeAliases标签,用来配置别名
<?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 resource="jdbc.properties"/> <typeAliases> <typeAlias type="com.powernode.bank.pojo.Account" alias="account"/> </typeAliases> <environments default="development"> .......
2、修改sql文件,resultType的值可以直接使用别名,并且不区分大小写
<select id="selectActLike" resultType="account"> select * from t_act where actno like concat ('',#{actno},'%') </select>
七、mybatis-config.xml文件的mapper配置
1、mybatis-config.xml文件中的mappers标签。
<mapper resource="CarMapper.xml"/> 要求类的根路径下必须有:CarMapper.xml <mapper url="file:///d:/CarMapper.xml"/> 要求在d:/下有CarMapper.xml文件 <mapper class="全限定接口名,带有包名"/>
2、mapper标签的属性可以有三个:
resource:这种方式是从类的根路径下开始查找资源。采用这种方式的话, 你的配置文件需要放到类路径当中才行。 url:这种方式是一种绝对路径的方式,这种方式不要求配置文件必须放到类路径当中, 哪里都行,只要提供一个绝对路径就行。这种方式使用极少 class:这个位置提供的是mapper接口的全限定接口名,必须带有包名的。
3、思考:mapper标签的作用是指定SalMapper.xml文件的路径,指定接口名有什么用呢?
<mapper class="com.powernode.mybatis.mapper.CarMapper"/> 如果你class指定是:com.powernode.mybatis.mapper.CarMapper 那么mybatis框架会自动去com/powernode/mybatis/mapper目录下查找CarMapper.xml文件。
注意:也就是说:
如果你采用这种方式,那么你必须保证CarMapper.xml文件和CarMapper接口必须在同一个目录下。 并且名字一致。 CarMapper接口-> CarMapper.xml LogMapper接口-> LogMapper.xml ....
八、获取插入数据时自动生成的主键
<insert id="insertAct" useGeneratedKeys="true" keyProperty="id"> insert into t_act values (null,#{actno},#{balance}) </ins
说明:
useGeneratedKeys="true" 使用自动生成的主键值 keyProperty="id" 指定主键值赋给对象的哪个属性