maven框架,了解MyBatis框架

 2023-10-06 阅读 30 评论 0

摘要:MyBatis 是一款優秀的持久層框架,它支持自定義 SQL、存儲過程以及高級映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設置參數和獲取結果集的工作。MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO(Plain Old Java Objects,普

MyBatis 是一款優秀的持久層框架,它支持自定義 SQL、存儲過程以及高級映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設置參數和獲取結果集的工作。MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對象)為數據庫中的記錄

JDBC編程存在的問題

在此之前我們了解的JDBC的操作為: 1. 首先創建數據庫連接池DataSource 2. 通過DataSource獲取數據庫連接Connection 3. 編寫要執行帶“?”占位符的SQL語句 4. 通過Connection及SQL創建操作命令對象Statement 5. 替換占位符:指定要替換的數據庫字段類型,占位符索引及要替換的值 6. 執行SQL語句 7. 處理結果集 8. 釋放資源

maven框架,存在問題
對用不同業務來說,他的CRUD操作類型基本上都是以上的步驟,只有如下部分是不一樣的:

  • 帶占位符的SQL語句
  • 替換占位符:一般使用基礎類型或Java對象,需要明確替換哪個占位符,哪個值來替換
  • 如果是查新。一般會將結果集轉換為Java對象,需要提供轉換的急Java類型,及與結果集字段的映射關系

可以看出少量的代碼真正用于業務功能,大部分的代碼都是樣板代碼。不過,這些樣板代碼非常重要,清理資源和處理錯誤確保了數據訪問的健壯性,避免了資源的泄露。

解決方案

  1. 最簡單的,涉及工具類提供統一的功能:獲取數據庫連接,釋放資源
  2. 使用模版設計模式,父類的模板方法提供統一的邏輯,子類提供不同實現。但這部分統一代碼邏輯都會比較復雜。
  3. 更進一步的考慮,其實可以通過 AOP 技術,自動的生成代理類,代理類的方法中織入了統一的樣板代碼。

框架會采用第三種解決方案,自動的生成樣板代碼,我們只需要提供 sql ,要替換占位符的數據,返回結果集要轉換的 java 類型
在這里插入圖片描述

ORM框架

ORM(Object Relational Mapping),即對象關系映射。在面向對象編程語言中,將關系型數據庫中的數據與對象建立起映射關系,進而自動的完成數據與對象的互相轉換:

  1. 將輸入數據(即傳入對象)+SQL 映射成原生 SQL
  2. 將結果集映射為返回對象,即輸出對象

ORM 把數據庫映射為對象
數據庫表(table)–> 類(class)
記錄(record,行數據)–> 對象(object)
字段(field) --> 對象的屬性(attribute)

常見的ORM框架

常見的ORM框架有Mybatis和Hibernate

Mybatis

Mybatis是一種典型的半自動的 ORM 框架,所謂的半自動,是因為還需要手動的寫 SQL 語句,再由框
架根據 SQL 及 傳入數據來組裝為要執行的 SQL。其優點為:

  1. 因為由程序員自己寫 SQL,相對來說學習門檻更低,更容易入門。
  2. 更方便做 SQL的性能優化及維護。
  3. 對關系型數據庫的模型要求不高,這樣在做數據庫模型調整時,影響不會太大。適合軟件需求變更
    比較頻繁的系統,因此國內系統大部分都是使用如 Mybatis 這樣的半自動 ORM 框架。
    其缺陷為:
    不能跨數據庫,因為寫的 SQL 可能存在某數據庫特有的語法或關鍵詞

Hibernate

Hibernate是一種典型的全自動 ORM 框架,所謂的全自動,是 SQL 語句都不用在編寫,基于框架的
API,可以將對象自動的組裝為要執行的 SQL 語句。其優點為:

  1. 全自動 ORM 框架,自動的組裝為 SQL 語句。
  2. 可以跨數據庫,框架提供了多套主流數據庫的 SQL 生成規則。
    其缺點為:
    學習門檻更高,要學習框架 API 與 SQL 之間的轉換關系
    對數據庫模型依賴非常大,在軟件需求變更頻繁的系統中,會導致非常難以調整及維護。可能數據
    庫中隨便改一個表或字段的定義,Java代碼中要修改幾十處。
    很難定位問題,也很難進行性能優化:需要精通框架,對數據庫模型設計也非常熟悉。

