欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java開發(fā)可離不開的@Mapper注解舉例詳解

 更新時(shí)間:2025年05月12日 10:13:15   作者:潛意識(shí)Java  
@Mapper 是 Mybatis 的注解,和Spring沒(méi)有關(guān)系,這篇文章主要介紹了Java中@Mapper注解的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

最近在學(xué) Java 編程的時(shí)候,碰到的一個(gè)超級(jí)厲害的 “小助手”,叫 @Mapper 注解。你們知道我平時(shí)搗鼓那些項(xiàng)目的時(shí)候,和數(shù)據(jù)庫(kù)打交道那叫一個(gè)頭疼,各種復(fù)雜的操作,寫得代碼又臭又長(zhǎng)。但自從我用上了 @Mapper 注解,哎呀媽呀,就像給我的編程之路開了掛,代碼變得簡(jiǎn)潔明了,開發(fā)效率蹭蹭地往上漲,整個(gè)人都輕松多了。而且我跟你們說(shuō),我去實(shí)習(xí)的時(shí)候發(fā)現(xiàn),還有了解行業(yè)信息的時(shí)候,那些大公司、小公司,大部分搞 Java 開發(fā)的項(xiàng)目里都在用這個(gè)注解,要是咱掌握了,不管是以后找工作,還是在公司里想要升職加薪,那都更有優(yōu)勢(shì),就好像握住了一把開啟職場(chǎng)大門的金鑰匙,所以大家可得跟著我好好學(xué)學(xué)。

啥是 @Mapper,給家人講明白

(一)通俗解釋

咱先通俗地講講 @Mapper 注解是啥。你們就把它想象成一個(gè)超級(jí)快遞員,咱們寫的 Java 代碼呢,就像是一個(gè)個(gè)寄件人和收件人,數(shù)據(jù)庫(kù)呢,就是那個(gè)大倉(cāng)庫(kù)。這個(gè) @Mapper 注解快遞員,就在 Java 代碼和數(shù)據(jù)庫(kù)之間跑來(lái)跑去,傳遞數(shù)據(jù)。比如說(shuō),咱們要往數(shù)據(jù)庫(kù)里存?zhèn)€新用戶的信息,或者從數(shù)據(jù)庫(kù)里把某個(gè)用戶的資料找出來(lái),只要給這個(gè)快遞員下達(dá)指令,也就是在代碼里用好 @Mapper 注解,它就能麻溜地把數(shù)據(jù)存儲(chǔ)、查詢這些事兒給辦好,讓咱們不用操心那些復(fù)雜的底層操作,輕松實(shí)現(xiàn)咱們想要的功能,是不是很神奇?

(二)專業(yè)剖析

再深入一點(diǎn),從專業(yè)角度來(lái)說(shuō),@Mapper 注解在 MyBatis 框架里可是個(gè)關(guān)鍵角色。MyBatis 是啥呢?它是一個(gè)超好用的持久層框架,能幫咱們把 Java 程序和數(shù)據(jù)庫(kù)連接得穩(wěn)穩(wěn)當(dāng)當(dāng)。而 @Mapper 注解呢,就是在這個(gè)連接過(guò)程中起重要作用。它讓咱們可以通過(guò)定義接口,在接口里寫各種方法,這些方法呢,又能和咱們寫在 XML 文件里,或者直接用注解寫的 SQL 語(yǔ)句一一對(duì)應(yīng)起來(lái),實(shí)現(xiàn)精準(zhǔn)的數(shù)據(jù)庫(kù)交互。比如說(shuō),咱們?cè)诮涌诶锒x一個(gè)查找用戶的方法,然后用 @Mapper 注解標(biāo)記這個(gè)接口,再配上對(duì)應(yīng)的 SQL 語(yǔ)句,當(dāng)咱們?cè)?Java 代碼里調(diào)用這個(gè)接口方法的時(shí)候,MyBatis 就知道要去數(shù)據(jù)庫(kù)里執(zhí)行哪條 SQL 語(yǔ)句,把咱們想要的數(shù)據(jù)找回來(lái),是不是覺(jué)得這背后的設(shè)計(jì)很精妙?

