青海省城乡和住房建设厅网站,动漫制作专业介绍及就业方向,山西网站开发建设,wordpress主题加密了文章目录1. 参数占位符 #{} 和 ${} 的区别2. ${} 的优点3. SQL 注入问题4. like 查询5. 返回字典映射#xff1a;resultMap6. 一对一查询#xff1a;association7. 一对多查询#xff1a;collection回顾一下#xff0c;在上一篇 MyBatis 之二#xff08;增、删、改操作resultMap6. 一对一查询association7. 一对多查询collection回顾一下在上一篇 MyBatis 之二增、删、改操作中学习了针对 MyBatis 的增、删、改操作三步走 在 mapperinterface里面添加增删改方法的声明在 XMl 中添加 增删改标签和对应的 sql 代码在 **Mapper 中右键 Generate 点击 Test 生成测试类 本篇将学习用 MyBatis 进行数据库的查询相关操作
1. 参数占位符 #{} 和 ${} 的区别
使用 #{} 得到 JDBC 的代码【针对 Integer 类型】 使用 ${} 得到 JDBC 的代码【针对 Integer 类型】 使用 #{} 得到 JDBC 的代码【针对 String 类型】 使用 ${} 得到 JDBC 的代码【针对 String 类型】出错了 #{} 和 ${} 区别 定义不同#{} 预处理而 ${} 是直接替换使用不同#{} 适用于所有类型的参数匹配但 ${} 只使用于数值类型安全性不同#{} 性能高并且没有安全性问题但 ${} 存在 SQL 注入的安全问题 代码如下
Mapper
public interface UserMapper {// 根据用户 id 查询用户public Userinfo getUserById(Param(id) Integer id);// 根据全面查询用户对象非模糊查询public Userinfo getUserByFullName(Param(username) String username);}?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
!-- namespace 是设置要实现的接口的具体包名 类名--
mapper namespacecom.example.mybatisdome1.mapper.UserMapper!-- 根据 id 查询用户 --select idgetUserById resultTypecom.example.mybatisdome1.model.Userinfoselect * from userinfo where id${id}/select!-- 根据全面查询用户对象非模糊查询) --select idgetUserByFullName resultTypecom.example.mybatisdome1.model.Userinfoselect * from userinfo where username${username}/select/mapperSpringBootTest
Slf4j
class UserMapperTest {Autowiredprivate UserMapper userMapper;Testvoid getUserById() {Userinfo userinfo userMapper.getUserById(1);log.info(用户信息 userinfo);}Testvoid getUserByFullName() {Userinfo userinfo userMapper.getUserByFullName(张三);log.info(用户信息 userinfo);}
}2. ${} 的优点
使用 ${} 可以实现排序查询
当传递的是一个 SQL 关键字 SQL 命令 例如 desc的时候只能使用 ${} 此时如果使用 #{} 就会认为传递的为一个普通的值会给这个值加上单引号这样就识别不出来 SQL 命令了所以执行就会报错
使用 ${} 注意因为使用 ${} 会存在 SQL 注入的问题所以当不得不使用 ${} 时那么一定要在业务代码中对传递的值进行安全校验当代码走到 Mapper 这一层时就必须要执行了所以一定要在业务代码中也就是 Controller 这一层对传递过来的 order 进行安全效验不但要判断是否为 null还要判断是不是 desc 或 asc如果都不是代码就不要往下执行 3. SQL 注入问题
当账号密码正确时可以查询到用户信息 如果是 SQL 注入时 4. like 查询
使用 #{} 报错但使用 ${} 在业务层的值又不能穷举 (如果使用 ${} 必须列出所有可能比如前面的 order 只有 desc 或 asc 两种可能所以可以使用 ${}但这里如果是 username 不可能列举所有可能所以不能使用 ${})
所以就可以使用 concat() 进行拼接 5. 返回字典映射resultMap
前面在xml 的 标签中写返回类型 resultType 时直接就是定义到某个实体类就行但这种情况只适用于字段名称和程序中属性名相同的情况下这种就是写起来方便
但如果是字段名称和属性名不同时继续使用 resultType 就会报错此时就要使用 resultMap 来配置映射
在一对一、一对多关系中可以使用 resultMap 映射并查询数 6. 一对一查询association
进行一对一查询需要使用 association 标签表示一对一的结果映射其中
property 属性指定其中所要一对一的那个属性resultMap 属性指定那个属性所关联的结果集映射columnPrefix 属性用来解决多表中相同字段数据覆盖的问题
一篇文章对应一个作者
1在 model 文件夹中创建 ArticleInfo 文章的实体类一对一查询注意加上属性 userInfo 作者
Data
public class ArticleInfo {private int id;private String title;private String content;private String createtime;private String updatetime;private int uid;private int rcount;private int state;private UserInfo userInfo;
}2在 Mapper 文件中创建 ArticleMapper 根据文章 id 获取文章
Mapper
public interface ArticleMapper {// 根据文章 id 获取文章public ArticleInfo getArticleById(Param(id) Integer id);}3在resources/mybatis 中写 ArticleMapper.xml 实现 2中的接口
?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
!-- namespace 是设置要实现的接口的具体包名 类名--
mapper namespacecom.example.mybatisdome1.mapper.ArticleMapperresultMap idBaseMap typecom.example.mybatisdome1.model.ArticleInfoid columnid propertyid/idresult columntitle propertytitle/resultresult columncontent propertycontent/resultresult columncreatetime propertycreatetime/resultresult columnupdatetime propertyupdatetime/resultresult columnuid propertyuid/resultresult columnrcount propertyrcount/resultresult columnstate propertystate/resultassociation propertyuserInforesultMapcom.example.mybatisdome1.mapper.UserMapper.BaseMapcolumnPrefixu_/association/resultMapselect idgetArticleById resultMapBaseMapselect a.*,u.id u_id,u.username u_username,u.password u_password from articleinfo a left join userinfo u on a.uid u.id where a.id #{id}/select
/mapper4生成测试类
SpringBootTest
Slf4j
class ArticleMapperTest {Resourceprivate ArticleMapper articleMapper;Testvoid getArticleById() {ArticleInfo articleInfo articleMapper.getArticleById(1);log.info(文章详情 articleInfo);}
}运行程序发现 userInfo 中属性没有查询到这是因为前面写的 UserMapper.xml 中 写的 resultMap 有问题要把所有属性都映射上
5修改 UserMapper.xml 中的 resultMap 6运行程序 7. 一对多查询collection
和一对一 标签类似一对多也需要标签 来表示一对多的结果映射
其中也是需要设置 property对象中的属性名、resultMap映射对象对应的字典、columnPrefix一般不要省略解决了多张表中相同字段查询数据覆盖的问题
一个用户多篇文章
1在实体类 UserInfo 中添加多篇文章的属性
Data
public class UserInfo {private Integer id;private String name;private String password;private String photo;private String createtime;private String updatetime;private int state;private ListArticleInfo artlist;
}2在 UserMapper 接口中写出查询用户及用户发表的所有文章的方法
Mapper
public interface UserMapper {// 查询用户及用户发表的所有文章public UserInfo getUserAndArticleByUid(Param(uid) Integer uid);}3在 UserMapper.xml 中实现接口中的方法
?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
!-- namespace 是设置要实现的接口的具体包名 类名--
mapper namespacecom.example.mybatisdome1.mapper.UserMapperresultMap idBaseMap typecom.example.mybatisdome1.model.UserInfo!-- 主键映射 --id columnid propertyid/id!-- 普通属性映射 --result columnusername propertyname/resultresult columnpassword propertypassword/resultresult columnphoto propertyphoto/resultresult columncreatetime propertycreatetime/resultresult columnupdatetime propertyupdatetime/resultresult columnstate propertystate/resultcollection propertyartlistresultMapcom.example.mybatisdome1.mapper.ArticleMapper.BaseMapcolumnPrefixa_/collection/resultMap!-- 查询用户及用户发表的所有文章 --select idgetUserAndArticleByUid resultMapBaseMapselect u.*,a.id a_id,a.title a_title,a.content a_content,a.createtime a_createtime,a.updatetime a_updatetimefrom userinfo u left join articleinfo a on u.id a.uid where u.id #{uid}/select/mapper4生成测试方法 运行程序