MyBatis框架與參數(shù)案例解析
MyBatis框架概述
MyBatis 是一款基于 Java 語言的半自動(dòng)化對(duì)象關(guān)系映射(ORM)持久層框架,其核心目標(biāo)是對(duì) JDBC API 進(jìn)行抽象與封裝,在保留開發(fā)者對(duì) SQL 語句精細(xì)控制能力的前提下,它有效解決了傳統(tǒng) JDBC 開發(fā)中存在的流程冗余、業(yè)務(wù)邏輯與數(shù)據(jù)訪問邏輯耦合、數(shù)據(jù)與對(duì)象映射復(fù)雜等問題。該框架最初由 Apache 軟件基金會(huì)以“iBatis”為名開源,2010 年遷移至 Google Code 平臺(tái)并正式更名為“MyBatis”,目前由 GitHub 社區(qū)主導(dǎo)維護(hù),是 Java 生態(tài)中應(yīng)用最廣泛的持久層框架之一。
MyBatis 可通過 XML 或注解等主流方式,對(duì)需執(zhí)行的 SQL 語句及對(duì)應(yīng)的執(zhí)行規(guī)則進(jìn)行配置??蚣軙?huì)將 Java 對(duì)象中的數(shù)據(jù)與 SQL 語句中的動(dòng)態(tài)參數(shù)進(jìn)行綁定,進(jìn)而執(zhí)行 SQL 操作,SQL 執(zhí)行完成后,MyBatis 會(huì)自動(dòng)將數(shù)據(jù)庫(kù)返回的結(jié)果集映射為 Java 對(duì)象并返回。
持久層是軟件架構(gòu)中負(fù)責(zé)數(shù)據(jù)持久化的核心層級(jí),主要功能是將內(nèi)存中的臨時(shí)數(shù)據(jù)持久化到存儲(chǔ)介質(zhì)(如數(shù)據(jù)庫(kù)),并能從存儲(chǔ)介質(zhì)中恢復(fù)數(shù)據(jù)至內(nèi)存。作為連接業(yè)務(wù)邏輯層與數(shù)據(jù)存儲(chǔ)層的橋梁,它可避免業(yè)務(wù)邏輯層直接與數(shù)據(jù)庫(kù)交互導(dǎo)致的系統(tǒng)耦合度升高問題。
MyBatis案例與詳解
創(chuàng)建數(shù)據(jù)庫(kù)和表結(jié)構(gòu)
create database mybatis_db; use mybatis_db; ? CREATE TABLE `user` ( `id` int(11) NOT NULL auto_increment, `username` varchar(32) NOT NULL COMMENT '用戶名稱', `birthday` datetime default NULL COMMENT '生日', `sex` char(1) default NULL COMMENT '性別', `address` varchar(256) default NULL COMMENT '地址', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ? insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (1,'老、王','2018-02-27 17:47:08','男','北京'),(2,'熊大','2018-03-02 15:09:37','女','上海'),(3,'熊二','2018-03-04 11:34:34','女','深圳'),(4,'光頭強(qiáng)','2018-03-04 12:04:06','男','廣州');
創(chuàng)建 maven Java工程
引入坐標(biāo)依賴,MyBatis的3.4.5的版本坐標(biāo),MySQL驅(qū)動(dòng)的jar包5.1.6版本,Junit單元測(cè)試的jar包,引入log4j的jar包1.2.12版本(需要引入log4j.properties的配置文件)
<dependencies>
<!--mybatis核心包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql驅(qū)動(dòng)包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- 單元測(cè)試 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>log4j.properties配置文件

編寫User的實(shí)現(xiàn)類,屬性盡量使用包裝類型
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}編寫UserMapper的接口和方法
import java.util.List;
public interface UserMapper {
//查詢所有的用戶
public List<User> findAll();
}在resources目錄下,創(chuàng)建mapper文件夾,編寫UserMapper.xml配置文件,導(dǎo)入約束文件
<?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.qcby.mapper.UserMapper">
<select id="findAll" resultType="com.qcby.domain.User">
select * from user;
</select>
</mapper>通過namespace關(guān)聯(lián)com.qcby.mapper.UserMapper接口,為接口中的findAll()方法綁定一條SQL語句,并指定查詢結(jié)果會(huì)被映射為User對(duì)象。
編寫主配置文件,在resources目錄下創(chuàng)建SqlMapConfig.xml配置文件,導(dǎo)入對(duì)應(yīng)的約束,編寫主配置文件。
<?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>
<environments default="mysql">
<environment id="mysql">
<!-- 配置事務(wù)管理類型 -->
<transactionManager type="JDBC"/>
<!-- 配置是否需要使用連接池,POOLED使用,UNPOOLED不使用 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 加載映射的配置文件 -->
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>編寫測(cè)試代碼
import com.qcby.domain.User;
import com.qcby.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class UserTest {
/**
* 測(cè)試查詢所有的方法
* @throws Exception
*/
@Test
public void testFindAll() throws Exception {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> list = mapper.findAll();
for (User user : list) {
System.out.println(user);
}
session.close();
in.close();
}
@Test
public void run() throws Exception {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = factory.openSession();
List<User> list = session.selectList("com.qcby.mapper.UserMapper.findAll");
for (User user : list) {
System.out.println(user);
}
session.close();
inputStream.close();
}
}實(shí)現(xiàn)效果:
執(zhí)行testFindAll()