動(dòng)手實(shí)操,代碼搞起

(一)環(huán)境搭建準(zhǔn)備

光說(shuō)不練假把式,咱們現(xiàn)在就動(dòng)手實(shí)操起來(lái)。第一步,得搭建開發(fā)環(huán)境,就像蓋房子得先打地基一樣。咱們先創(chuàng)建一個(gè) Maven 項(xiàng)目,要是不知道 Maven 是啥,它就像是一個(gè)貼心的管家,幫咱們把項(xiàng)目需要的各種庫(kù)文件都管得井井有條。在咱們常用的開發(fā)工具里,像 Intellij IDEA,打開之后,按照向?qū)б徊揭徊絹?lái),先填好項(xiàng)目的基本信息,比如 “Group”(一般是公司域名倒著寫,咱們自己練手就隨便填個(gè),像 “com.example”)、“Artifact”(項(xiàng)目名,自己起個(gè)喜歡的就行,像 “demo-project”)。然后,在項(xiàng)目的 pom.xml 文件里,得添加 MyBatis 以及咱們要連接的數(shù)據(jù)庫(kù)驅(qū)動(dòng)依賴。比如說(shuō),如果咱們連接 MySQL 數(shù)據(jù)庫(kù),就得加上這些:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>

這里的 “org.mybatis.spring.boot:mybatis-spring-boot-starter” 就是 MyBatis 在 Spring Boot 項(xiàng)目里的啟動(dòng)器,它把 MyBatis 相關(guān)的東西都整合好了,方便咱們使用;“mysql:mysql-connector-java” 就是連接 MySQL 的驅(qū)動(dòng)。把這些依賴加好,咱們的開發(fā)環(huán)境就算是搭好了,就可以開始下一步啦。

(二)定義實(shí)體類

環(huán)境搭好了,接下來(lái)咱們定義實(shí)體類。以用戶信息為例,咱們?cè)陧?xiàng)目的 “com.example.entity” 目錄下(要是沒(méi)有這個(gè)目錄,就新建一個(gè)),創(chuàng)建一個(gè) User 實(shí)體類,代碼如下:

package com.example.entity;

public class User {
    private Long id;
    // 用戶ID,每個(gè)用戶獨(dú)一無(wú)二的標(biāo)識(shí)
    private String name;
    // 用戶姓名
    private String email;
    // 用戶郵箱

    // 這里得生成get、set方法,方便MyBatis存取數(shù)據(jù)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

這個(gè) User 實(shí)體類就像是一個(gè)裝用戶信息的小盒子,里面的屬性對(duì)應(yīng)著數(shù)據(jù)庫(kù)里用戶表的字段,通過(guò) get、set 方法,MyBatis 就能方便地把數(shù)據(jù)取出來(lái)放進(jìn)去,是不是很好理解?

(三)創(chuàng)建 Mapper 接口

有了實(shí)體類,咱們接著創(chuàng)建 Mapper 接口。在 “com.example.mapper” 目錄下(同樣,沒(méi)有就新建),創(chuàng)建一個(gè) UserMapper 接口,代碼如下:

package com.example.mapper;

import com.example.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserMapper {
    @Insert("INSERT INTO user (name, email) VALUES (#{name}, #{email})")
    void insertUser(User user);

    @Delete("DELETE FROM user WHERE id = #{id}")
    void deleteUserById(Long id);

    @Update("UPDATE user SET name = #{name}, email = #{email} WHERE id = #{id}")
    void updateUser(User user);

    @Select("SELECT * FROM user WHERE id = #{id}")
    User selectUserById(Long id);

    @Select("SELECT * FROM user")
    List<User> selectAllUsers();
}

這里的 @Mapper 注解就像給這個(gè)接口貼上了一個(gè)特殊的標(biāo)簽,告訴 MyBatis 這個(gè)接口很重要,要重點(diǎn)關(guān)注。接口里的每個(gè)方法,都對(duì)應(yīng)著一條 SQL 操作,像插入用戶信息、刪除用戶、更新用戶資料、根據(jù) ID 查找用戶、查找所有用戶,咱們都用對(duì)應(yīng)的 @Insert、@Delete、@Update、@Select 注解把 SQL 語(yǔ)句寫在方法上,而且注意看,這些 SQL 語(yǔ)句里的 #{參數(shù)名},就能自動(dòng)把咱們傳入的 User 實(shí)體類里的對(duì)應(yīng)屬性值取出來(lái),用到 SQL 語(yǔ)句里,是不是超級(jí)智能?

(四)編寫 SQL 語(yǔ)句

剛才咱們?cè)?Mapper 接口里已經(jīng)寫了一些簡(jiǎn)單的 SQL 語(yǔ)句,不過(guò)有時(shí)候,咱們的需求會(huì)更復(fù)雜一點(diǎn)。比如說(shuō),咱們要根據(jù)用戶的姓名和郵箱模糊查詢用戶,這時(shí)候就可以用動(dòng)態(tài) SQL。在 UserMapper 接口里,咱們?cè)偌右粋€(gè)方法:

