JavaWeb学习笔记(三)利用Mybatis实现CRUD操作

0 准备环境

0.1 创建数据库表tb_brand

drop table if exists tb_brand;
creat table tb_brand
(
	-- id 主键
	id			 int primary key auto_increment,
	-- 品牌名称
	brand_name   varchar(20),
	-- 企业名称
	company_name varchar(20),
	-- 排序字段
	ordered 	 int,
	-- 描述信息
	description  varchar(100),
	-- 状态:0:禁用 1:启用
	state 		 int
);

0.2 创建实体类Brand类

public class Brand {
		// id 主键
		private Integer id;
		// 品牌名称
		private String brandName;
		// 企业名称
		private String companyName;
		// 排序字段
		private Integer ordered;
		// 描述信息
		private String description;
		// 状态:0:禁用 1:启用
		private Integer status;
		//省略 setter and getter。自己写时要补全这部分代码
}

1 查询所有数据

1.1 编写接口方法(Mapper接口)

在BrandMapper接口中定义方法:

List<Brand> selectALL();

1.2 编写SQL语句(SQL映射文件)

在resources下创建BrandMapper.xml映射配置文件

<mapper namespace="com.example.mapper.BrandMapper">
		<select id="selectAll" resultType="brand">
				select *
				from tb_brand;
		</select>
</mapper>

这里resltType参数为brand,需在mybatis-config.xml文件中设置别名(见上一章)

1.3 起别名解决表中字段和类属性名不一致

表中的字段名brand_name和类中的属性名brandName不一致,导致查询失败,可以在编写查询语句时为字段起别名

<select id="selectAll" resultType="brand">
		select
		id, brand_name as brandName, company_name as companyName, ordered, description, status
		from tb_brand;
</select>
  • SQL片段

Step1:将需要复用的SQL片段抽取到 sql 标签

<sql id="brand_column">
   	id, brand_name as brandName, company_name as companyName, ordered, description, status
</sql>

Step2:在原SQL语句中进行引用

<select id="selectAll" resultType="brand">
		select
		<include refid="brand_column" />
		from tb_brand;
</select>

1.4 使用resultMap解决问题

在SQL映射配置文件中使用resultMap定义字段属性的映射关系:

<resultMap id="brandResultMap" type="brand">
		<!--
				id:完成主键字段的映射
				column:表的列名
				property:实体类的属性名
				result:完成一般字段的映射
				column:表的列名
				property:实体类的属性名
			-->
		<result column="brand_name" property="brandName"/>
		<result column="company_name" property="companyName"/>
</resultMap>

SQL语句正常编写,resultType参数改为resultMap参数(上面定义的resultMap的id):

<select id="selectAll" resultMap="brandResultMap">
		select *
		from tb_brand;
</select>

2 单条件查询

2.1 编写接口方法(Mapper接口)

在BrandMapper接口中定义方法:

Brand selectById(int id);

2.2 编写SQL语句(SQL映射文件)

在 BrandMapper.xml 映射配置文件中编写 statement ,使用 resultMap 而不是使用 resultType

<select id="selectById" resultMap="brandResultMap">
		select *
		from tb_brand where id = #{id};
</select>

2.3 参数占位符

mybatis提供了两种参数占位符:

  • #{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。从上述例子可以看出使用#{} 底层使用的是PreparedStatement
  • ${} :拼接SQL。底层使用的是 Statement ,会存在SQL注入问题。

2.4 SQL语句中特殊字段处理

因为映射配置文件是xml类型的问题,而 > < 等这些字符在xml中有特殊含义,所以此时我们需要将这些符号进行转义,可以使用以下两种方式进行转义:
1、转义字符

<select id="selectById" resultMap="brandResultMap">
	    select *
	    from tb_brand
	    where id &lt; #{id}; // &lt; 即相当于 <
</select>

2、

<select id="selectById" resultMap="brandResultMap">
	    select *
	    from tb_brand
	    where id
	    <![CDATA[
	    	=
	    ]]>
	    #{id};
</select>

3 多条件查询

3.1 编写接口方法(Mapper接口)

Mybatis针对多参数有多种实现

  • 使用 @Param("参数名称") 标记每一个参数,在映射配置文件中就需要使用 #{参数名称} 进行占位
List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
  • 将多个参数封装成一个 实体对象 ,将该实体对象作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时,里面的内容必须和实体类属性名保持一致
