目录
1. 数据库字段和 Java 对象不一致
2. 多表查询
3. 动态 SQL 使用
4. 标签
5. 标签
6. 标签
7. 标签
8. 标签
9. 通过注解实现
9.1 查找所有数据
9.2 通过 id 查找
我们先来看一下数据库中的数据:
接下来,我们在之前代码的基础上修改字段的名称:
/**
* 数据库字段和 Java 对象不完全一致
*/
@Data
public class User {
private Integer id;
private String name;
private String pwd;
private String photo;
private Date createtime;
private Date updatetime;
}
@Slf4j
@SpringBootTest
class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
void queryAll() {
List users = userMapper.queryAll();
log.info(users.toString());
}
@BeforeEach
void setUp() {
log.info("before...");
}
@AfterEach
void tearDown() {
log.info("after...");
}
}
可以看到能够获取数据,但是对应字段的值为 null 了:
因为数据库的字段命名规则和 Java 的命名规则不一致,数据库命名:字母小写,以下划线分割;Java 属性命名:小驼峰,第一个英文单词首字母小写,其他英文单词首字母大写。
一个 xml 文件中,可以存在多个 resultMap,只需要 id 不同即可:
List queryAllMap();
@Test
void queryAllMap() {
List users = userMapper.queryAllMap();
log.info(users.toString());
}
此时,我们可以看到成功查询到数据:
那么具体的关系如下图标注所示:
我们再新建一张表:
-- 创建⽂章表
drop table if exists articleinfo;
create table articleinfo(
id int primary key auto_increment,
title varchar(100) not null,
content text not null,
createtime datetime default now(),
updatetime datetime default now(),
uid int not null,
rcount int not null default 1,
`state` int default 1
)default charset 'utf8mb4';
如下图所示:
添加文章的数据:
-- ⽂章添加测试数据
insert into articleinfo(title,content,uid)
values('Java','Java正⽂',1);
文章添加数据后,如下图所示:
首先是 SQL 语句的多表查询:
select * from articleinfo ta
left join userinfo tb on ta.uid = tb.id;
接下来通过 Mybatis 实现:
首先新建 ArticleInfo 类:
@Data
public class ArticleInfo {
private Integer id;
private String title;
private String content;
private Date createtime;
private Date updatetime;
private Integer rcount;
private User user;
}
新建 ArticleMapper.xml 文件:
添加测试类:
@Slf4j
@SpringBootTest
class ArticleMapperTest {
@Autowired
private ArticleMapper articleMapper;
@Test
void queryArticle() {
List articleInfos = articleMapper.queryArticle();
log.info(articleInfos.toString());
}
}
运行结果如下图所示:
我们可以看到上述方式的结果显示的不够完整且需要输入的 SQL 语句过多。
接下来,我们通过另一种方式来实现:
List queryArticle2();
在 ArticleMapper.xml 文件中添加以下配置:
添加测试类:
@Test
void queryArticle2() {
List articleInfos = articleMapper.queryArticle2();
log.info(articleInfos.toString());
}
查询数据如下图所示:
需要注意,在实际的开发中,要尽量避免使用 *,无论数据库中有多少字段都需要一一罗列出来。
如下所示:
在实际的应用中,并不是每个信息都是必填的,也就是动态 SQL根据输入参数的不同动态的拼接 SQL。
我们先来看一下表中现有的数据:
接下来,我们插入数据:
void insert(ArticleInfo articleInfo);
insert into articleinfo(title,content,uid,state)values (#{title},#{content},#{userId},#{state})
@Test
void insert() {
ArticleInfo articleInfo = new ArticleInfo();
articleInfo.setTitle("测试文章");
articleInfo.setContent("测试文章内容");
articleInfo.setUserId(1);
articleInfo.setState(null);
articleMapper.insert(articleInfo);
}
可以看到,上面我们是自行将 state 的值设置为了 null,那么如果我们没有给这个字段赋值呢?
修改 XML 文件:
insert into articleinfo(title,content,uid)values (#{title},#{content},#{userId})
可以看到当我们没有对 state 赋值时,进行了自动默认赋值为1:
那么,这显然是不符合我们的预期的,我们想要实现的是当用户没有输入数据时,应该为默认值;输入数据时,显示为输入的数据。此时就需要用到标签了。
我们的目标是根据用户输入的情况,动态拼接 SQL。
void insertByCondition(ArticleInfo articleInfo);
insert into articleinfo(title,content,uid
,state
)
values
(#{title},#{content},#{userId}
,#{state}
)
@Test
void insertByCondition() {
ArticleInfo articleInfo = new ArticleInfo();
articleInfo.setTitle("测试文章2");
articleInfo.setContent("测试文章内容2");
articleInfo.setUserId(1);
articleMapper.insert(articleInfo);
}
接下来我们设置 state 为0:
@Test
void insertByCondition() {
ArticleInfo articleInfo = new ArticleInfo();
articleInfo.setTitle("测试文章3");
articleInfo.setContent("测试文章内容3");
articleInfo.setUserId(1);
articleInfo.setState(0);
articleMapper.insert(articleInfo);
}
当我们需要对多个字段应用 if 标签时,会存在报错:
如果统一把逗号放在字段前面,当第一个字段为 null 时,整个 SQL 的最前面就会多一个逗号;如果统一把逗号放在字段后面,当最后一个字段为 null 时,整个 SQL 的最后面会多一个逗号。
上面的插入数据功能,如果所有字段都是非必填项,就考虑使用标签结合标签,对多个字段都采取动态生成的方式。 标签中有如下属性:
使用
insert into articleinfo
title,
content,
uid,
state
values
#{title},
#{content},
#{content},
#{state},
可以看到此时能够正确执行:
当我们需要使用 where 语句进行条件筛选时:
List queryBycondition(@Param("uid") Integer uid,@Param("state")Integer state);
@Test
void queryBycondition() {
List articleInfos = articleMapper.queryBycondition(1,1);
log.info(articleInfos.toString());
}
可以看到成功执行:
此时我们修改代码如下:
@Test
void queryBycondition() {
List articleInfos = articleMapper.queryBycondition(1,null);
log.info(articleInfos.toString());
}
依然可以成功执行:
当我们修改代码如下时:
@Test
void queryBycondition() {
List articleInfos = articleMapper.queryBycondition(null,1);
log.info(articleInfos.toString());
}
产生报错信息:
添加语句 1 = 1,继续修改代码如下:
此时可以看到成功执行:
接下来,我们使用 where 标签实现以上功能。
在 XML 文件中,添加以下语句:
可以已经生成了 where 并且去掉了 and :
当两个字段均为 null 时,可以看到直接去掉了 where:
@Test
void queryBycondition() {
List articleInfos = articleMapper.queryBycondition(null,null);
log.info(articleInfos.toString());
}
综上,我们可以知道 where 标签具有以下作用:
void updateByCondition(@Param("uid") Integer uid,@Param("state")Integer state);
update articleinfo
set
uid = #{uid},
state = #{state},
@Test
void updateByCondition() {
articleMapper.updateByCondition(1,null);
}
运行后,产生以下报错:
接下来,我们使用 set 标签:
update articleinfo
uid = #{uid},
state = #{state},
运行成功:
综上,我们可以看到 set 标签的作用:
对集合进行遍历时可以使用该标签。标签有如下属性:
因此,我们来通过 foreach 标签实现以下目标:
接下来我们通过代码实现:
void batchDelete(List ids);
delete from articleinfo where id in
#{id}
@Test
void batchDelete() {
List ids = Arrays.asList(2,3,4,5,6,10,11);
articleMapper.batchDelete(ids);
}
可以看到成功运行:
表中相应的数据也删除了:
注意:
还需要注意的是 collection 也可以是参数的名称:
Mybatis 的实现有两种方式:
接下来,我们来看一下如何通过注解来实现:
@Mapper
public interface UserMapper2 {
@Select("select * from userinfo")
List queryAll();
}
@Slf4j
@SpringBootTest
class UserMapper2Test {
@Autowired
private UserMapper2 userMapper2;
@Test
void queryAll() {
List userList = userMapper2.queryAll();
log.info(userList.toString());
}
}
运行结果如下:
@Mapper
public interface UserMapper2 {
@Select("select * from userinfo where id = #{uid}")
User queryById(Integer aaa);
}
@Slf4j
@SpringBootTest
class UserMapper2Test {
@Autowired
private UserMapper2 userMapper2;
@Test
void queryById() {
User user = userMapper2.queryById(1);
log.info(user.toString());
}
}
可以看到运行结果如下:
一个项目中,注解和 XML 的方式可以并存,对于简单的 SQL 使用注更加方便,但是对于动态 SQL 注解写起来非常麻烦。