其他查询操作
多表查询
查询sql:SELECT ta.id,ta.title,ta.content,ta.uid,tb.username,tb.age,tb.gender FROM articleinfo ta LEFT JOIN userinfo tb ON ta.uid = tb.id WHERE ta.id = #{id}
由于返回的数据中出现了其他表的数据,因此相应接收的Java类就要添加对应的属性.
@Data
public class ArticleInfo {
private Integer id;
private String title;
private String content;
private Integer uid;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
//添加⽤⼾相关信息
private String username;
private Integer age;
private Integer gender;
}
其余相关操作无需变化.
@Select("SELECT ta.id,ta.title,ta.content,ta.uid,tb.username,tb.age,tb.gender " +
"FROM articleinfo ta LEFT JOIN userinfo tb ON ta.uid = tb.id " +
"WHERE ta.id = #{id}")
ArticleInfo queryUserByUid(Integer id);
@Test
void queryUserByUid() {
System.out.println(articleInfoMapper.queryUserByUid(1));
}

#{}和${}
MyBatis提供了两种赋值方式,#{}和${}.
#{}和${}的使用
观察对Integer类型进行赋值时的差异
@Select("select * from userinfo where id = #{id}")
List<UserInfo> selectUserInfoById(Integer id);
@Select("select * from userinfo where id = ${id}")
List<UserInfo> selectUserInfoById2(Integer id);


观察到,在使用#{}时,sql语句是一个有占位符的预编译sql,而使用${}时是直接将参数拼接在sql语句中.
对String类型进行赋值:
@Select("select * from userinfo where username = #{username}")
List<UserInfo> selectUserInfoByName(String username);
@Select("select * from userinfo where username = ${username}")
List<UserInfo> selectUserInfoByName2(String username);


传递字符串时,使用#{}正常得到了结果,而使用${}出现了Badsql异常(sql语句错误),观察sql语句发现:admin没有正确加上引号.事先添加引号,观察运行结果:
@Select("select * from userinfo where username = '${username}'")
List<UserInfo> selectUserInfoByName2(String username);

在手动添加引号之后,运行结果正确.
#{}和${}的区别
从简单的角度讲#{}和${}的区别就是预编译sql和即时sql的区别.
首先,预编译sql的性能更好.因为一条sql语句要经过sql语法解析,sql优化,sql编译之后才会执行.预编译SQL,编译⼀次之后会将编译后的SQL语句缓存起来,后⾯再次执⾏这条语句时,不会再次编译
(只是输⼊的参数不同),省去了解析优化等过程,以此来提⾼效率.
预编译sql可以防止sql注入,在使用${}时,可能会发生sql注入问题.在上面的根据名称查询中,如果用户输入了' or 1 = '1,那么整条sql语句就会变为select * from userinfo where username ='' or 1 ='1',由于1=1永远为true,那么此次查询将会把表中的所有信息都查出来.
@Test
void selectUserInfoByName2() {
System.out.println(userInfoMapper.selectUserInfoByName2("' or 1 = '1"));
}

${}的"立足之本"
上面提到${}的性能不如#{},甚至还会出现sql注入问题,那么为什么MyBatis没有删除${}呢?
因为${}是直接将字符串拼接在sql语句上,不会主动添加引号,那么在一下不能主动添加引号的情况下,就只能使用${}不能使用#{}.
排序是在浏览网页时非常常见的功能,排序sql语句最后需要指定升序或降序(select * from userinfo order by id asc/desc),在这里就不能对升序或降序添加引号,就只能使用${}.
@Select("select * from userinfo order by id ${sort}")
List<UserInfo> selectUserInfoBySort(String sort);
@Test
void selectUserInfoBySort() {
System.out.println(userInfoMapper.selectUserInfoBySort("desc"));
}

如果使用#{},就会因为自动拼接引号而导致badsql异常.
在使用${}时,为了避免sql注入需要对内容进行严格的校验.
数据库连接池
数据库连接池负责分配,管理和释放数据库连接,它允许应⽤程序重复使⽤⼀个现有的数据库连接,⽽不是再重新建⽴⼀个.
没有使⽤数据库连接池的情况:每次执⾏SQL语句,要先创建⼀个新的连接对象,然后执⾏SQL语句,SQL语句执⾏完,再关闭连接对象释放资源.这种重复的创建连接,销毁连接⽐较消耗资源
使⽤数据库连接池的情况:程序启动时,会在数据库连接池中创建⼀定数量的Connection对象,当客户请求数据库连接池,会从数据库连接池中获取Connection对象,然后执⾏SQL,SQL语句执⾏完,再把Connection归还给连接池.
这样就能减少网络开销,提升资源复用率,提升系统的性能.
⽬前⽐较流⾏的数据库连接池是Hikari,Druid.Spring Boot默认使用Hikari.


被折叠的 条评论
为什么被折叠?