Mybatis的使用

  1. 首先創建一個Maven項目 mybatis-study,在pom.xml中引入SpringBoot及Mybatis需要的依賴包,
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!-- 默認使用的Spring Framework版本為5.2.10.RELEASE --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.5.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>org.example</groupId><artifactId>mybatis-study</artifactId><version>1.0-SNAPSHOT</version><properties><java.version>1.8</java.version></properties><dependencies><!-- spring-boot-starter-web: 基于SpringBoot開發的依賴包,會再次依賴spring-framework中基本依賴包,aop相關依賴包,web相關依賴包,還會引入其他如json,tomcat,validation等依賴 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!-- 排除tomcat依賴 --><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><!-- 添加 Undertow 依賴 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-undertow</artifactId></dependency><!--引入AOP依賴--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!-- mybatis-spring-boot-starter: Mybatis框架在SpringBoot中集成的依賴包,Mybatis是一種數據庫對象關系映射Object-Relationl Mapping(ORM)框架,其他還有如Hibernate等 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.3</version></dependency><!-- Mybatis代碼生成工具 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.5</version></dependency><!-- druid-spring-boot-starter: 阿里Druid數據庫連接池,同樣的運行時需要 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.3</version></dependency><!-- JDBC:mysql驅動包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version><scope>runtime</scope></dependency><!-- spring-boot-devtools: SpringBoot的熱部署依賴包 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><!-- 不能被其它模塊繼承,如果多個子模塊可以去掉 --><optional>true</optional></dependency><!-- lombok: 簡化bean代碼的框架 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- spring-boot-starter-test: SpringBoot測試框架 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><!-- SpringBoot的maven打包插件 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!-- 明確指定一些插件的版本,以免受到 maven 版本的影響 --><plugin><artifactId>maven-clean-plugin</artifactId><version>3.1.0</version></plugin><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version></plugin><plugin><artifactId>maven-deploy-plugin</artifactId><version>2.8.2</version></plugin><plugin><artifactId>maven-install-plugin</artifactId><version>2.5.2</version></plugin><plugin><artifactId>maven-jar-plugin</artifactId><version>3.2.0</version></plugin><plugin><artifactId>maven-resources-plugin</artifactId><version>3.1.0</version></plugin><plugin><artifactId>maven-site-plugin</artifactId><version>3.3</version></plugin><plugin><artifactId>maven-surefire-plugin</artifactId><version>2.22.2</version></plugin></plugins></build></project>
  1. 準備數據庫
    在根目錄下創建一個dp包,然后創建一個init.sql的文件,然后放入數據的初始化語句
drop database if exists mybatis_study;
create database mybatis_study character set utf8mb4;use mybatis_study;drop table if exists user;
create table user(id int primary key auto_increment,username varchar(20) not null unique comment '賬號',password varchar(20) not null comment '密碼',nickname varchar(20) comment '用戶昵稱',sex bit default 0 comment '性別,0/false為女,1/true為男',birthday date comment '生日',head varchar(50) comment '頭像地址',create_time timestamp default now() comment '創建日期,默認為插入時的日期'
) comment '用戶表';insert into user(username, password) values ('a1', '11');
insert into user(username, password) values ('a2', '12');
insert into user(username, password) values ('b', '2');
insert into user(username, password) values ('c', '3');
  1. 準備一個SpringBoot的啟動類
    在java目錄創建org.example.Application的啟動類
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}
  1. 準備SpringBoot的配置文件
    在resource目錄下創建一個application.properties文件,其中賬號和密碼為你自己MySQL的賬號和密碼
