目录
一、定义接口、实体类、创建XML文件实现接口)
二、MyBatis的增删改查
1、MyBatis传递参数查询
写法一
写法二
两种方式的区别
2、删除操作
3、根据id修改用户名
4、添加用户操作
返回受影响的行数
返回自增id
5、like查询
6、多表查询
三、注意
1、mybatisx插件报错
2、数据回滚
3、查询某字段结果为null时
注意包名:
实体类
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 getAll();
}
XML文件
@Param("id")与${id}相互匹配 (及时执行)
使用id去查询某条数据(传参数)
UserInfo getUserById(@Param("id") Integer uid);
-- 这里应该写${id},而不是uid
测试类:
@Test
void getUserById() {
UserInfo userInfo = userMapper.getUserById(1);
System.out.println(userInfo.toString());
}
@Param("id")与#{id}相互匹配 (预执行)
1.${}是直接替换;而#{}是预执行
2.使用${}是不安全的,存在SQL注入;而#{}是安全的,不存在SQL注入
3.${}使用场景:当业务需要传递SQL语句时,只能使用${},不能使用#{}。
SQL注入:将SQL代码插入或添加到应用(用户)的输入参数中的攻击,之后再将这些参数传递给后台的sql服务器加以解析和执行。
UserInfo getUserById(@Param("id") Integer uid);
delete from userinfo where id=#{id}
测试类
@Transactional //数据回滚:使用该注解,会执行下面操作,但是不会真的操作数据库中的内容
@Test
void testGetUserById() {
int id = 1;
UserInfo result = userMapper.getUserById(id);
System.out.println("受影响的行数:"+result);
}
// 根据id修改用户名
// 返回受影响行数
int update(UserInfo userInfo);
update userinfo set username=#{username} where id=#{id}
@Transactional
@Test
void update() {
UserInfo userInfo = new UserInfo();
userInfo.setId(1);
userInfo.setUsername("管理员");
int result = userMapper.update(userInfo);
System.out.println("受影响行数"+ result);
}
运行结果:
//返回受影响字段
int add(UserInfo userInfo);
insert into userinfo(username,password,photo)
values (#{username},#{password},#{photo})
//测试类
@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);
}
int insert(UserInfo userInfo);
insert into userinfo(username,password,photo) values (#{username},#{password},#{photo})
//测试类
@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());
}
List getListByLike(@Param("username")String username);
@Test
void getListByLike() {
String username = "三";
List list = userMapper.getListByLike(username);
System.out.println(list);
}
运行结果:
使用注解将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 getAll();
}
测试类:
class ArticleMapperTest {
@Autowired
private ArticleMapper articleMapper;
@Test
void getAll() {
List list = articleMapper.getAll();
System.out.println(list);
}
}
以上并非系统报错,而是插件在报错,告诉我们没有设置返回的技术类型,高版本的idea遇到这种情况运行是不会报错的。
@Transactional //数据回滚:使用该注解,会执行下面操作,但是不会真的操作数据库中的内容
原因是:实体类中的属性和数据库表中的字段名不一致。
解决方案:
1.将实体类中的属性和表中的字段名保持一致(最简单的解决方案)
2.使用sql语句中的as进行列名(字段名)重命名,让列名(字段名)等于属性名
select username as name from userinfo where id=#{id}c 3.定义一个resultMap,将属性名和字段名进行手动映射
resultMap放入mapper.xml的
中
以下是对应关系:尽量把全部属性映射上,否则多表查询时可能会报错。
上图有个错误!!! colum是表里面的字段名,property是实体类里的属性,写反了。