List<Brand> selectByCondition(Brand brand);
  • 将多个参数封装到map集合中,将map集合作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容}时,里面的内容必须和map集合中的名称一致
List<Brand> selectByCondition(Map map);

3.2 编写SQL语句(SQL映射文件)

<select id="selectByCondition" resultMap="brandResultMap">
		select *
		from tb_brand
		where status = #{status}
		and company_name like #{companyName}
		and brand_name like #{brandName}
</select>

3.3 动态SQL

上述功能实现存在很大的问题。用户在输入条件时,肯定不会所有的条件都填写,而Mybatis对动态SQL有很强大的支撑:

  • 使用if标签和where标签
<select id="selectByCondition" resultMap="brandResultMap">
		select *
		from tb_brand
		<where>
				<if test="status != null">
						and status = #{status}
				</if>
				<if test="companyName != null and companyName != '' ">
						and company_name like #{companyName}
				</if>
				<if test="brandName != null and brandName != '' ">
						and brand_name like #{brandName}
				</if>
		</where>
</select>

注意:需要给每个条件前都加上 and 关键字。

4 单条件查询(动态SQL)

在查询时只能选择 品牌名称 、 当前状态 、 企业名称 这三个条件中的一个,但是用户到底选择哪儿一个,我们并不能确定。这种就属于单个条件的动态SQL语句。

4.1 编写接口方法(Mapper接口)

List<Brand> selectByConditionSingle(Brand brand);

4.2 编写SQL语句(SQL映射文件)

  • 使用choose标签和when标签(类似于switch语句)
<select id="selectByConditionSingle" resultMap="brandResultMap">
		select *
		from tb_brand
		<where>
				<choose><!--相当于switch-->
						<when test="status != null"><!--相当于case-->
								status = #{status}
						</when>
						<when test="companyName != null and companyName != '' "><!--相当于case-->
								company_name like #{companyName}
						</when>
						<when test="brandName != null and brandName != ''"><!--相当于case-->
								brand_name like #{brandName}
						</when>
				</choose>
		</where>
</select>

5 添加数据

参数:除了id之外的所有的数据。id对应的是表中主键值,而主键我们是自动增长生成的。

5.1 编写接口方法(Mapper接口)

void add(Brand brand);

5.2 编写SQL语句(SQL映射文件)

<insert id="add">
		insert into tb_brand (brand_name, company_name, ordered, description, status)
		values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>

添加完数据需要提交事务 sqlSession.commit();

5.3 添加-主键返回

在数据添加成功后,有时候需要获取插入数据库数据的主键(主键是自增长),也就是add(Brand brand)中的参数brand类的属性id会被自动赋值

<insert id="add" useGeneratedKeys="true" keyProperty="id">
		insert into tb_brand (brand_name, company_name, ordered, description, status)
		values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>

在 insert 标签上添加如下属性:

  • useGeneratedKeys:是够获取自动增长的主键值。true表示获取
  • keyProperty :指定将获取到的主键值封装到哪儿个属性里

这样的话,往数据库添加完数据后,brand实体类的id也被赋值了

//接收参数
int status = 1;
String companyName = "波导手机";
String brandName = "波导";
String description = "手机中的战斗机";
int ordered = 100;

//封装对象,这时候id属性是没有值得
Brand brand = new Brand();
brand.setStatus(status);
brand.setCompanyName(companyName);
brand.setBrandName(brandName);
brand.setDescription(description);
brand.setOrdered(ordered);

brandMapper.add(brand);
Integer id = brand.getId(); // 这时候id会被赋值
System.out.println(id);

6 修改数据

6.1 编写接口方法(Mapper接口)

void update(Brand brand);

6.2 编写SQL语句(SQL映射文件)

<update id="update">
    update tb_brand
    <set>
        <if test="brandName != null and brandName != ''">
            brand_name = #{brandName},
        </if>
        <if test="companyName != null and companyName != ''">
            company_name = #{companyName},
        </if>
        <if test="ordered != null">
            ordered = #{ordered},
        </if>
        <if test="description != null and description != ''">
            description = #{description},
        </if>
        <if test="status != null">
            status = #{status}
        </if>
    </set>
    where id = #{id};
</update>

set 标签可以用于动态包含需要更新的列,忽略其它不更新的列。

7 删除一行数据

7.1 编写接口方法(Mapper接口)

void deleteById(int id);

7.2 编写SQL语句(SQL映射文件)

