MyBatis
MyBatis是一款优秀的 持久化 框架,用于简化JDBC的开发,就是更加简单的完成程序与数据库之间交互的框架
1. Mybatis基础操作
1.1打印日志
在Mybatis中,我们可以借助日志,查看到sql语句的执行,执行传递的参数以及执行结果
只需要在配置文件中进行配置即可:
mybatis:
configuration: # 配置打印 MyBatis⽇志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
我们尝试运行一个测试用例:
- 如果没有配置日志:
- 配置了日志:
分别表示:执行的sql语句,参数的传递,以及sql执行的结果
1.2参数传递
如果我们要查一个id为4的用户信息:
@Mapper
public interface UserInfoMapper {
@Select("select * from userinfo where id = 4")
public UserInfo queryUserById();
}
@SpringBootTest
class UserInfoMapperTest {
@Autowired
private UserInfoMapper userInfoMapper;
@Test
void queryUserById() {
UserInfo userInfo = userInfoMapper.queryUserById();
System.out.println(userInfo);
}
}
执行结果:
但是这样的话,貌似sql语句就写死了,因此sql语句里面的id不应该是固定数值
解决方法: 使用 #{}
的方式获取方法中的参数
@Select("select * from userinfo where id = #{id}")
public UserInfo queryUserById(int id);
//测试代码
@Test
void queryUserById() {
UserInfo userInfo = userInfoMapper.queryUserById(4);
System.out.println(userInfo);
}
执行结果:
也可以通过@Param
设置参数的别名
@Select("select * from userinfo where id = #{id}")
public UserInfo queryUserById(@Param("id") int id);
那么就会出现以下几种情况:
(1). 只有一个参数
@Select("select * from userinfo where id = #{param}")
public UserInfo queryUserById(int id);
执行结果:
结论:只有一个参数的时候,即使是参数名不一致,也不用指定
(2). 有多个参数
@Select("select * from userinfo where id = #{param} and username = #{name}")
public UserInfo queryUserById(int id,String username);
//测试用例:
@Test
void queryUserById() {
UserInfo userInfo = userInfoMapper.queryUserById(4,"wangwu");
System.out.println(userInfo);
}
执行结果
报错提示:在参数id,param1,username,param2里面没有找到param
此时我们就能知道,实际上方法会自动帮我们生成几个参数:id,param1,username,param2
那么我们改动一下:
@Select("select * from userinfo where id = #{id} and username = #{username}")
public UserInfo queryUserById(int id,String username);
执行结果就是正确的
(3)多个参数加上@Param
@Select("select * from userinfo where id = #{id1} and username = #{username1}")
public UserInfo queryUserById(@Param("id") int id1,@Param("username") String username1);
执行结果:
报错提示:在参数id,param1,username,param2里面没有找到id1
此时我们就能知道,实际上方法会自动帮我们生成几个参数:id,param1,username,param2,其中 id 和 username 是 @Param
注解里面的值
这样才是对的:
@Select("select * from userinfo where id = #{id} and username = #{username}")
public UserInfo queryUserById(@Param("id") int id1,@Param("username") String username1);
无论如何,如果有多个参数,sql里面的变量一定要和方法生成的参数名保持一致
1.3 INSERT
假设sql语句为:insert into userinfo (username,
password,age,gender,phone) values ("zhaoliu","zhaoliu",19,1,"15912412311");
需要将sql语句里面的常量替换成动态的参数
@Insert("insert into userinfo (username,`password`,age,gender,phone) " +
"values (#{username},#{password},#{age},#{gender},#{phone});")
public int insertUser(UserInfo userInfo);
测试用例:
@Test
void insertUser() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("zhaoliu");
userInfo.setPassword("zhaoliu");
userInfo.setAge(18);
userInfo.setGender(1);
userInfo.setPhone("110");
System.out.println(userInfoMapper.insertUser(userInfo));
}
执行结果:
** 返回主键**
通常情况下,我们需要增加数据后得到数据的主键,以供后续操作
想要拿到自增的ID,需要在Mapper接口的方法上添加一个Options的注解
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into userinfo (username,`password`,age,gender,phone) " +
"values (#{username},#{password},#{age},#{gender},#{phone});")
public int insertUser(UserInfo userInfo);
- useGeneratedKeys:会让MyBatis使用JDBC的getGeneratedKeys来得到由数据库内部生成的默认的主键(例如自增主键)
- keyProperty:指定能够唯一识别对象的属性
测试用例:
@Test
void insertUser() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("zhaoliu");
userInfo.setPassword("zhaoliu");
userInfo.setAge(18);
userInfo.setGender(1);
userInfo.setPhone("110");
System.out.println(userInfoMapper.insertUser(userInfo) + " 得到主键" + userInfo.getId());
}
执行结果
1.4 DELETE
@Delete("delete from userinfo where id = #{id}")
public int deleteUserById(@Param("id") int id);
测试用例:
@Test
void deleteUserById() {
userInfoMapper.deleteUserById(5);
}
执行结果:
1.5 UPDATE
@Update("update userinfo set `password` = #{password} where id = #{id}")
public int updatePasswordById(UserInfo userInfo);
测试用例:
@Test
void updatePasswordById() {
UserInfo userInfo = new UserInfo();
userInfo.setPassword("123456");
userInfo.setId(1);
userInfoMapper.updatePasswordById(userInfo);
}
执行结果:
1.6 SELECT
我们在最开始查询的时候,发现其中有几个值是null但是明明数据库返回的值是有数值的
实际上,当自动映射查询结果时,Mybatis会获取结果中返回的列名并在java类中查找相同名字的属性(忽略大小写)
但是由于在数据库里面的列名是类似于"delete_flag" 这样的格式,而在java里面是类似于 "deleteFlag"的格式,匹配不上,就无法赋值
解决方法如下:
起别名
在sql语句中给列名起别名,保持列名和实体类属性名一致
@Select("select id,username,`password`,age,gender,phone,delete_flag as deleteFlag, " +
"create_time as createTime, update_time as updateTime from userinfo")
public List<UserInfo> queryAllUser1();
测试用例:
@Test
void queryAllUser1() {
List<UserInfo> userInfos = userInfoMapper.queryAllUser1();
System.out.println(userInfos);
}
执行结果:
结果映射
@Select("select id,username,`password`,age,gender,phone,delete_flag,create_time from userinfo")
@Results({
@Result(column = "delete_flag",property = "deleteFlag"),
@Result(column = "create_time",property = "createTime"),
@Result(column = "update_time",property = "updateTime")
})
List<UserInfo> queryAllUser2();
测试用例:
@Test
void queryAllUser2() {
List<UserInfo> userInfos = userInfoMapper.queryAllUser2();
System.out.println(userInfos);
}
代码:
如果其他的SQL也希望使用这个映射关系,可以使用能id给这个@Results
定义别名,使用@ResultMap
注解来复用
开启驼峰命名
通常数据库列名命名是使用下划线分割各个单词的命名方式,而java属性名一般遵循驼峰命名法.
我们可以在配置文件里面将mapUnderscoreToCamelCase
设置为true
此时即使是最之前,我们不做任何处理的java代码也能得到完整结果