一、創建Mybatis的項目
Mybatis 是?個持久層框架, 具體的數據存儲和數據操作還是在MySQL中操作的, 所以需要添加MySQL驅動
1.添加依賴
或者 手動添加依賴
<!--Mybatis 依賴包--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.4</version></dependency><!--mysql驅動包--><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency>
項??程創建完成后,?動在pom.xml?件中,導?Mybatis依賴和MySQL驅動依賴
版本會隨著SpringBoot 版本發?變化
SpringBoot 3.X對?MyBatis版本為3.X
對應關系參考:Introduction – mybatis-spring-boot-autoconfigure
2.配置常見的數據庫信息
這是常見關于Mybatis的配置信息,大家可以自取
csdn暫時還不支持yml文件,這是 yml 文件:
spring:datasource: # 配置數據庫名url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=falseusername: root #數據庫用戶password: root #密碼driver-class-name: com.mysql.cj.jdbc.Driver# 設置 Mybatis 的 xml 保存路徑
mybatis: mapper-locations: classpath:mapper/*Mapper.xmlconfiguration: # 配置打印 MyBatis 執行的 SQLlog-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true #自動駝峰轉換
前提是有這樣的一個數據庫
那么這里提供一個數據庫:
-- 創建數據庫
DROP DATABASE IF EXISTS mybatis_test;CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;-- 使用數據數據
USE mybatis_test;-- 創建表[用戶表]
DROP TABLE IF EXISTS user_info;
CREATE TABLE `user_info` (`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,`username` VARCHAR ( 127 ) NOT NULL,`password` VARCHAR ( 127 ) NOT NULL,`age` TINYINT ( 4 ) NOT NULL,`gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-女 0-默認',`phone` VARCHAR ( 15 ) DEFAULT NULL,`delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-刪除',`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now() ON UPDATE now(),PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; -- 添加用戶信息
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );-- 創建文章表
DROP TABLE IF EXISTS article_info;CREATE TABLE article_info (id INT PRIMARY KEY auto_increment,title VARCHAR ( 100 ) NOT NULL,content TEXT NOT NULL,uid INT NOT NULL,delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-刪除',create_time DATETIME DEFAULT now(),update_time DATETIME DEFAULT now()
) DEFAULT charset 'utf8mb4';-- 插入測試數據
INSERT INTO article_info ( title, content, uid ) VALUES ( 'Java', 'Java正文', 1 );
這樣一個表
3.寫對應的對象
一般寫在model文件夾下
@Data
public class UserInfo {private Integer id;private String username;private String password;private Integer age;private Integer gender;private String phone;//數據庫用下劃線連接單詞,java直接用小駝峰private Integer deleteFlag;private Date createTime;private Date updateTime;}
4.寫持久層代碼
一般寫在mapper文件夾下,或者Dao
@Mapper
public interface UserInfoMapper {//查詢所有用戶的信息@Select("select * from user_info")List<UserInfo> selectAll();
}
5.單元測試
在對應的mapper接口下,右擊
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid selectAll() {userInfoMapper.selectAll().forEach(x -> System.out.println(x));//等同于
// List<UserInfo> userInfos = userInfoMapper.selectAll();
// for (UserInfo userInfo : userInfos) {
// System.out.println(userInfo);
// }}
}
結果:
二、Mybatis的基本操作
1.日志打印
2.傳遞單個參數
通過 #{……} 傳遞 參數
@Mapper
public interface UserInfoMapper {// 只有一個參數的時候這里寫什么名字無所謂@Select("select * from user_info where id = #{id}")UserInfo selectUserById(Integer id);
}
單元測試:
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid selectUserById() {System.out.println(userInfoMapper.selectUserById(2));}
}
結果:
3.傳遞多個參數
3種方法
方法1:
標簽 和 方法 中的名字一樣
方法2:
它給方法的每個形參取了別名,例如第一個param1 第二個 param2
方法3:
使用@Param("……"),和 標簽中的 #{……}對應
@Mapper
public interface UserInfoMapper {// @Select("select * from user_info where id = #{id} and gender = #{gender}") 方法1 推薦// @Select("select * from user_info where id = #{param2} and gender = #{param1}") 方法2 不推薦// @Select("select * from user_info where id = #{id2} and gender = #{gender2}") 錯誤//@Select("select * from user_info where id = #{id2} and gender = #{gender2}") // 方法3 推薦List<UserInfo> selectUserByIdAndGender(@Param("id2") Integer id,@Param("gender2") Integer gender);}
單元測試:
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid selectUserByIdAndGender() {List<UserInfo> userInfos = userInfoMapper.selectUserByIdAndGender(3, 1);System.out.println(userInfos);}
}
結果:
返回的參數可以是對象,也可以是集合類:
當我們知道數據庫中對應的參數只有一個時,可以用類接收,但是最好用集合,萬一他人增加了符號相同條件的數據,一個類就裝不下。
4.查(Select)
查詢之前已經都寫到了,就不再寫了。
發現這樣的一個問題:
數據庫的規范是單詞之間用下劃線分割,java的變量規范是小駝峰命名。這就導致了屬性對應不上導致為null
解決辦法,我先講最推薦的:
4.1 開啟駝峰命名
在yml或者properties文件中設置:
# 設置 Mybatis 的 xml 保存路徑
mybatis:mapper-locations: classpath:mapper/*Mapper.xmlconfiguration: # 配置打印 MyBatis 執行的 SQLlog-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true #自動駝峰轉換
4.2 起別名
@Mapper
public interface UserInfoMapper {@Select("select id, username, password, age, gender, phone, delete_flag as deleteFlag, " +"create_time as createTime, update_time as updateTime from user_info")List<UserInfo> selectAll2();}
即便是不用起別名也不建議用 select * , 就應該用到哪一列寫哪一列,即便是所有的列都需要也這么寫,因為更加規范。
4.3 結構映射
4.3.1 @Results 和 @Result
@Mapper
public interface UserInfoMapper {// @Select("select id, username, password, age, gender, phone, delete_flag as deleteFlag, " +
// "create_time as createTime, update_time as updateTime from user_info")@Results({@Result(column = "delete_flag", property = "deleteFlag"),@Result(column = "create_time", property = "createTime"),@Result(column = "update_time", property = "updateTime")})@Select("select id, username, password, age, gender, phone, delete_flag, create_time, update_time from user_info")List<UserInfo> selectAll2();
}
這樣比起別名麻煩呀,那么真實用法是這樣:
4.3.2 @ResultMap
5.增(Insert)
5.1傳遞對象
方法一:
@Mapper
public interface UserInfoMapper {@Insert("insert into user_info (username, `password`, age, gender) values (#{username},#{password},#{age},#{gender})")Integer insertUser(UserInfo userInfo);}
Mapper層
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid insertUser() {UserInfo userInfo = new UserInfo();userInfo.setUsername("張三");userInfo.setPassword("123445");userInfo.setAge(19);userInfo.setGender(0);userInfoMapper.insertUser(userInfo);}}
成功:
方法二:
@Mapper
public interface UserInfoMapper {@Insert("insert into user_info (username, `password`, age, gender)" +"values (#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender})")Integer insertUserByParam(@Param("userInfo") UserInfo userInfo);
}
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid insertUserByParam() {UserInfo userInfo = new UserInfo();userInfo.setUsername("李四");userInfo.setPassword("jaba213");userInfo.setAge(19);userInfo.setGender(0);userInfoMapper.insertUser(userInfo);}
}
6.刪(Delete)
刪除的時候一般使用id刪除
假設我們現在是pdd的員工,我們下單了一個商品但是還沒有付錢,那么此時我們就需要拿到這個訂單的id,如果在10分鐘內不付錢,我們就刪除這個訂單。
那么我們就需要在插入之后拿到id,可以用這個注解:
6.1 @Options
@Mapper
public interface UserInfoMapper {@Delete("delete from user_info where id = #{id}")Integer delete(Integer id);@Options(useGeneratedKeys = true, keyProperty = "id")@Insert("insert into user_info (username, `password`, age, gender)" +"values (#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender})")Integer insertUserByParam(@Param("userInfo") UserInfo userInfo);}
單元測試:
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid insertUserByParam() {UserInfo userInfo = new UserInfo();userInfo.setUsername("wangmaz");userInfo.setPassword("54231");userInfo.setAge(19);userInfo.setGender(0);//返回影響的行數Integer result = userInfoMapper.insertUserByParam(userInfo);// 通過getId()獲取 System.out.println("執行結果" + result + " ,id : " + userInfo.getId());}
結果:
那么拿到數據你想用這個id干什么自己處理就好了
普通的刪除:
@Mapper
public interface UserInfoMapper {@Delete("delete from user_info where id = #{id}")Integer delete(Integer id);}
單元測試:
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid delete() {
// 刪除id為11的數據userInfoMapper.delete(11);}
}
運行前:
運行后:
7.改(Update)
@Mapper
public interface UserInfoMapper {@Update("update user_info set password = #{password} where id = #{id}")Integer update(Integer id, String password);
}
@Mapper
public interface UserInfoMapper {@Update("update user_info set password = #{password} where id = #{id}")Integer update(Integer id, String password);
}
修改前:
修改后 :
三、報錯信息
看到這樣的報錯“密碼錯誤”,直接去看配置信息
數據庫返回結構太多,方法定義的返回結果不匹配
標簽參數和方法參數不匹配