debug=true
# 設置打印日志的級別,及打印sql語句
#日志級別:trace,debug,info,warn,error
#基本日志
logging.level.root=INFO
#掃描的包并按debug日志級別打印:druid.sql.Statement類和org.example包
logging.level.druid.sql.Statement=DEBUG
logging.level.org.example=DEBUG#數據庫連接池配置:
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_study?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=******#指定Mybatis表和實體映射關系xml配置文件,包含表與實體的映射,字段和屬性的映射,及各個sql語句
mybatis.mapper-locations=classpath:mapper/**Mapper.xml
  1. 然后在對database進行配置,配置完成之后在init.sql頁面點擊右鍵run,然后就可以在database里面看到自己剛剛創建的數據庫

在這里插入圖片描述
6. 最后運行Spring啟動類,不報即可

Mybatis開發

Java實體類

需要根據數據庫表建立 Java類,表中的每個字段需要對應類中的屬性。之后會在 Mybatis 的映射文件中配置字段與屬性的映射關系。
這部分實體類對象,對應以前面圖中綠色的兩個部分,一般會以如下方式呈現:

  1. 作為傳入數據,表現在方法參數上。
  2. 作為結果集轉換的輸出數據,表現在方法的返回值上

配置Mybatis數據操作Mapper接口

這部分對應以上圖中淡黃色的部分:由開發人員提供執行SQL的接口,框架會自動為接口生成代理類,
代理類中會包含模版方法的代碼邏輯

在 org.example.mapper 包下創建的用戶類的 Mybatis 映射 Mapper 接口:
注意接口需要使用注解 @Mapper 及 @Component 。在SpringBoot啟動后,SpringBoot會自動掃描到啟
動類包下的注解類,且Mybatis框架會進一步完成生成代理類的工作。

@Mapper
@Component
public interface UserMapper {User selectById(Integer id);
}

配置Mybatis實體映射文件

映射文件是xml文件,且在 application.properties 中指定了路徑,是在classpath:mapper/**Mapper.xml ,該路徑是在類加載路徑下的mapper文件夾下,所有以Mapper.xml 結尾的文件。

所以可以在 src/main/resources 下新建 mapper 文件夾,并創建文章類的映射文件UserMapper(這個名字最好和Mapper接口類中的UserMapper一致)

<?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="org.example.mapper.UserMapper"><resultMap id="Basespace" type="org.example.model.User"><id column="id" property="id"/><result column="username" property="username"/><result column="password" property="password"/></resultMap></mapper>
  • mapper標簽:需要指定 namespace 屬性,表示命名空間,值為 mapper 接口的全限定名,包括全包名.類名
  • resultMap標簽:配置查詢結果集與 Java 類的映射關系,包括如下配置:
  1. id 綁定該映射的鍵,之后可以通過 id 值來使用。在本命名空間使用可以直接使用,其他命
    名空間需要以 命名空間.resultMap的id 的方式來使用。之后的部分會進一步使用。這里先大
    概介紹。
  2. type 綁定該結果集映射的 Java 類。
  3. id標簽指定結果集的唯一標識,一般為數據庫主鍵。
  4. result標簽指定結果集字段與 Java 類中屬性的映射,其中 column 指定結果集字段,
    property 指定 Java 屬性。

配置SQL

之后還需要在 Mybatis 映射文件中配置 SQL,需要配置在mapper>標簽下,與<resultMap標簽同級

對 CRUD 操作來說,每個不同類型的操作都有對應的標簽

  • select標簽:查詢語句
  • insert標簽:插入語句
  • update標簽:修改語句
  • delete標簽:刪除語句
    <select id="selectById" parameterType="java.lang.Integer"resultMap="BaseResultMap">select * from User where id=#{id}</select>

注意:

  1. 都必須指定 id 屬性,該屬性會綁定 mapper 接口方法,值和方法名相同。本質上 Mybatis 是根據 mapper包名 查找對應的命名空間,之后在調用方法時,在該命名空間下根據 接口方法名 查找對應 id 的 sql。
  2. 使用 parameterType 指定傳入數據的類型,該配置只能在mapper接口方法參數只有一個時使用,也可以省略。如果有多個方法參數,需要另行設置,
  3. .查詢語句可以使用 resultMap 屬性綁定結果集映射,值為結果集映射的 id 。注意返回結果集有一行和多行數據時,都可以使用 resultMap 綁定映射,對應接口方法的返回值是一個對象(結果集為一行),或 List<類型>(結果集為多行)
  4. 對插入,修改,刪除這樣的更新操作來說,返回的值都是 int,表示更新成功的數量,所以不用指定 resultMap 。
  5. 傳入數據可以在 sql 語句中使用 #{方法參數名} 的方式獲取。

單元測試

可以在Spring中方便的使用JUnit來完成單元測試,在src/test/java下,創建一個單元測試類
//指定為Spring環境中的單元測試
@RunWith(SpringRunner.class)
//指定為SpringBoot環境的單元測試,Application為啟動類
@SpringBootTest(classes = Application.class)
//使用事務,在SpringBoot的單元測試中會自動回滾
@Transactional
public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void selectByIdTest(){User user = userMapper.selectById(1);System.out.println(user);}
}

執行結果:
在這里插入圖片描述

多個方法參數(模糊匹配)

當接收多個方法參數時,xml 映射文件中的 sql 配置不能再使用 parameterType 屬性,需要在方法參
數上使用 @Param(“參數的名稱”) ,之后在 sql 中使用 #{參數的名稱} 的方式來替換占位符。

@Mapper//啟動時會掃描該注解的接口,動態生成代理類
@Component
public interface UserMapper {User selectById(Integer id);int insert(User user);List<User> selectLike(@Param("username") String username,@Param("password") String password);
}

User.xml映射文件的配置

    <select id="selectLike" resultMap="BaseResultMap">select * from user whereusername like #{username} and  password like #{password}</select>

單元測試類1
例如這里模糊匹配username為“a”開頭的,password為“1”開頭的

    @Testpublic void selectLikeTest(){String username = "a%";String password = "1%";List<User> users = userMapper.selectLike(username,password);System.out.println(users);}

運行結果
在這里插入圖片描述
在這里插入圖片描述

#{參數} vs ${參數}

例如上述示例,假如我們模糊查詢出來的數據想讓它進行降序排序,那么我們要怎么做呢?

對于 #{參數} 的使用來說,如果參數是字符串,在替換占位符時,會在 sql 語句中加上單引號。如果是不能使用單引號的字符串,例如 sql 語句是 order by 字段 {傳入參數} ,此時 {傳入參數} 就需要使用 ${傳入參數} 這樣的占位符,替換時不會帶上單引號。

示例:在以上模糊查詢語句中,加上根據文章標題排序的功能,要求是根據方法參數傳入的字符串 asc 或 desc 來排序

  1. 首先將UserMapper接口方法調整為
@Mapper//啟動時會掃描該注解的接口,動態生成代理類
@Component
public interface UserMapper {User selectById(Integer id);int insert(User user);List<User> selectLike(@Param("username") String username,@Param("password") String password,@Param("orderBy") String orderBy);
}
  1. 然后再將UserMapper.xml調整為:
    <select id="selectLike" resultMap="BaseResultMap">select * from user whereusername like #{username} and  password like #{password}order by password ${orderBy}</select>
  1. 然后在調整單元測試代碼
    @Testpublic void selectLikeTest(){String username = "a%";String password = "1%";List<User> users = userMapper.selectLike(username,password,"desc");System.out.println(users);}
}

插入時獲取自增主鍵

在之前插入數據時,如果是自增主鍵,插入后無法獲取到。此時需要在 Mybatis 映射文件中,insert標簽配置如下屬性

  • useGeneratedKeys:這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由數據庫內部生成的主鍵(比如:像 MySQL 和 SQL Server 這樣的關系型數據庫管理系統的自動遞增字段),默認值:false。
  • keyColumn:設置生成鍵值在表中的列名,在某些數據庫(像 PostgreSQL)中,當主鍵列不是表中的第一列的時候,是必須設置的。如果生成列不止一個,可以用逗號分隔多個屬性名稱。
  • keyProperty:指定能夠唯一識別對象的屬性,MyBatis 會使用 getGeneratedKeys 的返回值或insert 語句的 selectKey 子元素設置它的值,默認值:未設置( unset )。如果生成列不止一個,可以用逗號分隔多個屬性名稱。
    如:我們將插入的數據使用id進行自增
    <insert id="insert" useGeneratedKeys="true" keyProperty="id">insert into user(username,password,nickname,sex,birthday,head)values (#{username},#{password},#{nickname},#{sex},#{birthday},#{head})</insert>

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/120730.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息