testFindAll () 函數(shù)通過 MyBatis 的接口代理方式實(shí)現(xiàn)數(shù)據(jù)庫(kù)查詢
首先利用 MyBatis 的 Resources 工具類加載主配置文件 SqlMapConfig.xml 的輸入流,再通過 SqlSessionFactoryBuilder 構(gòu)建出 SqlSessionFactory 會(huì)話工廠,隨后打開 SqlSession 會(huì)話,調(diào)用 SqlSession 的 getMapper (UserMapper.class) 獲取 UserMapper 接口的代理對(duì)象,調(diào)用代理對(duì)象的 findAll () 方法時(shí),MyBatis 會(huì)自動(dòng)匹配 UserMapper.xml 中對(duì)應(yīng) namespace 和 id 的 SQL 語句執(zhí)行查詢,得到 User 對(duì)象集合并打印,最后釋放資源。這種方式面向接口編程,支持編譯期類型檢查,是 MyBatis 官方推薦的規(guī)范用法。
執(zhí)行run()

run () 函數(shù)采用 MyBatis 傳統(tǒng)的命名空間 + ID 方式執(zhí)行查詢
流程上同樣先加載配置文件、創(chuàng)建 SqlSessionFactory 并打開 SqlSession,但執(zhí)行查詢時(shí)直接調(diào)用 SqlSession 的 selectList () 方法,通過字符串 “com.qcby.mapper.UserMapper.findAll” 定位目標(biāo) SQL,得到 User 對(duì)象集合并打印,最后釋放資源。
實(shí)現(xiàn)增刪改查
UserMapper接口代碼
import com.qcby.domain.User;
import java.util.List;
public interface UserMapper {
public List<User> findAll();
public User findById(Integer userId);
public void insert(User user);
public void update(User user);
public void delete(Integer userId);
public List<User> findByName1(String username);
public List<User> findByName2(String username);
public Integer findByCount();
}UserMapper.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.qcby.mapper.UserMapper">
<select id="findAll" resultType="com.qcby.domain.User">
select * from user;
</select>
<!-- 通過id查詢,SQL語句使用#{}占位符的名稱,名稱可以任意,僅限于基本數(shù)據(jù)類型和String類型
-->
<select id="findById" resultType="com.qcby.domain.User" parameterType="int">
select * from user where id = #{id};
</select>
<!--保存操作-->
<insert id="insert" parameterType="com.qcby.domain.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select last_insert_id();
</selectKey>
insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 修改 -->
<update id="update" parameterType="com.qcby.domain.User">
update user set username = #{username},birthday = #{birthday},sex = #{sex},address=#{address} where id = #{id}
</update>
<!-- 刪除 -->
<delete id="delete" parameterType="Integer">
delete from user where id = #{id}
</delete>
<!-- 模糊查詢1 -->
<select id="findByName1" resultType="com.qcby.domain.User" parameterType="string">
select * from user where username like #{username}
</select>
<!-- 模糊查詢2,固定寫法 -->
<select id="findByName2" resultType="com.qcby.domain.User" parameterType="string">
select * from user where username like '%${value}%'
</select>
<!-- 具體函數(shù)的查詢 -->
<select id="findByCount" resultType="int">
select count(*) from user
</select>
</mapper>UserTest 代碼
package com.qcby;
import com.qcby.domain.User;
import com.qcby.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class UserTest1 {
private InputStream in;
private SqlSession session;
private UserMapper mapper;
@Before
public void init() throws Exception {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
session = factory.openSession();
mapper = session.getMapper(UserMapper.class);
}
@After
public void destory() throws IOException {
in.close();
session.close();
}
@Test
public void testFindAll() throws Exception {
List<User> list = mapper.findAll();
// 遍歷
for (User user : list) {
System.out.println(user);
}
in.close();
}
@Test
public void testFindById() throws Exception {
User user = mapper.findById(41);
System.out.println(user);
in.close();
}
@Test
public void testInsert() throws Exception {
User user = new User();
user.setUsername("美美");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("順義");
mapper.insert(user);
session.commit();
System.out.println(user.getId());
}
@Test
public void testUpdate() throws Exception {
User user = mapper.findById(4);
user.setUsername("小鳳");
mapper.update(user);
session.commit();
}
@Test
public void testDelete() throws Exception {
mapper.delete(2);
session.commit();
}
// 第一種
@Test
public void testFindByName() throws Exception {
List<User> list = mapper.findByName1("%王%");
for (User user : list) {
System.out.println(user);
}
}
// 第二種
@Test
public void testFindByName1() throws Exception {
List<User> list = mapper.findByName2("王");
for (User user : list) {
System.out.println(user);
}
}
@Test
public void testFindByCount() throws Exception {
Integer count = mapper.findByCount();
System.out.println("總記錄數(shù):"+count);
}
}實(shí)現(xiàn)效果:
執(zhí)行 testInsert() 方法

