MyBatis與其使用方法示例詳解
ORM
在講解Mybatis之前,我們需了解一個概念ORM(Object-Relational Mapping)對象關系映射,其是數(shù)據(jù)庫與Java對象進行映射的一個技術.通過使用ORM,我們可以不用編寫負責的Sql語句,而是通過操作對象來實現(xiàn)增刪改查操作
缺優(yōu)分析
- 優(yōu)點
- 提高開發(fā)效率,減少代碼的重復性和維護成本
- 增加代碼的可讀性,降低復雜度
- 對數(shù)據(jù)庫查詢的細節(jié)進行抽象,隱藏了sql語句
- 缺點
- 在進行多表聯(lián)查時,或存在where條件時,ORM語句會變得復雜
MyBatis
- mybatis是一個支持自定義SQL的持久層框架,通過XML文件來實現(xiàn)SQL配置和數(shù)據(jù)映射,MyBatis允許開發(fā)者手動編寫SQL語句,提高靈活性
Mybatis通過
mapper
文件,將sql查詢和Java對象綁定到一起,簡化了JDBC代碼的編寫,手動設置參數(shù),獲取結果集的工作
MyBatis的工作流程
- 其分為以下幾步
MyBatis的基本使用
環(huán)境準備
- 引入依賴包:
<!--springboot的mybatis > <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> <!-- MySQL 連接器 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency>
- 創(chuàng)建mybatis配置文件(
mybatis-config.xml
)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- mybatis環(huán)境 --> <environments default="mysql"> <environment id="mysql"> <!-- 配置事務的類型 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置數(shù)據(jù)源(連接池) --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/數(shù)據(jù)庫名稱?userSSL=false&serverTimezone=Asia/Shanghai"/> <property name="username" value="帳號"/> <property name="password" value="密碼"/> </dataSource> </environment> </environments> <!-- mybatis映射配置位置 --> <!-- 按模塊映射不同的配置文件,讓配置文件看起來更簡潔 --> <mappers> <mapper resource="映射配置文件全路徑"></mapper> </mappers> </configuration>
- springboot中的
application.yml
mybatis: # mapper配置文件 mapper-locations: classpath:mapper/*.xml # resultType別名,沒有這個配置resultType包名要寫全,配置后只要寫類名 type-aliases-package: com.mashang.xiaomistore.domain configuration: #下劃線自動轉駝峰 map-underscore-to-camel-case: true
- 創(chuàng)建Mapper映射文件
<?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.company.mapper.StudentMapper"> <select id="queryAll" resultType="com.company.entity.Student"> SELECT * FROM student </select> </mapper>
- 創(chuàng)建Mapper接口:
public interface StudentMapper { List<Student> queryAll(); }
MyBatis日志配置
- 引入SpringBoot中的log4j
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j2 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> <version>3.4.3</version> </dependency>
- 在SpringBoot中在
application.yml
中mybatis
配置項中進行配置
mybatis: configuration: log-impl: org.apache.ibatis.logging.log4j.Log4jImpl
- 配置
log4j.properties
文件
### 設置### log4j.rootLogger = debug,stdout,D,E ### 輸出信息到控制抬 ### log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n ### 輸出DEBUG 級別以上的日志到=D://logs/error.log ### log4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = D://logs/log.log log4j.appender.D.Append = true log4j.appender.D.Threshold = DEBUG log4j.appender.D.layout = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ### 輸出ERROR 級別以上的日志到=D://logs/error.log ### log4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File =D://logs/error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
一個基本的mybatis的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.example.mapper.UserMapper"> <!-- CRUD 配置 --> </mapper>
CURD實現(xiàn)
select查詢
使用<select>
標簽實現(xiàn)基本查詢
<select id ="getUserById" resultType="com.company.domain.entity.User"> SELECT * FORM user </select>
id
:對應Mapper接口中的方法名,必須一致resultType
:指定返回結果映射到哪個Java類傳參
#{}
與${}
的區(qū)別#{}
的特點- 事先進行預編譯:使用
#{}
的參數(shù)會被Mybatis當作JDBC中的?
占位符 - 防止sql注入:由于會事先進行預編譯,Mybatis能夠防止Sql注入
- 類型轉換:會根據(jù)參數(shù)類型進行適當?shù)念愋娃D換
- 事先進行預編譯:使用
${}
的特點- 字符串拼接:
&{}
直接將字符串進行替換,相當于在Sql中直接拼接傳入的參數(shù) - 存在sql注入的風險:沒有預編譯,會引發(fā)sql注入問題
- 字符串拼接:
多條件查詢
<select id="getUserByNameAndAge" resultType="User"> SELECT * FROM user WHERE name = #{name} AND age = #{age} </select>
模糊查詢
<select> SELECT * FROM user WHERE name LIKE CONCAT('%', #{name}, '%') </select>
- 使用LIKE關鍵字和CONCAT()函數(shù)進行查詢
insert插入
使用<insert>
標簽實現(xiàn)基本插入操作
<insert id="insertUser" parameterType="User"> INSERT INTO user(name, age) VALUES (#{name}, #{age}) </insert>
parameterType
:表示入?yún)㈩愋?/li>
實現(xiàn)回填自增主鍵
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user (name, age) VALUES (#{name}, #{age}) </insert>
- 使用
userGeneratedKeys
和keyProperty
實現(xiàn) userGeneratedKeys
:表示是否啟動自增keyProperty
:表示將生成的主鍵賦值給哪個java對象的哪個屬性如user.id
update更新
使用<update>
標簽實現(xiàn)基本更新
<update id="updateUser" parameterType="User"> UPDATE user SET name=#{name}, age =#{age} WHERE id = #{id} </update>
delete刪除
使用<delete>
標簽基本查詢
<delete id="deleteUserById" parameterType="Integer"> DELETE FROM user WHERE id = #{id} </delete>
傳參方式
多參數(shù)傳參(使用@Param)
<select id="getUserByNameAndAge" resultType="User"> SELECT * FROM user WHERE name = #{name} AND age = #{age} </select>
User getUserByNameAndAge( @Param("name") String name, @Param("age") Integer age);
- 當方法有多個參數(shù)時,使用
@Param
注解明確參數(shù)名 - Mapper接口
對象參數(shù)
<insert id="insertUser" parameterType="User"> INSERT INTO user (name, age) VALUES (#{name}, #{age}) </insert>
void insertUser(User user);
- 當參數(shù)為一個Java對象時,MyBatis自動將對象屬性映射到Sql語句中的占位符
#{name}
對應user.name,#{age}
對應user.age- Mapper接口
Map參數(shù)
<select id="getUserByMap" resultType="User"> SELECT * FROM user WHERE name = #{name} AND age = #{age} </select>
User getUserByMap(Map<String, Object> params);
- 通過Map傳遞多個參數(shù)或動態(tài)參數(shù)
- Mapper接口
集合/數(shù)組參數(shù)
<select id="getUsersByIds" resultType="User"> SELECT * FROM user WHERE id IN <foreach collection="ids" item="id" open="(" separator="," close=")"> #{id} </foreach> </select>
List<User> getUsersByIds(@Param("ids") List<Integer> ids);
- 適用于批量查詢,比如WHERE id IN (…)
<foreach>
是動態(tài)sql中的知識點等下會系統(tǒng)講解- Mapper接口
動態(tài)sql
與標簽
<where>
:生成WHERE子句,并自動判斷去掉開頭多余的AND/OR
關鍵字,使sql更簡潔<if>
:用于判斷傳參條件,根據(jù)條件決定是否拼接某段SQL語句,適用于傳參條件不固定,只有在滿足條件時接入某個子串
<select id="getUserByCondition" resultType="User"> SELECT * FROM user <where> <if test="name != null and name != ''"> AND name LIKE CONCAT('%', #{name}, '%') </if> <if test="age != null"> AND age = #{age} </if> </where> </select>
- 當
name
為非空,會添加AND name LIKE CONCAT('%', #{name}, '%')
當age
為非空時會添加AND age = #{age}
- 結合標簽使用,能自動處理首個AND,使得SQL語句正確
- 其作用在于動態(tài)拼接SQL片段前添加或去除特點字符,比如前綴,后綴,以及多余的分隔符如
,
- 常用于INSERT和UPDATE語句,避免出現(xiàn)多余逗號
INSERT語句
<insert id="insertUserSelective" parameterType="User"> INSERT INTO user <trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null">name,</if> <if test="age != null">age,</if> <if test="email != null">email,</if> </trim> VALUES <trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null">#{name},</if> <if test="age != null">#{age},</if> <if test="email != null">#{email},</if> </trim> </insert>
- 標簽包裹字段列表和對應值部分
suffixOverrides=”,”
表示自動去除多余的逗號,確保sql語法正確
UPDATE語句
<set>
標簽是<trim>
的特性化
<update id="updateUserDynamic" parameterType="User"> UPDATE user <set> <if test="name != null">name = #{name},</if> <if test="age != null">age = #{age},</if> <if test="email != null">email = #{email},</if> </set> WHERE id = #{id} </update>
<set>
標簽內部原理類似<trim>
,會自動去除多余逗號<foreach>
用于遍歷集合,數(shù)組和Map,常用于批量操作或動態(tài)生成IN子句- 其主要屬性
- collection:集合或數(shù)組名稱(可用
@Param()
指定對應名稱,默認為list
或array
) - item:循環(huán)時每個元素的別名
- open:循環(huán)生成sql片段的前綴
- separator:循環(huán)時的分隔符
- close:循環(huán)生成sql片段的后綴
- collection:集合或數(shù)組名稱(可用
<select id="getUsersByIds" resultType="User"> SELECT * FROM user <where> <if test="ids != null"> AND id IN <foreach collection="ids" item="id" open="(" separator="," close=")"> #{id} </foreach> </if> </where> </select>
- 當ids不為null時,進入
<if test="ids != null">
生成的sql片段為SELECT * FROM AND WHERE id IN(#{id},#{id},…)
- 其中標簽遍歷集合ids,用逗號進行分隔,并在開頭添加
(
括號,結尾添加)
括號 - 最終標簽會去除第一個AND,使sql合法
SELECT * FROM id WHERE IN(#{id},#{id},…)
MyBatis的映射
基本映射
用于單一的字段對應
假設有一個user表,其中有字段id,name,age
其在Java中有個簡單的對應類User,其屬性分別也是id,name,age
那么在Mapper.xml進行select查詢時
SELECT id, name, age FROM user WHERE id = #{id}
MyBatis會將查詢的結果中每一列值自動賦值給User對象中相同的屬性
- 數(shù)據(jù)庫列表的id→User對象的id
- 數(shù)據(jù)庫列表的name→User對象的name
- 數(shù)據(jù)庫列表的age→User對象的age
這樣可能就會出現(xiàn)一種情況,數(shù)據(jù)庫列表的列名與對象的屬性名不一致,通常使用開啟駝峰轉換來解決→在application.yml
的mybatis配置中添加如下配置:
mybatis: map-underscore-to-camel-case: true
一對一映射
當查詢中需要查詢一個對象時
- 現(xiàn)假設,數(shù)據(jù)庫有兩張表一個user(用戶)表,另一個user_detail(用戶詳細信息)表,在Java中我們可以創(chuàng)建兩個類User和UserDetail類
- 然后再創(chuàng)建一個UserVo類,其中包含User的屬性和一個UserDatail對象
public class User { private Integer id; private String name; private Integer age; } public class UserDetail { private Integer detailId; private String address; private String phone; } public class UserVo { private Integer id; private String name; private Integer age; private UserDetail userDetail; // 一對一關系:一個用戶對應一份詳細信息 }
XML配置如下:
<resultMap id="userVoMap" type="com.example.UserVo"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="age" column="age"/> <!-- 一對一映射 --> <association property="userDetail" javaType="com.example.UserDetail"> <id property="detailId" column="detail_id"/> <result property="address" column="address"/> <result property="phone" column="phone"/> </association> </resultMap> <select id="getUserVoById" resultMap="userVoMap" parameterType="int"> SELECT u.id, u.name, u.age, ud.detail_id, ud.address, ud.phone FROM user u LEFT JOIN user_detail ud ON u.id = ud.user_id WHERE u.id = #{id} </select>
<resultMap>
標簽- 用于定義一組映射規(guī)則,將查詢的結果轉換為一個指定類型的Java對象
- 屬性
- id:為該映射指定一個唯一標識,供其在XML中引用使用,如
<resultMap id="userResultMap" type="com.example.User">
- type:指定映射結果對應的Java類型(對象的全路徑)
- id:為該映射指定一個唯一標識,供其在XML中引用使用,如
<result>
標簽- 用于將數(shù)據(jù)庫列映射到Java對象的屬性,在
<resultMap>
中使用 - 屬性
- property:Java對象中的屬性名稱,如
<result property="userName" column="user_name"/>
其表示將查詢到的user_name列的值賦值給userName屬性 - cloumn:數(shù)據(jù)庫查詢結果中的列名,如
column="user_name”
表示sql查詢列名為user_name的值
- property:Java對象中的屬性名稱,如
- 用于將數(shù)據(jù)庫列映射到Java對象的屬性,在
<id>
標簽<id>
類似于<result>
主要用于映射主鍵字段- 屬性
- property:與
<result>
相同,映射到Java對象的主鍵屬性 - column:對應數(shù)據(jù)庫中的主鍵列名
- property:與
<association>
標簽- 表示一個一對一關連
- 當查詢到結果時,MyBatis會將用戶的基本字段
{id,name,age}
直接映射到UserVo中,同時將詳細信息{detail_id,address,phone}
封裝為一個UserDetail對象,并賦值到UserVo的userDetail
對象中
一對多映射
提供用于有列表對象的查詢
現(xiàn)假設一個老師(Teacher)類和一個學生(student)類,一個老師可以對應多個學生,在Java中我們可以設計Teacher類, 使用List屬性來存放老師的所有學生
public class Teacher { private Integer id; private String teacherName; private Integer age; private List<Student> students; // 一對多關系:一個老師對應多個學生 } public class Student { private Integer id; private String name; private Integer age; }
XML配置如下:
<resultMap id="teacherMap" type="com.example.Teacher"> <id property="id" column="teacher_id"/> <result property="teacherName" column="teacher_name"/> <result property="age" column="teacher_age"/> <!-- 一對多映射 --> <collection property="students" ofType="com.example.Student"> <id property="id" column="student_id"/> <result property="name" column="student_name"/> <result property="age" column="student_age"/> </collection> </resultMap> <select id="getTeacherWithStudents" resultMap="teacherMap" parameterType="int"> SELECT t.id as teacher_id, t.teacher_name, t.age as teacher_age, s.id as student_id, s.name as student_name, s.age as student_age FROM teacher t LEFT JOIN student s ON t.id = s.teacher_id WHERE t.id = #{id} </select>
<collection>
標簽:用于表示一對多關系,把查詢結果中的學生記錄封裝成一個列表,并賦值到Teacher對象中的student
屬性
到此這篇關于MyBatis與其使用方法講解的文章就介紹到這了,更多相關MyBatis使用方法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
java模板引擎Thymeleaf和前端vue的區(qū)別及說明
這篇文章主要介紹了java模板引擎Thymeleaf和前端vue的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11基于Jpa中ManyToMany和OneToMany的雙向控制
這篇文章主要介紹了Jpa中ManyToMany和OneToMany的雙向控制,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12百度翻譯API使用詳細教程(前端vue+后端springboot)
這篇文章主要給大家介紹了關于百度翻譯API使用的相關資料,百度翻譯API是百度面向開發(fā)者推出的免費翻譯服務開放接口,任何第三方應用或網(wǎng)站都可以通過使用百度翻譯API為用戶提供實時優(yōu)質的多語言翻譯服務,需要的朋友可以參考下2024-02-02詳解Java刪除Map中元素java.util.ConcurrentModificationException”異常解決
這篇文章主要介紹了詳解Java刪除Map中元素java.util.ConcurrentModificationException”異常解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01Java 添加、修改、讀取、復制、刪除Excel批注的實現(xiàn)
這篇文章主要介紹了Java 添加、修改、讀取、復制、刪除Excel批注的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02Java如何接收并解析HL7協(xié)議數(shù)據(jù)
文章主要介紹了HL7協(xié)議及其在醫(yī)療行業(yè)中的應用,詳細描述了如何配置環(huán)境、接收和解析數(shù)據(jù),以及與前端進行交互的實現(xiàn)方法,文章還分享了使用7Edit工具進行調試的經驗,并記錄了一個常見的解析問題及其解決方法2024-12-12java操作(DOM、SAX、JDOM、DOM4J)xml方式的四種比較與詳解
java中四種操作(DOM、SAX、JDOM、DOM4J)xml方式的比較與詳解2008-10-10