@Select("<script>" +
            "SELECT * FROM user " +
            "<where>" +
                "<if test='name!= null'>" +
                    "AND name LIKE '%${name}%'" +
                "</if>" +
                "<if test='email!= null'>" +
                    "AND email LIKE '%${email}%'" +
                "</if>" +
            "</where>" +
        "</script>")
List<User> selectUsersByNameAndEmail(User user);

這里用了<if>標(biāo)簽來(lái)判斷傳入的用戶姓名和郵箱是不是為空,如果不為空,就拼接到 SQL 語(yǔ)句里,實(shí)現(xiàn)模糊查詢,是不是很靈活?而且注意,這里用的是參數(shù)名,它和參數(shù)名有點(diǎn)不一樣,{參數(shù)名} 是直接把參數(shù)值拼接到 SQL 語(yǔ)句里,適合這種模糊查詢的場(chǎng)景,不過(guò)要注意防止 SQL 注入哦,咱們后面再詳細(xì)說(shuō)。

(五)配置文件完善

代碼寫得差不多了,咱們還得完善配置文件。在 Spring Boot 項(xiàng)目里,一般是在 application.properties 或者 application.xml 文件里設(shè)置數(shù)據(jù)庫(kù)連接信息。比如說(shuō),在 application.properties 文件里,咱們得寫上這些:

spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

這里的 “spring.datasource.url” 就是數(shù)據(jù)庫(kù)的連接地址,“localhost” 表示本地?cái)?shù)據(jù)庫(kù),“3306” 是 MySQL 的默認(rèn)端口,“mydb” 是數(shù)據(jù)庫(kù)名,后面的參數(shù) “useSSL=false” 是說(shuō)不用 SSL 加密連接(在本地測(cè)試可以這樣,正式環(huán)境可能需要根據(jù)情況調(diào)整),“serverTimezone=UTC” 是設(shè)置時(shí)區(qū),避免時(shí)間上的一些問(wèn)題;“spring.datasource.username” 和 “spring.datasource.password” 就是登錄數(shù)據(jù)庫(kù)的用戶名和密碼,這得根據(jù)咱們自己安裝數(shù)據(jù)庫(kù)時(shí)設(shè)置的來(lái)填;“spring.datasource.driver-class-name” 就是指定數(shù)據(jù)庫(kù)驅(qū)動(dòng)類,這里是 MySQL 的驅(qū)動(dòng)。把這些配置寫好,就像給咱們的程序指明了數(shù)據(jù)倉(cāng)庫(kù)的位置,它就能順利找到數(shù)據(jù)庫(kù),開始干活啦。

(六)測(cè)試驗(yàn)證功能