<delete id="deleteById">
		delete from tb_brand where id = #{id};
</delete>

8 批量删除数据

8.1 编写接口方法(Mapper接口)

void deleteByIds(int[] ids);

参数是一个数组,数组中存储的是多条数据的id

8.2 编写SQL语句(SQL映射文件)

编写SQL时需要遍历数组来拼接SQL语句。Mybatis 提供了 foreach 标签供我们使用
foreach 标签:
用来迭代任何可迭代的对象(如数组,集合)。

  • collection 属性:

    • mybatis会将数组参数,封装为一个Map集合。
      默认:array = 数组
      使用@Param注解改变map集合的默认key的名称(见下)
  • item 属性:本次迭代获取到的元素。

  • separator 属性:集合项迭代之间的分隔符。 foreach 标签不会错误地添加多余的分隔符。也就是最后一次迭代不会加分隔符。

  • open 属性:该属性值是在拼接SQL语句之前拼接的语句,只会拼接一次

  • close 属性:该属性值是在拼接SQL语句拼接后拼接的语句,只会拼接一次

<delete id="deleteByIds">
		delete from tb_brand where id
		in
		<foreach collection="array" item="id" separator="," open="(" close=")">
				#{id}
		</foreach>
		;
</delete>

假如数组中的id数据是{1,2,3},那么拼接后的sql语句就是:

delete from tb_brand where id in (1,2,3);

9 Mybatis参数传递

Mybatis 接口方法中可以接收各种各样的参数,如下:

  • 多个参数
  • 单个参数:单个参数又可以是如下类型
    • POJO 类型
    • Map 集合类型
    • Collection 集合类型
    • List 集合类型
    • Array 类型
    • 其他类型

9.1 多个参数

我们在接口方法中定义多个参数,Mybatis 会将这些参数封装成 Map 集合对象,值就是参数值,而键在没有使用 @Param注解时有以下命名规则:

  • arg 开头 :第一个参数就叫 arg0,第二个参数就叫 arg1,以此类推。如:
map.put("arg0",参数值1);
map.put("arg1",参数值2);
  • param 开头 : 第一个参数就叫 param1,第二个参数就叫 param2,依次类推。如:
map.put("param1",参数值1);
map.put("param2",参数值2);

在映射配合文件的SQL语句中使用用 arg 开头的和 param 书写,代码的可读性会变的特别差,此时可以使用 @Param注解:

User select(@Param("username") String username, String password);

Mybatis 在封装 Map 集合时,键名就会覆盖arg0参数,变成如下:

map.put("username",参数值1);
map.put("arg1",参数值2);
map.put("param1",参数值1);
map.put("param2",参数值2);

结论:以后接口参数是多个时,在每个参数上都使用 @Param 注解。这样代码的可读性更高。

9.2 单个参数

  • POJO 类型

    直接使用。要求 属性名参数占位符名称 一致

  • Map 集合类型

    直接使用。要求 map集合的键名参数占位符名称 一致

  • Collection 集合类型

    Mybatis 会将集合封装到 map 集合中,如下:

    map.put(“arg0”,collection集合);
    map.put(“collection”,collection集合);

    可以使用 @Param 注解替换map集合中默认的 arg 键名。

  • List 集合类型

    Mybatis 会将集合封装到 map 集合中,如下:

    map.put(“arg0”,list集合);

    map.put(“collection”,list集合);

    map.put(“list”,list集合);

    可以使用 @Param 注解替换map集合中默认的 arg 键名。

  • Array 类型

    Mybatis 会将集合封装到 map 集合中,如下:

    map.put(“arg0”,数组);

    map.put(“array”,数组);

    可以使用 @Param 注解替换map集合中默认的 arg 键名。

  • 其他类型

    比如int类型,参数占位符名称 叫什么都可以。尽量做到见名知意

10 注解实现CRUD

使用注解开发会比配置文件开发更加方便。如下就是使用注解进行开发

@Select(value = "select * from tb_user where id = #{id}")
public User select(int id);

注意:

  • 注解是用来替换映射配置文件方式配置的,所以使用了注解,就不需要再映射配置文件中书写对应的 statement

Mybatis 针对 CRUD 操作都提供了对应的注解,已经做到见名知意。如下:

  • 查询 :@Select
  • 添加 :@Insert
  • 修改 :@Update
  • 删除 :@Delete

所以,注解完成简单功能,配置文件完成复杂功能(动态SQL)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值