Mybatis入門之基本操作!!!
一顆小胡椒2022-07-21 11:12:11
前言
- 作為一個資深后端碼農天天都要和數據庫打交道,最早使用的是 Hiberate,一個封裝性極強的持久性框架。自從接觸到 Mybatis 就被它的靈活性所折服了,可以自己寫 SQL,雖然輕量級,但是麻雀雖小,五臟俱全。這篇文章就來講講什么是 Mybatis,如何簡單的使用 Mybatis。
什么是 Mybatis
- MyBatis 是一款優秀的
持久層框架,它支持自定義 SQL、存儲過程以及高級映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設置參數和獲取結果集的工作。MyBatis 可以通過簡單的XML或注解來配置和映射原始類型、接口和Java POJO(Plain Old Java Objects,普通老式 Java 對象)為數據庫中的記錄。
環境搭建
- 本篇文章使用的環境是
SpringBoot+Mybatis+Mysql
Maven 依賴
- MySQL 驅動依賴和 Druid 連接池的依賴
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> <scope>runtime</scope> </dependency> <!--druid連接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.9</version> </dependency>
- Mybatis 啟動包依賴,此處導入的是 SpringBoot 和 Mybatis 整合啟動器的依賴,點擊去可以看到,這個啟動包依賴了
mybatis和mybatis-spring(Mybatis 和 Spring 整合的 Jar 包),因此使用 SpringBoot 之后只需要導入這個啟動器的依賴即可。
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency>
- 以上兩個依賴添加成功后,Maven 環境就已經配置完了。
數據庫連接池配置(Druid)
- 這個不是本文的重點,而且網上很多教程,我就簡單的配置一下,在 SpringBoot 的
application.properties中配置即可。
##單一數據源 spring.datasource.url=jdbc\:mysql\://127.0.0.1\:3306/vivachekcloud_pzhdermyy?useUnicode\=true&characterEncoding\=UTF-8&zeroDateTimeBehavior\=convertToNull&useSSL\=false spring.datasource.username=root spring.datasource.password=123456 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver #初始化連接大小 spring.datasource.druid.initial-size=0 #連接池最大使用連接數量 spring.datasource.druid.max-active=20 #連接池最小空閑 spring.datasource.druid.min-idle=0 #獲取連接最大等待時間 spring.datasource.druid.max-wait=6000 spring.datasource.druid.validation-query=SELECT 1 #spring.datasource.druid.validation-query-timeout=6000 spring.datasource.druid.test-on-borrow=false spring.datasource.druid.test-on-return=false spring.datasource.druid.test-while-idle=true #配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒 spring.datasource.druid.time-between-eviction-runs-millis=60000 #置一個連接在池中最小生存的時間,單位是毫秒 spring.datasource.druid.min-evictable-idle-time-millis=25200000 #spring.datasource.druid.max-evictable-idle-time-millis= #打開removeAbandoned功能,多少時間內必須關閉連接 spring.datasource.druid.removeAbandoned=true #1800秒,也就是30分鐘 spring.datasource.druid.remove-abandoned-timeout=1800 #<!-- 1800秒,也就是30分鐘 --> spring.datasource.druid.log-abandoned=true spring.datasource.druid.filters=mergeStat #spring.datasource.druid.verifyServerCertificate #spring.datasource.filters=stat,wall,log4j # 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄 spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
基礎概念
dao層:用于存放和數據庫交互的文件,Mybatis 的interface都放在此層service層:用于存放業務邏輯的文件。
配置 xml 文件存放的位置
- Mybatis 中
xml的文件默認是要和interface放在一個包下的,并且文件的名稱要一樣。 - 在和 SpringBoot 整合后有兩種配置方式,下面詳細介紹。
application.properties 中設置
- 既然是和 SpringBoot 整合,那么萬變不離
xxxAutoConfiguration這個配置類了,Mybatis 的配置類就是MybatisAutoConfiguration,如下:
@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {}
- 可以看到
@EnableConfigurationProperties(MybatisProperties.class)這行代碼,就是將 properties 中的屬性映射到 MybatisProperties 這個成員屬性中,因此設置的方式就要看其中的屬性。
public class MybatisProperties {
//前綴
public static final String MYBATIS_PREFIX = "mybatis";
/**
* Mybatis配置文件的位置
*/
private String configLocation;
/**
* Mybatis的Mapper的xml文件的位置
*/
private String[] mapperLocations;
- 因此設置的方式很簡單,如下:
## xml文件放置在/src/main/resource/mapper/文件夾下 mybatis.mapper-locations=classpath*:/mapper/**/*.xml
配置類中設置
- 不是本章重點,后面在講 Mybatis 和 SpringBoot 整合的文章會涉及到該內容。
配置掃描 Mybatis 的 interface
- 在和 SpringBoot 整合后,掃描 Mybatis 的接口,生成代理對象是一件很簡單的事,只需要一個注解即可。
@Mapper
- 該注解標注在 Mybatis 的
interface類上,SpringBoot 啟動之后會掃描后會自動生成代理對象。實例如下:
@Mapper
public interface UserInfoMapper {
int insert(UserInfo record);
int insertSelective(UserInfo record);
}
- 缺點:每個
interface都要標注一個,很雞肋,一個項目中的 interface 少說也有上百個吧。
@MapperScan
@Mapper注解的升級版,標注在配置類上,用于一鍵掃描 Mybatis 的interface。- 使用也是很簡單的,直接指定接口所在的包即可,如下:
@MapperScan({"com.xxx.dao"})
public class ApiApplication {}
@MapperScan和@Mapper這兩個注解千萬不要重復使用。- 優點:一鍵掃描,不用每個 interface 配置。
基本的 crud
- 既然和數據庫交互,避免不了 crud 操作,就安心做一個妥妥的
crud boy吧。 - 針對 Mybatis 其實有兩套方法映射,一個是 XML 文件的方式,一個是注解的方式。但是今天只講 XML 文件的方式,原因很簡單,注解的方式企業不用,誰用誰倒霉,哈哈。
查詢
- 查詢語句是 MyBatis 中最常用的元素之一——光能把數據存到數據庫中價值并不大,還要能重新取出來才有用,多數應用也都是查詢比修改要頻繁。MyBatis 的基本原則之一是:在每個插入、更新或刪除操作之間,通常會執行多個查詢操作。因此,MyBatis 在查詢和結果映射做了相當多的改進。一個簡單查詢的 select 元素是非常簡單的。
<select id="selectPersonById" parameterType="int" resultType="com.myjszl.domain.Person">
SELECT name,age,id FROM PERSON WHERE ID = #{id}
</select>
- 對應的
interface的方法如下:
Person selectPersonById(int id);
<select>這個標簽有很多屬性,比較常用的屬性如下:id(必填):在命名空間中唯一的標識符,可以被用來引用這條語句。和interface中的方法名要一致。parameterType(可選):將會傳入這條語句的參數的類全限定名或別名。這個屬性是可選的,因為 MyBatis 可以通過類型處理器(TypeHandler)推斷出具體傳入語句的參數,默認值為未設置(unset)。resultType:期望從這條語句中返回結果的類全限定名或別名。注意,如果返回的是集合,那應該設置為集合包含的類型,而不是集合本身的類型。resultType和resultMap之間只能同時使用一個。resultMap:對外部resultMap的命名引用。結果映射是 MyBatis 最強大的特性,如果你對其理解透徹,許多復雜的映射問題都能迎刃而解。resultType和resultMap之間只能同時使用一個。
變更
- 數據變更語句 insert,update 和 delete 的實現非常接近。
- 下面是 insert,update 和 delete 語句的示例:
<insert id="insertAuthor">
insert into Author (id,username,password,email,bio)
values (#{id},#{username},#{password},#{email},#{bio})
</insert>
<update id="updateAuthor">
update Author set
username = #{username},
password = #{password},
email = #{email},
bio = #{bio}
where id = #{id}
</update>
<delete id="deleteAuthor">
delete from Author where id = #{id}
</delete>
#{}和${}的區別
- 上面的例子中我們可以看到使用的都是
#{},關于#{}和${}的區別也是在很多初級工程師的面試最常被問到的,現在只需要記住區別就是#{}使用了 JDBC 的預編譯,可以防止 SQL 注入,提高了安全性,${}并沒有預編譯,安全性不夠。在后面 Mybatis 的源碼講解中將會涉及到為什么一個用了預編譯,一個沒用。
自增 ID 的返回
- 關于 Mysql 的文章中有提到,設計一個表最好要有一個自增 ID,無論這個 ID 你是否用到,具體原因不在解釋,可以翻看之前的文章。
- 有了自增 ID,插入之后并不能自動返回,但是我們又需要這個 ID 值,那么如何返回呢?
<insert>標簽提供了兩個屬性用來解決這個問題,如下:useGeneratedKeys:設置為 true,表示使用自增主鍵返回keyProperty:指定返回的自增主鍵映射到parameterType的哪個屬性中。- 假設插入
Person,并且 person 表中的自增主鍵 id 需要返回,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.xxx.dao.PersonMapper">
<insert id='addPerson' parameterType='com.xxx.domain.Person' useGeneratedKeys="true"
keyProperty="id" >
insert into person(name,age)
values(#{name},#{age});
</insert>
</mapper>
SQL 代碼片段
- 這個元素可以用來定義可重用的 SQL 代碼片段,以便在其它語句中使用。參數可以靜態地(在加載的時候)確定下來,并且可以在不同的 include 元素中定義不同的參數值。比如:
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
- 這個 SQL 片段可以在其它語句中使用,例如:
<select id="selectUsers" resultType="map"> select <include refid="userColumns"><property name="alias" value="t1"/></include>, <include refid="userColumns"><property name="alias" value="t2"/></include> from some_table t1 cross join some_table t2 </select>
開啟駝峰映射
- DBA 在設計數據庫的時候,往往使用的是下劃線(
_)的方式,比如user_id。但是 Java 是不規范的,我們通常將它轉換為userId,這就是駝峰命名方法。 - 但是在使用 Mybatis 查詢的時候,比如:
<select id='selectById' resultType='com.xxx.doamin.User'> select user_id from user_info </select>
- 上面的
user_id和User中的userId根本不對應,也就映射不進去,此時查詢的結果就是 userId 是 null,當然我們可以使用別名的方式,SQL 可以改寫為select user_id as userId from user_info - 另外一種方式是不用別名,直接開啟 Mybatis 的駝峰映射規則,會自動映射,開啟的方式很簡單,就是在
application.properties文件配置一下,如下:
mybatis.configuration.map-underscore-to-camel-case=true
總結
- 本文主要講了 Mybatis 與 SpringBoot 的整合過程,基本的 crud,各種標簽的屬性等內容,屬于一個入門級別的教程,后續的內容會逐漸深入。
- 另外,MySQL 進階的教程已經寫了五篇文章了,每一篇都是經典,已經出了一個專輯,感興趣的可以收藏一下MySQL 進階。
- 感謝你的閱讀,作者會定時的更新原創文章,如果覺得寫的不錯的話,可以關注一下本公眾號。
一顆小胡椒
暫無描述