最后,咱們得測(cè)試驗(yàn)證一下咱們寫的代碼是不是好使。咱們?cè)陧?xiàng)目的測(cè)試類里,比如說(shuō) “com.example.test” 目錄下(沒(méi)有就新建),創(chuàng)建一個(gè) UserMapperTest 類,代碼如下:

package com.example.test;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.example.entity.User;
import com.example.mapper.UserMapper;

import java.util.List;

@SpringBootTest
public class UserMapperTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void testInsertUser() {
        User user = new User();
        user.setName("張三");
        user.setEmail("zhangsan@example.com");
        userMapper.insertUser(user);
    }

    @Test
    public void testSelectUserById() {
        Long id = 1L;
        User user = userMapper.selectUserById(id);
        assert user!= null;
        System.out.println("用戶姓名:" + user.getName() + ", 郵箱:" + user.getEmail());
    }

    @Test
    public void testSelectAllUsers() {
        List<User> userList = userMapper.selectAllUsers();
        for (User user : userList) {
            System.out.println("用戶姓名:" + user.getName() + ", 郵箱:" + user.getEmail());
        }
    }
}

這里用了 Spring Boot 的測(cè)試框架,通過(guò) @Autowired 注解把咱們之前寫的 UserMapper 接口注入進(jìn)來(lái),然后在各個(gè)測(cè)試方法里,分別調(diào)用插入用戶、根據(jù) ID 查找用戶、查找所有用戶的方法,用斷言來(lái)驗(yàn)證結(jié)果,比如說(shuō)查找用戶的時(shí)候,斷言找到的用戶不為空,這樣就能確保咱們的代碼能正常工作,就像考試后核對(duì)答案一樣,心里踏實(shí)多了。

深入探索,高級(jí)玩法揭秘

(一)動(dòng)態(tài) SQL 語(yǔ)句運(yùn)用

剛才咱們簡(jiǎn)單介紹了動(dòng)態(tài) SQL,現(xiàn)在深入講講。除了剛才用的<if>標(biāo)簽,還有<choose>、<where>等標(biāo)簽也很常用。比如說(shuō),咱們要實(shí)現(xiàn)一個(gè)復(fù)雜的查詢,根據(jù)不同的條件查找用戶,有時(shí)候按姓名查,有時(shí)候按郵箱查,有時(shí)候按年齡范圍查,這時(shí)候就可以用<choose>標(biāo)簽,代碼如下:

@Select("<script>" +
            "SELECT * FROM user " +
            "<where>" +
                "<choose>" +
                    "<when test='name!= null'>" +
                        "AND name LIKE '%${name}%'" +
                    "</when>" +
                    "<when test='email!= null'>" +
                        "AND email LIKE '%${email}%'" +
                    "</when>" +
                    "<when test='age!= null'>" +
                        "AND age BETWEEN #{age.start} AND #{age.end}" +
                    "</when>" +
                "</choose>" +
            "</where>" +
        "</script>")
List<User> selectUsersByCondition(User user, AgeRange age);

這里假設(shè)咱們還有一個(gè) AgeRange 類,用來(lái)表示年齡范圍,通過(guò)<choose>標(biāo)簽,咱們可以根據(jù)傳入的不同條件,靈活地生成不同的 SQL 語(yǔ)句,滿足各種復(fù)雜的查詢需求,是不是很強(qiáng)大?

(二)關(guān)聯(lián)查詢與結(jié)果映射

再來(lái)講講關(guān)聯(lián)查詢,比如說(shuō)咱們的項(xiàng)目里有用戶表和訂單表,一個(gè)用戶可能有多個(gè)訂單,咱們有時(shí)候需要查詢用戶及其訂單信息,這時(shí)候就可以用 @Results、@ResultMap 注解。首先,咱們得在 UserMapper 接口里定義一個(gè)方法:

@Select("SELECT u.*, o.* FROM user u LEFT JOIN order o ON u.id = o.user_id")
@Results(id = "userWithOrdersResult", value = {
    @Result(property = "id", column = "u.id"),
    @Result(property = "name", column = "u.name"),
    @Result(property = "email", column = "u.email"),
    @Result(property = "orders", javaType = List.class, many = @Many(select = "com.example.mapper.OrderMapper.selectOrdersByUserId")),
})
User getUserWithOrders(Long id);

這里的 @Select 注解寫了關(guān)聯(lián)查詢的 SQL 語(yǔ)句,通過(guò) LEFT JOIN 把用戶表和訂單表連接起來(lái)。@Results 注解用來(lái)定義結(jié)果映射,把查詢結(jié)果正確地映射到 User 實(shí)體類和它關(guān)聯(lián)的訂單列表上,其中 @Result 注解對(duì)應(yīng)著每個(gè)屬性的映射,對(duì)于訂單列表,咱們用 @Result 的 many 屬性,指定了一個(gè)子查詢,通過(guò)調(diào)用 OrderMapper 接口的 selectOrdersByUserId 方法,獲取用戶的訂單信息,是不是很巧妙?

常見問(wèn)題排雷

(一)注解失效問(wèn)題

在使用 @Mapper 注解的時(shí)候,有時(shí)候會(huì)遇到注解失效的問(wèn)題。比如說(shuō),咱們明明寫了 @Mapper 注解,但是 MyBatis 好像沒(méi)看到一樣,接口方法調(diào)用就報(bào)錯(cuò)。這可能是因?yàn)樵蹅儧](méi)有正確配置 MyBatis,讓它掃描到咱們的 Mapper 接口。在 Spring Boot 項(xiàng)目里,如果咱們用的是注解驅(qū)動(dòng)的方式,得確保在啟動(dòng)類上加上 @MapperScan 注解,指定 Mapper 接口所在的包,比如:

package com.example;

import org.springframework.boot.SpringBootApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.MapperScan;

@SpringBootApplication
@MapperScan("com.example.mapper")
public class DemoApplication {
    public static void main(String[] args) {
        SpringBootApplication.run(DemoApplication.class, args);
    }
}

這里的 @MapperScan ("com.example.mapper") 就告訴 Spring Boot,去 “com.example.mapper” 這個(gè)包下掃描所有的 Mapper 接口,這樣就能解決注解失效的問(wèn)題啦。

(二)SQL 語(yǔ)法錯(cuò)誤排查

還有一個(gè)常見的問(wèn)題就是 SQL 語(yǔ)法錯(cuò)誤。咱們寫 SQL 語(yǔ)句的時(shí)候,不小心寫錯(cuò)了,比如說(shuō)少寫了個(gè)引號(hào),或者關(guān)鍵字拼錯(cuò)了,這時(shí)候程序運(yùn)行就會(huì)報(bào)錯(cuò)。遇到這種情況,咱們得學(xué)會(huì)從報(bào)錯(cuò)信息里快速定位問(wèn)題。一般來(lái)說(shuō),MyBatis 會(huì)給出比較詳細(xì)的報(bào)錯(cuò)信息,告訴咱們是哪個(gè) SQL 語(yǔ)句出錯(cuò)了,在哪個(gè)位置,咱們根據(jù)這些信息,仔細(xì)檢查 SQL 語(yǔ)句,就能找到錯(cuò)誤并改正。比如說(shuō),報(bào)錯(cuò)信息里說(shuō) “near 'FROM user WHERE id = #{id}': syntax error”,咱們就知道是在 “FROM user WHERE id = #{id}” 這個(gè)語(yǔ)句里有語(yǔ)法錯(cuò)誤,可能是少了個(gè)空格,或者關(guān)鍵字寫錯(cuò)了,仔細(xì)一看,原來(lái)是 “DELETE” 寫成了 “DELET”,改正之后就沒(méi)問(wèn)題啦。

總結(jié)

到此這篇關(guān)于Java中@Mapper注解舉例詳解的文章就介紹到這了,更多相關(guān)Java的@Mapper注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論