上一节主要写了MyBatis入门案例以及Mapper代理,这节主要结合前面的知识实现MyBatis的增删改查,涉及动态sql的使用!
查询所有在入门案例里已经举例过了,这里不再写案例!
首先补充mybatis-config.xml核心配置文件:
可以添加类型别名,然后对应的sql映射文件里resultType就可以直接简写返回值类型了,而且不区分大小写!
下面进入案例:
public static void main(String[] args) throws IOException {
//1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 执行sql (只有这块需要手写,其他步骤直接复制)
MemberMapper memberMapper = sqlSession.getMapper(MemberMapper.class);
int id = 2;
Member member = memberMapper.selectById(id);
System.out.println(member);
//4. 释放资源
sqlSession.close();
}
mybatis提供了两种参数占位符:
接下来来看另为的问题:
这里sql语句>是没有问题的,但小于号<是xml标签的开始符号,会报错!
有两种解决方式:
方式一:使用<的转义字符:
<select id="selectById" resultType="member">
select * from member where id < #{id}
select>
方式二:使用CDATA区:
<select id="selectById" resultType="member">
select * from member where id
#{id}
select>
CDATA区里的字符会当做纯文本处理!
sql映射文件:MemberMapper.xml
而该功能有2个参数,我们就需要考虑定义接口时,参数应该如何定义。Mybatis针对多参数有多种实现:
1.使用 @Param(“参数名称”) 标记每一个参数,在映射配置文件中就需要使用 #{参数名称} 进行占位!
int age = 28;
String name = "张";
// 模糊匹配,参数处理
name = '%' + name + '%';
List<Member> members = memberMapper.selectByCondition(age,name);
System.out.println(members);
2.将多个参数封装成一个 实体对象 ,将该实体对象作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时,里面的内容必须和实体类属性名保持一致。
int age = 28;
String name = "张";
// 模糊匹配,参数处理
name = '%' + name + '%';
// 封装对象
Member member = new Member();
member.setAge(age);
member.setName(name);
List<Member> members = memberMapper.selectByCondition(member);
System.out.println(members);
3.将多个参数封装到map集合中,将map集合作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容}时,里面的内容必须和map集合中键的名称一致。
int age = 28;
String name = "张";
// 模糊匹配,参数处理
name = '%' + name + '%';
// 封装map对象
HashMap map = new HashMap();
map.put("age",age);
map.put("name",name);
List<Member> members = memberMapper.selectByCondition(map);
System.out.println(members);
上述功能实现存在很大的问题,假如我们在做开发遇到用户在输入条件时,这个需求肯定不会所有的条件都填写,一种是对于不同填写情况判断,用不同的sql,但这样比较麻烦,写的sql也多,所以MyBatis提供了动态sql,可以帮助我们一条语句就搞定这种搜索查询情况!
<select id="selectByCondition" resultType="member">
select *
from member
where age = #{age}
and name like #{name};
select>
上面的意思就是说,这样的sql查询必须是两个或者多个参数都有才能查出来,而我们的需求是两个甚至多个条件任选都满足查询,这就是动态sql,只需一条sql就搞定,那下面就来看看怎么搞!
<select id="selectByCondition" resultType="member">
select *
from member
where
<if test="age != null">
age = #{age}
if>
<if test="name != null and name != ''">
and name like #{name}
if>
select>
用动态sql的if标签即可满足!if标签可以判断参数是否有值,使用test属性判断!
可以看到此时只有一个条件,依然满足!
但是如果是第一个条件没有,此时就会出问题:
报错也很明显,多了一个and,对于这种情况有两种解决方式!
方式一:不常用
```xml
<select id="selectByCondition" resultType="member">
select *
from member
where 1=1
<if test="age != null">
and age = #{age}
if>
<if test="name != null and name != ''">
and name like #{name}
if>
select>
加一个1=1恒等式不就行了,但我们sql可不这么写,所以用第二个方法!
方法二:使用where 标签
<select id="selectByCondition" resultType="member">
select *
from member
<where>
<if test="age != null">
age = #{age}
if>
<if test="name != null and name != ''">
and name like #{name}
if>
where>
select>
还有一个情况就是我们的条件只有一个,但我们不知道是哪一个条件!
这就需要使用到 choose(when,otherwise)标签 实现, 而 choose 标签类似于Java 中的switch语句。
<select id="selectByCondition" resultType="member">
select *
from member
where
<choose>
<when test="age != null">
age = #{age}
when>
<when test="name != null and name != ''">
and name like #{name}
when>
choose>
select>
但这样有个问题是当单个条件都没有时会多出一个where,此时跟上面一样,有两种解决方案!
方案一:借助otherwise多写一个恒等式
<select id="selectByCondition" resultType="member">
select *
from member
where
<choose>
<when test="age != null">
age = #{age}
when>
<when test="name != null and name != ''">
and name like #{name}
when>
<otherwise>
1 = 1
otherwise>
choose>
select>
方案二 :用where标签
<select id="selectByCondition" resultType="member">
select *
from member
<where>
<choose>
<when test="age != null">
age = #{age}
when>
<when test="name != null and name != ''">
and name like #{name}
when>
choose>
where>
select>
sql映射文件:
<insert id="add">
insert into member (name,gender,age)
values (#{name},#{gender},#{age});
insert>
mapper接口
void add(Member member);
主要代码:
package com.aniu;
import com.aniu.mapper.MemberMapper;
import com.aniu.pojo.Member;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/**
* @Author:Aniu
* @Date:2023/4/13 22:07
* @description 增加
*/
public class MyBatisDemo4 {
public static void main(String[] args) throws IOException {
//1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
// SqlSession sqlSession = sqlSessionFactory.openSession(true); // 开启自动提交
//3. 执行sql (只有这块需要手写,其他步骤直接复制)
MemberMapper memberMapper = sqlSession.getMapper(MemberMapper.class);
String name = "阿牛";
String gender = "男";
int age = 21;
Member member = new Member();
member.setGender(gender);
member.setName(name);
member.setAge(age);
memberMapper.add(member);
//手动提交事务
sqlSession.commit();
//4. 释放资源
sqlSession.close();
}
}
在数据添加成功后,有时候需要获取插入数据库数据的主键(主键是自增长)。
此时直接从pojo类中获取不到,sql映射文件里的insert语句要添加两个属性:
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into member (name,gender,age)
values (#{name},#{gender},#{age});
insert>
有修改部分字段,有全部修改,这里依旧使用动态sql来实现全部需求
sql映射文件:
<update id="update">
update member
<set>
<if test="name != null and name != ''">
name = #{name},
</if>
<if test="gender != null and gender != ''">
gender = #{gender},
</if>
<if test="age != null">
age = #{age}
</if>
</set>
where id = #{id};
</update>
依然有逗号问题,所以用set标签处理
mapper接口:
int update(Member member);
主要实现:
public class MyBatisDemo4 {
public static void main(String[] args) throws IOException {
//1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
// SqlSession sqlSession = sqlSessionFactory.openSession(true); // 开启自动提交
//3. 执行sql (只有这块需要手写,其他步骤直接复制)
MemberMapper memberMapper = sqlSession.getMapper(MemberMapper.class);
String name = "aniu";
int id = 5;
Member member = new Member();
member.setName(name);
member.setId(id);
int count = memberMapper.update(member);
System.out.println(count);
//手动提交事务
sqlSession.commit();
//4. 释放资源
sqlSession.close();
}
}
根据id删除:
void deleteById(int id);
<delete id="deleteById">
delete from member where id = #{id};
delete>
批量删除:
/**
* 批量删除
*/
void deleteByIds(int[] ids);
编写SQL语句:
在 MemberMapper.xml 映射配置文件中编写删除多条数据的 statement 。
编写SQL时需要遍历数组来拼接SQL语句。Mybatis 提供了 foreach 标签供我们使用:
<delete id="deleteByIds">
delete from member where id
in
<foreach collection="array" item="id" separator="," open="(" close=")">
#{id}
foreach>
;
delete>
使用@Param注解改变map集合的默认key的名称后:
void deleteByIds(@Param("ids") int[] ids);
主要测试代码:
package com.aniu;
import com.aniu.mapper.MemberMapper;
import com.aniu.pojo.Member;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/**
* @Author:Aniu
* @Date:2023/4/14 19:36
* @description 批量删除
*/
public class MyBatisDemo5 {
public static void main(String[] args) throws IOException {
//1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
// SqlSession sqlSession = sqlSessionFactory.openSession(true); // 开启自动提交
//3. 执行sql (只有这块需要手写,其他步骤直接复制)
MemberMapper memberMapper = sqlSession.getMapper(MemberMapper.class);
int[] ids = {1,2,3};
memberMapper.deleteByIds(ids);
//手动提交事务
sqlSession.commit();
//4. 释放资源
sqlSession.close();
}
}
使用注解开发会比配置文件开发更加方便。如下就是使用注解进行开发:
@Select(value = "select * from member where id = #{id}")
public Member select(int id);
注意:
Mybatis 针对 CURD 操作都提供了对应的注解,已经做到见名知意。如下:
注意:在官方文档中 入门 中有这样的一段话:
所以,注解完成简单功能,配置文件完成复杂功能。这里对注解的使用不再举例!
如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。
系列专栏
flask框架入门到实战
软磨 css
硬泡 javascript