目录
一、定义接口、实体类、创建XML文件实现接口)
二、MyBatis的增删改查
🍅1、MyBatis传递参数查询
🎈写法一
🎈写法二
🎈两种方式的区别
🍅2、删除操作
🍅3、根据id修改用户名
🍅4、添加用户操作
🎈返回受影响的行数
🎈返回自增id
🍅5、like查询
🍅6、多表查询
三、动态SQL
🍅 <if>标签
🍅 <trim>标签
🍅 <where>标签
🍅 <set>标签
🍅 <foreach>标签
四、注意
🍅1、mybatisx插件报错
🍅2、数据回滚
🍅 3、查询某字段结果为null时
一、定义接口、实体类、创建XML文件实现接口)
注意包名:
实体类
package com.example.demo.model;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class UserInfo {
private int id;
private String username;
private String password;
private String photo;
private LocalDateTime updatatime;
private LocalDateTime createtime;
private int state;
}
接口
package com.example.demo.dao;
import com.example.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper //数据持久层的标志
public interface UserMapper {
List<UserInfo> getAll();
}
XML文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.dao.UserMapper">
<!-- id是UserMapper的方法名-->
<select id="getAll" resultType="com.example.demo.model.UserInfo">
-- 不写分号
select * from userinfo
</select>
</mapper>
二、MyBatis的增删改查
🍅1、MyBatis传递参数查询
🎈写法一
@Param("id")与${id}相互匹配 (及时执行)
使用id去查询某条数据(传参数)
UserInfo getUserById(@Param("id") Integer uid);
-- 这里应该写${id},而不是uid
<select id="getUserById" resultType="com.example.demo.model.UserInfo">
select * from userinfo where id=${id}
</select>
测试类:
@Test
void getUserById() {
UserInfo userInfo = userMapper.getUserById(1);
System.out.println(userInfo.toString());
}
🎈写法二
@Param("id")与#{id}相互匹配 (预执行)
<select id="getUserById" resultType="com.example.demo.model.UserInfo">
select * from userinfo where id=#{id}
</select>
🎈两种方式的区别
1.${}是直接替换;而#{}是预执行
2.使用${}是不安全的,存在SQL注入;而#{}是安全的,不存在SQL注入
3.${}使用场景:当业务需要传递SQL语句时,只能使用${},不能使用#{}。
SQL注入:将SQL代码插入或添加到应用(用户)的输入参数中的攻击,之后再将这些参数传递给后台的sql服务器加以解析和执行。
🍅2、删除操作
UserInfo getUserById(@Param("id") Integer uid);
<!-- delete操作不需要设置返回类型-->
<delete id="delById">
delete from userinfo where id=#{id}
</delete>
测试类
@Transactional //数据回滚:使用该注解,会执行下面操作,但是不会真的操作数据库中的内容
@Test
void testGetUserById() {
int id = 1;
UserInfo result = userMapper.getUserById(id);
System.out.println("受影响的行数:"+result);
}
🍅3、根据id修改用户名
// 根据id修改用户名
// 返回受影响行数
int update(UserInfo userInfo);
<!-- 默认返回受影响的行数,不需要设置resultType-->
<update id="update" >
update userinfo set username=#{username} where id=#{id}
</update>
@Transactional
@Test
void update() {
UserInfo userInfo = new UserInfo();
userInfo.setId(1);
userInfo.setUsername("管理员");
int result = userMapper.update(userInfo);
System.out.println("受影响行数"+ result);
}
运行结果:
🍅4、添加用户操作
🎈返回受影响的行数
//返回受影响字段
int add(UserInfo userInfo);
<insert id="add">
insert into userinfo(username,password,photo)
values (#{username},#{password},#{photo})
</insert>
//测试类
@Test
void add() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("张三");
userInfo.setPassword("11111");
userInfo.setPhoto("/image/default.png");
int result = userMapper.add(userInfo);
System.out.println("受影响的行数:"+ result);
}
运行结果:
🎈返回自增id
int insert(UserInfo userInfo);
<insert id="insert" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into userinfo(username,password,photo) values (#{username},#{password},#{photo})
</insert>
//测试类
@Test
void insert() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("李四");
userInfo.setPassword("111111");
userInfo.setPhoto("");
int result = userMapper.insert(userInfo);
System.out.println("受影响的行数:" + result +
"| id:"+ userInfo.getId());
}
运行结果:
对应关系:
🍅5、like查询
List<UserInfo> getListByLike(@Param("username")String username);
<select id="getListByLike" resultType="com.example.demo.model.UserInfo">
select * from userinfo where username like concat('%',#{username},'%')
</select>
@Test
void getListByLike() {
String username = "三";
List<UserInfo> list = userMapper.getListByLike(username);
System.out.println(list);
}
运行结果:
🍅6、多表查询
使用注解将sql语句和接口连接起来。
之前是,写一个接口就要写一个对应的xml文件编写sql语句。现在可以不使用这种方法
可以直接在接口中通过注解编写查询语句:
@Mapper
public interface ArticleMapper{
@Select("select a.*,u.username from articleinfo a" +
"left join userinfo u on a.uid=u.id")
List<Articleinfo> getAll();
}
测试类:
class ArticleMapperTest {
@Autowired
private ArticleMapper articleMapper;
@Test
void getAll() {
List<Articleinfo> list = articleMapper.getAll();
System.out.println(list);
}
}
三、动态SQL
动态SQL时MyBatis的强大特性之一,可以完成不同条件下的sql拼接,就是在XML文件中动态的去写判断条件。以下是一些动态标签:
🍅 <if>标签
语法:
<if test="photo!=null">
........
</if>
//代码示例
int add2(UserInfo userinfo);
<insert id="add2">
insert into userinfo(username,password
<if test="photo!=null">
,photo
</if>
)values (#{username},#{password}
<if test="photo!=null">
,#{photo}
</if>
)
</insert>
🍅 <trim>标签
<trim>标签中有如下属性:
* prefix:表示整个语句块,以prefix的值作为前缀
* suffix:表示整个语句块,以suffix的值作为后缀
* prefixOverrides:表示整个语句块要去除掉的前缀
* suffixOverrides:表示整个语句块要去除掉的后缀
int add3(UserInfo userInfo);
<insert id="add3">
insert into userinfo
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username!=null">
username,
</if>
<if test="password!=null">
password,
</if>
<if test="photo!=null">
photo
</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username!=null">
#{username},
</if>
<if test="password!=null">
#{password},
</if>
<if test="photo!=null">
#{photo}
</if>
</trim>
</insert>
🍅 <where>标签
<where>标签:
* 根据有<where>标签中的内容决定是否生成“where”关键字
* 去除最前面的“and”关键字,不能去掉后面的
<!-- 直接写select * from userinto where会报错,但是使用where标签就不会报错-->
<select id="getListByWhere" resultType="com.example.demo.model.UserInfo">
select * from userinfo
<where>
<if test="id!=0">
id=#{id}
</if>
<if test="username!=null">
and username=#{username}
</if>
<if test="password!=null">
and password=#{password}
</if>
</where>
</select>
使用<trim>标签也可以生成where
<select id="getListByWhere" resultType="com.example.demo.model.UserInfo">
select * from userinfo
<trim prefix="where" prefixOverrides="and">
<if test="id!=0">
id=#{id}
</if>
<if test="username!=null">
and username=#{username}
</if>
<if test="password!=null">
and password=#{password}
</if>
</trim>
</select>
🍅 <set>标签
和where标签使用一样
<update id="update2">
update userinfo
<set>
<if test="username!=null">
username=#{username},
</if>
<if test="password!=null">
password=#{password},
</if>
<if test="photo!=null">
photo=#{photo},
</if>
</set>
where id=#{id}
</update>
🍅 <foreach>标签
MyBatis提供了
<foreach>
标签来处理动态SQL中的循环操作。这个标签允许你在SQL语句中迭代一个集合,并生成重复的SQL片段。<foreach>标签属性:
* collection:绑定方法参数中的集合,如List,Set,Map或数组对象
* item:遍历时的每一个对象
* open:语句块开头的字符串
* close:语句块结束的字符传
* separator:每次遍历之间间隔的字符串
以下例子可以看成是:
delete from userinfo where id in(?,?,?,?)
<delete id="delByIds">
delete from userinfo
where id in
<foreach collection="ids" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</delete>
//测试类
@Test
void delByIds() {
List<Integer> list = new ArrayList<Integer>(){{
add(8);
add(9);
add(10);
add(11);
}};
int result = userMapper.delByIds(list);
System.out.println("result" + result);
}
四、注意
🍅1、mybatisx插件报错
以上并非系统报错,而是插件在报错,告诉我们没有设置返回的技术类型,高版本的idea遇到这种情况运行是不会报错的。
🍅2、数据回滚
@Transactional //数据回滚:使用该注解,会执行下面操作,但是不会真的操作数据库中的内容
🍅 3、查询某字段结果为null时
原因是:实体类中的属性和数据库表中的字段名不一致。
解决方案:
1.将实体类中的属性和表中的字段名保持一致(最简单的解决方案)
2.使用sql语句中的as进行列名(字段名)重命名,让列名(字段名)等于属性名
<!-- 加入要查询的字段名应该是name,对name进行重命名 --> <selet id="getUserById" resultType="com.example.demo.model.UserInfo"> select username as name from userinfo where id=#{id}c </select>
3.定义一个resultMap,将属性名和字段名进行手动映射
resultMap放入mapper.xml的<mapper></mapper>中
<resultMap id="UserMapper" type="com.example.demo.model.UserInfo"> <id column="id" property="id"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> </resultMap> <select id="getUserById" resultMap="BaseMap"> select * from userinfo where id=#{id} </select>
以下是对应关系:尽量把全部属性映射上,否则多表查询时可能会报错。
上图有个错误!!! colum是表里面的字段名,property是实体类里的属性,写反了。