該方法執(zhí)行的是這條SQL語句
<insert id="insert" parameterType="com.qcby.domain.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select last_insert_id();
</selectKey>
insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
</insert>其中selectKey標(biāo)簽用于獲取插入記錄后自動(dòng)生成的主鍵值,keyProperty=“id” 表示將查詢到的主鍵值賦值給傳入U(xiǎn)ser對(duì)象的id屬性,order=“AFTER” 指定該查詢?cè)趇nsert語句執(zhí)行之后執(zhí)行(自增長(zhǎng)主鍵是在記錄插入后生成的),resultType=“java.lang.Integer” 聲明查詢返回的主鍵類型為Integer,內(nèi)部 SQL select last_insert_id(); 是 MySQL 的內(nèi)置函數(shù),用于獲取當(dāng)前會(huì)話中最后一次插入操作生成的自增長(zhǎng)主鍵值。MyBatis 通過 <selectKey> 獲取到主鍵值后,會(huì)主動(dòng)調(diào)用對(duì)象的setId()方法賦值,而由于對(duì)象是引用傳遞,外部的user對(duì)象就能通過getId()獲取到這個(gè)值。
session.commit() 的核心功能是提交事務(wù),確保數(shù)據(jù)庫(kù)修改持久化。在 MyBatis 中,默認(rèn)采用 JDBC 事務(wù)管理機(jī)制(對(duì)應(yīng)配置中的 <transactionManager type="JDBC"/>),通過 factory.openSession() 獲取的 SqlSession 默認(rèn)開啟事務(wù)且不自動(dòng)提交。當(dāng)執(zhí)行 mapper.insert(user) 時(shí),插入操作僅暫存于事務(wù)中,直到調(diào)用 session.commit() 才會(huì)將數(shù)據(jù)永久寫入數(shù)據(jù)庫(kù),完成數(shù)據(jù)持久化,若未顯式調(diào)用 commit(),SqlSession 關(guān)閉時(shí)會(huì)自動(dòng)執(zhí)行事務(wù)回滾,所有未提交的修改都將被撤銷,數(shù)據(jù)庫(kù)不會(huì)保留新增數(shù)據(jù)。
模糊查詢符號(hào)使用的區(qū)別
#{}本質(zhì)是MyBatis對(duì)JDBC中PreparedStatement占位符機(jī)制的封裝,會(huì)被解析為SQL中的?,后續(xù)通過PreparedStatement的setXxx()方法將參數(shù)值安全傳入。它具備自動(dòng)類型轉(zhuǎn)換能力,可根據(jù)Java參數(shù)類型(如String、Integer)與數(shù)據(jù)庫(kù)字段的JDBC類型(如VARCHAR、INT)完成適配,無需手動(dòng)處理兼容問題。同時(shí),因參數(shù)以純數(shù)據(jù)形式通過預(yù)編譯占位符傳入,特殊字符會(huì)被轉(zhuǎn)義,能有效抵御SQL注入攻擊。在參數(shù)接收上,#{}可處理簡(jiǎn)單類型值(如int、String)與POJO對(duì)象的屬性值,當(dāng)parameterType為單個(gè)簡(jiǎn)單類型時(shí),其括號(hào)內(nèi)的名稱可任意填寫,MyBatis均能正確識(shí)別。${}采用直接字符串替換的處理邏輯,不會(huì)生成SQL占位符,而是將參數(shù)值直接拼接至SQL語句中,且不進(jìn)行任何JDBC類型轉(zhuǎn)換,無論Java參數(shù)是int型還是String型,最終都會(huì)以字符串形式拼入。它同樣支持接收簡(jiǎn)單類型值與POJO屬性值,但在參數(shù)規(guī)則上與#{}存在差異:當(dāng)parameterType為單個(gè)簡(jiǎn)單類型時(shí),${}括號(hào)內(nèi)必須填寫“value”,否則MyBatis無法識(shí)別對(duì)應(yīng)參數(shù),這是其與#{}在單個(gè)簡(jiǎn)單類型參數(shù)處理上的核心區(qū)別。
實(shí)現(xiàn)效果:


MyBatis參數(shù)詳解
- parameterType
parameterType 是 MyBatis 中用于指定 SQL 語句接收參數(shù)類型的配置屬性。它主要作用是告訴 MyBatis 傳入 SQL 的參數(shù)數(shù)據(jù)類型,以便框架正確解析和處理參數(shù)。該屬性的值可以是基本數(shù)據(jù)類型(如 int、String)、包裝類(如 Integer、Long)、自定義實(shí)體類、Map 等集合類型。在 Mapper 接口方法中,當(dāng)參數(shù)為單個(gè)簡(jiǎn)單類型時(shí),parameterType的取值可以是Java 類型的全限定名(如java.lang.Integer),也可以是 MyBatis 內(nèi)置的類型別名(如int);但對(duì)于復(fù)雜類型(如自定義對(duì)象),parameterType需指定該類的全限定名或自定義別名。 - resultType
resultType 用于指定 SQL 查詢語句返回結(jié)果的類型,它告訴 MyBatis查詢結(jié)果需要被映射成什么類型的對(duì)象,MyBatis 會(huì)根據(jù)該類型,將 SQL 執(zhí)行后的結(jié)果集自動(dòng)封裝為對(duì)應(yīng)的對(duì)象或數(shù)據(jù)結(jié)構(gòu),它適用于結(jié)果集字段與 Java 對(duì)象屬性名完全一致的場(chǎng)景。MyBatis 會(huì)根據(jù) resultType 定義的類型,自動(dòng)將查詢結(jié)果集中的列值映射到對(duì)應(yīng)類型的對(duì)象屬性中。其取值可以是基本數(shù)據(jù)類型(如 String、int)、自定義實(shí)體類、List 等集合類型(此時(shí)需指定集合中元素的類型)。 - resultMap
resultMap 是 MyBatis 中用于自定義結(jié)果映射規(guī)則的配置標(biāo)簽,適用于結(jié)果集字段與 Java 對(duì)象屬性名不一致,或存在復(fù)雜關(guān)聯(lián)關(guān)系(如一對(duì)一、一對(duì)多)的場(chǎng)景。它通過(主鍵映射)和(普通字段映射)標(biāo)簽,手動(dòng)指定數(shù)據(jù)庫(kù)列名與 Java 對(duì)象屬性名的對(duì)應(yīng)關(guān)系,解決字段名與屬性名不匹配的問題。此外,resultMap 還支持通過(一對(duì)一關(guān)聯(lián))和(一對(duì)多關(guān)聯(lián))標(biāo)簽處理關(guān)聯(lián)查詢,實(shí)現(xiàn)復(fù)雜對(duì)象的嵌套映射。與 resultType 相比,resultMap 的優(yōu)勢(shì)在于靈活性和可復(fù)用性,一旦定義可在多個(gè) SQL 語句中引用,尤其適合處理復(fù)雜的數(shù)據(jù)映射場(chǎng)景。
類型別名定義
MyBatis 內(nèi)置了一些常用類型的別名(如int對(duì)應(yīng)Integer、string對(duì)應(yīng)String、list對(duì)應(yīng)ArrayList等),開發(fā)者無需手動(dòng)定義即可直接使用。
也可以進(jìn)行別名的注冊(cè),在SqlMapConfig.xml配置文件中設(shè)置
<!-- 定義別名 --> <typeAliases> <!-- 把com.qcby.domain.User使用user別名來顯示 <typeAlias type="com.qcby.domain.User" alias="user"/> --> <!-- 針對(duì)com.qcby.domain包下的所有的類,都可以使用當(dāng)前的類名做為別名 --> <package name="com.qcby.domain"/> </typeAliases>
在 MyBatis 的核心配置文件中,使用<typeAlias>標(biāo)簽單獨(dú)指定某個(gè)類的別名,或通過<package>標(biāo)簽批量掃描某個(gè)包下的所有類,此時(shí) MyBatis 會(huì)默認(rèn)以類名(首字母大小寫均可,不區(qū)分大小寫)作為別名,例如掃描com.qcby.domain包后,User類可直接用user或User作為別名
<select id="findAll" resultType="user"> select * from user </select>
定義后的類型別名可直接在 Mapper 配置文件的parameterType、resultType等屬性中使用,其值不再是原來的全路徑了
到此這篇關(guān)于MyBatis框架與參數(shù)案例解析的文章就介紹到這了,更多相關(guān)MyBatis框架與參數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 中實(shí)現(xiàn)隨機(jī)無重復(fù)數(shù)字的方法
為了更好地理解這個(gè)題意,我們先來看下具體內(nèi)容:生成一個(gè)1-100 的隨機(jī)數(shù)組,但數(shù)組中的數(shù)字不能重復(fù),即位置是隨機(jī)的,但數(shù)組元素不能重復(fù)2013-03-03
一文詳解為什么越來越多項(xiàng)目開始從JDK?8升級(jí)到JDK?21
從JDK 8升級(jí)到JDK 21,不僅是版本的迭代,更是開發(fā)理念與技術(shù)棧的全面革新,這篇文章主要介紹了為什么越來越多項(xiàng)目開始從JDK?8升級(jí)到JDK?21的相關(guān)資料,需要的朋友可以參考下2026-01-01
JAVA使用JDBC技術(shù)操作SqlServer數(shù)據(jù)庫(kù)實(shí)例代碼
本篇文章主要介紹了JAVA使用JDBC技術(shù)操作SqlServer數(shù)據(jù)庫(kù)實(shí)例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01
SpringMVC文件上傳原理及實(shí)現(xiàn)過程解析
這篇文章主要介紹了SpringMVC文件上傳原理及實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07

