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

Java?Mybatis查詢數(shù)據(jù)庫舉例詳解

 更新時間:2023年10月31日 14:54:03   作者:ζ◇十點半就睡覺  
這篇文章主要給大家介紹了關(guān)于Java?Mybatis查詢數(shù)據(jù)庫的相關(guān)資料,在MyBatis中可以使用遞歸查詢實現(xiàn)對數(shù)據(jù)庫中樹形結(jié)構(gòu)數(shù)據(jù)的查詢,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

前言

經(jīng)過前面的學習Spring系列的操作已經(jīng)差不多了,接下來我們繼續(xù)學習更加重要的知識,將前端傳遞的參數(shù)存儲起來,或者查詢數(shù)據(jù)庫里面的數(shù)據(jù)

1. MyBatis 是什么?

MyBatis是款優(yōu)秀的持久層框架,它支持自定義SQL、存儲過程以及高級映射。MyBatis幾乎祛除了所有的JDBC代碼以及設(shè)置參數(shù)和獲取結(jié)果集的操作。MyBatis可以通過簡單的XML或者注解來配置和映射原始類型、接口和Java POJO為數(shù)據(jù)庫中的記錄

簡單來說MyBatis是簡單完成程序和數(shù)據(jù)庫交互的工具,也就是更簡單的操作和讀取數(shù)據(jù)庫的工具

2. 為什么要學習MyBatis?

對于后端程序員來說,程序是由以下兩個程序組成的:

  • 后端程序
  • 數(shù)據(jù)庫

而這兩個重要的組成部分要通訊,就要依靠數(shù)據(jù)庫連接工具,那么數(shù)據(jù)庫連接工具有哪些?比如JDBC還有今天我們要介紹的MyBatis。既然已經(jīng)有了JDBC,為什么還要學習MyBatis?這是因為JDBC操作太繁瑣了,我們來回顧一下JDBC的操作流程:

  • 創(chuàng)建數(shù)據(jù)庫連接池DataSource
  • 通過DataSource獲取數(shù)據(jù)庫連接Connection
  • 編寫要帶?的占位符的SQL語句
  • 通過Connection及SQL創(chuàng)建操作命令對象Statement
  • 替換占位符:指定要替換的數(shù)據(jù)庫字段類型,占位符索引及要替換的值
  • 使用Statement執(zhí)行SQL語句
  • 查詢操作:返回結(jié)果集ResultSet,更新操作:返回更新的數(shù)量
  • 處理結(jié)果集
  • 釋放資源

3. 怎么學MyBatis?

MyBatis的學習只分為兩部分:

  • 配置MyBatis開發(fā)環(huán)境
  • 使用MyBatis模式和語法操作數(shù)據(jù)庫

4. 第一個MyBatis查詢

開始搭建MyBatis之前,我們需要先來看看它在整個框架之中的地位

MyBatis也是一個ORM框架,ORM即對象關(guān)系映射。在面向?qū)ο缶幊陶Z言當中,講關(guān)系型數(shù)據(jù)庫中的數(shù)據(jù)與對象建立起映射關(guān)系,進行自動完成數(shù)據(jù)與對象的相互轉(zhuǎn)換

  • 將輸入數(shù)據(jù)(即傳入對象)+ SQL映射原生SQL
  • 將結(jié)果集映射為返回對象,即輸出對象

ORM把數(shù)據(jù)庫映射為對象:

  • 數(shù)據(jù)表—》 類
  • 記錄—》對象
  • 字段—》對象的屬性

一般的ORM框架,會將數(shù)據(jù)庫模型的每一張表都映射為一個Java類

也就是說使用MyBatis可以像操作對象一樣操作數(shù)據(jù)庫中的表,可以實現(xiàn)對象和數(shù)據(jù)表之間的轉(zhuǎn)換,我們接下來看看MyBatis的使用

4.1 創(chuàng)建數(shù)據(jù)庫和表

使用MyBatis的方式來讀取用戶表當中的所有用戶,我們使用個人博客的數(shù)據(jù)包。

-- 創(chuàng)建數(shù)據(jù)庫
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8mb4;
-- 使?數(shù)據(jù)數(shù)據(jù)
use mycnblog;
-- 創(chuàng)建表[?戶表]
drop table if exists userinfo;
create table userinfo(
                         id int primary key auto_increment,
                         username varchar(100) not null,
                         password varchar(32) not null,
                         photo varchar(500) default '',
                         createtime datetime default now(),
                         updatetime datetime default now(),
                         `state` int default 1
) default charset 'utf8mb4';
-- 創(chuàng)建?章表
drop table if exists articleinfo;
create table articleinfo(
                            id int primary key auto_increment,
                            title varchar(100) not null,
                            content text not null,
                            createtime datetime default now(),
                            updatetime datetime default now(),
                            uid int not null,
                            rcount int not null default 1,
                            `state` int default 1
)default charset 'utf8mb4';
-- 創(chuàng)建視頻表
drop table if exists videoinfo;
create table videoinfo(
                          vid int primary key,
                          `title` varchar(250),
                          `url` varchar(1000),
                          createtime datetime default now(),
                          updatetime datetime default now(),
                          uid int
)default charset 'utf8mb4';
-- 添加?個?戶信息
INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`,
`createtime`, `updatetime`, `state`) VALUES
(1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1)
;
-- ?章添加測試數(shù)據(jù)
insert into articleinfo(title,content,uid)
values('Java','Java正?',1);

-- 添加視頻
insert into videoinfo(vid,title,url,uid) values(1,'java title','http://ww
w.baidu.com',1);

4.2 添加MyBatis框架支持

添加MyBatis框架支持分為兩種情況:一種情況是對之前的Spring項目進行升級,另一種情況是創(chuàng)建一個全新的MyBatis和Spring Boot項目

擴展:在老項目當中快速的添加框架,更簡單的操作是使用EditStarters插件

4.3 配置連接字符串和MyBatis

此步驟需要進行兩項設(shè)置,數(shù)據(jù)庫連接字符串設(shè)置和MyBatis的XML文件配置

4.3.1 配置連接數(shù)據(jù)庫

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8&&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

注意事項:

如果使用mysql-connector-java是5.x之前使用的con.mysql.jdbc.Driver如果大于5.x使用的是com.mysql.cj.jdbc.Driver

配置MyBatis中的XML路徑

MyBatis的XML中保存的是查詢數(shù)據(jù)庫的具體操作的SQL,配置如下:

mybatis:
  mapper-locations: classpath:mybatis/**Mapper.xml

4.4 添加業(yè)務(wù)代碼

下面按照后端開發(fā)的工程思路,也就是下面的流程來實現(xiàn)MyBatis查詢所有用戶的功能:

4.4.1 添加實體類

先添加用戶的實體類:

import lombok.Data;
import java.util.Date;
@Data
public class User {
 private Integer id;
 private String username;
 private String password;
 private String photo;
 private Date createTime;
 private Date updateTime;
}

4.4.2 添加Mapper接口

數(shù)據(jù)持久層的接口定義:

@Mapper
public interface UserMapper {
    public UserInfo getUserById(@Param("id") Integer id);

    public void add(@RequestBody UserInfo userInfo);
}

4.4.3 添加UserMapper.xml

數(shù)據(jù)持久層的實現(xiàn),MyBatis的固定格式:

<?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.demo.mapper.UserMapper">
    <select id="getUserById" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where id = #{id}
    </select>
</mapper>
  • 標簽:需要指定namespace屬性,表示命名空間,值為mapper接口的全限定名,包括包名.類名
  • <select> 標簽:是用來執(zhí)行數(shù)據(jù)庫的查詢操作的

    id:是和interface中定義的方法名稱是一樣的,表示對接口的具體實現(xiàn)方法

    resultType:是返回的數(shù)據(jù)類型,也就是開頭定義的實體類

4.4.4 添加Service

服務(wù)層代碼如下:

@Service
public class UserService {
    @Resource
    private UserMapper userMapper;

    public UserInfo getUserById(Integer id) {
        return userMapper.getUserById(id);
    }
}

4.4.5 添加Controller

控制層的代碼實現(xiàn)如下:

@Controller
@ResponseBody
public class UserController {
    @Resource
    private UserService userService;

    @RequestMapping("/getuserbyid")
    public UserInfo getUserById(Integer id) {
        return userService.getUserById(id);
    }
}

5. 增、刪、改操作

5.1 增加用戶的操作

<insert id="add">
    insert into userinfo(username, password, photo) values (#{username}, #{password}, #{photo})
</insert>
<insert id="getId" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
    insert into userinfo(username, password, photo) values (#{username}, #{password}, #{photo})
</insert>
  • useGeneratedKeys: 這會令MyBatis使用JDBC的getGeneratedKeys 方法取出由數(shù)據(jù)庫內(nèi)部生成的主鍵。(像MySQL和SQL service這樣的關(guān)系型數(shù)據(jù)庫關(guān)系系統(tǒng)自增主鍵)默認值是:false
  • keyColumn: 設(shè)置生成建在表中的列名,在某些數(shù)據(jù)庫當中,當主鍵的列不是第一列的時候,是必須設(shè)置的。如果生成列不止一個,可以用逗號分割各個屬性名稱
  • keyProperty:指定能夠唯一

5.2 刪除用戶的操作

<delete id="del">
    delete from userinfo where id = #{id}
</delete>

5.3 修改用戶操作

<update id="update">
    update userinfo set username = #{name} where id = #{id}
</update>

6. 查詢操作

6.1 單表查詢

controller代碼如下:

@RequestMapping("/getuserbyid")
public UserInfo getUserById(Integer id) {
    return userService.getUserById(id);
}

Mapper.xml實現(xiàn)代碼如下:

<select id="getUserById" resultType="com.example.demo.model.UserInfo">
    select * from userinfo where id = #{id}
</select>

6.1.1 參數(shù)占位符 #{} 和 ${}

  • #{} :預編譯處理
  • ${}:字符直接替換

預編譯處理是指:MyBatis在處理#{}時,會將SQL中的#{}替換為?,使用statement的set方法來賦值。直接替換:是MyBatis在處理 時,就是把 {}時,就是把 時,就是把{}替換成變量的值

6.1.2 $優(yōu)點

使用${}可以實現(xiàn)排序查詢,而是用#{}就不能實現(xiàn)排序查詢,因為當使用#{}查詢時,如果傳遞的值為String則會加引號,就會導致SQL錯誤。

6.1.3 SQL 注入問題

<select id="isLogin" resultType="com.example.demo.model.User">
	select * from userinfo where username='${name}' and password='${pwd}'
</select>

結(jié)論:用于查詢的字段,盡量使用#{}預查詢的方式

6.1.4 like查詢

like使用#{}報錯,這個時候不能使用${},可以考慮使用MySQL內(nèi)置的函數(shù)concat()來處理,實現(xiàn)代碼如下:

<select id="findUserByName3" resultType="com.example.demo.model.User">
    select * from userinfo where username like concat('%',#{username},'%');
</select>

concat可以連接字符。

6.2 多表查詢

如果增、刪、改返回影響的行數(shù),那么在mapper.xml中可以不設(shè)置返回的類型的。但是即使是最簡單的查詢,也要設(shè)置返回類型否則就會出現(xiàn)錯誤。

也就是說**對于<select>查詢標簽,至少存在兩個屬性:

  • id 屬性:用于標識實現(xiàn)接口的那個方法
  • 結(jié)果映射屬性:結(jié)果映射有兩種實現(xiàn)標簽:<resultType<resultMap

6.2.1 返回類型

絕大多數(shù)查詢場景可以使用resultType進行返回,如下代碼所示:

<select id="getNameById" resultType="java.lang.String">
    select username from userinfo where id=#{id}
</select>

它的優(yōu)點就是使用方便、直接定義到某個實體類就可以

6.2.2 返回字典映射:resultMap

resultMap使用場景:

  • 字段名稱和程序中的屬性名稱不相同的情況,可以使用resultMap配置映射
  • 一對一和多對一關(guān)系可以使用resultMap映射并查詢數(shù)據(jù)

字段名和屬性名不同的情況

<resultMap id="BaseMap" type="com.example.demo.model.User">
    <id column="id" property="id"></id>
    <result column="username" property="username"></result>
    <result column="password" property="pwd"></result>
</resultMap>
<select id="getUserById" resultMap="com.example.demo.mapper.UserMapper.BaseMap">
    select * from userinfo where id=#{id}
</select>

6.2.3 多表查詢

在多表查詢的時候,如果使用resultMap標簽,在一個類中包含了另一個對象是查詢不出來包含的對象的。如下圖所示:

此時我們就需要使用特殊手段來實現(xiàn)聯(lián)表查詢了。

6.2.3.1 一對一的映射

一對一映射要使用<association>標簽,具體實現(xiàn)如下所示:一篇文章只能對應(yīng)一個作者

<resultMap id="BaseMap" type="com.example.demo.model.ArticleInfo">
    <id column="id" property="id"></id>
    <result column="title" property="title"></result>
    <result column="content" property="content"></result>
    <result column="createtime" property="createtime"></result>
    <result column="updatetime" property="updatetime"></result>
    <result column="uid" property="uid"></result>
    <result column="rcount" property="rcount"></result>
    <result column="state" property="state"></result>
    <association property="userInfo" resultMap="com.example.demo.mapper.UserMapper.BaseMap" columnPrefix="u_">				</association>
</resultMap>

<select id="getArticleById" resultMap="BaseMap">
    select a.*, u.id u_id, u.username u_username, u.password u_password from articleinfo a left join userinfo u on a.uid = u.id where a.id = #{id}
</select>

以上使用<assciation>標簽,表示一對一的結(jié)果映射:

  • property屬性:指定Article中對應(yīng)的屬性,即用戶
  • resultMap屬性:指定關(guān)聯(lián)的結(jié)果集映射,將基于該映射配置來組織用戶數(shù)據(jù)
  • columnPrefix屬性:綁定一對一對象時,是通過columnPrefix+assoction.result.colmn來映射結(jié)果集字段

注意:columnPrefix屬性不能省略,如果省略當聯(lián)表中有相同的字段,那么會導致查詢出錯

6.2.3.2 一對多的映射

一對多需要使用<collection>標簽,用法和<association>相同,如下所示:

<resultMap id="BaseMap" type="com.example.demo.model.ArticleInfo">
    <id column="id" property="id"></id>
    <result column="title" property="title"></result>
    <result column="content" property="content"></result>
    <result column="createtime" property="createtime"></result>
    <result column="updatetime" property="updatetime"></result>
    <result column="uid" property="uid"></result>
    <result column="rcount" property="rcount"></result>
    <result column="state" property="state"></result>
    <association property="userInfo" resultMap="com.example.demo.mapper.UserMapper.BaseMap" columnPrefix="u_">		    </association>
</resultMap>

<select id="getArticleById" resultMap="BaseMap">
    select a.*, u.id u_id, u.username u_username, u.password u_password from articleinfo a left join userinfo u on a.uid = u.id where a.id = #{id}
</select>

7. 復雜情況

動態(tài)SQL是MyBatis的強大特性之一,能夠完成不同條件下不同的sql拼接

7.1 <if>標簽

在注冊的時候,我們可能遇到這樣一個問題。注冊分為兩個字段:必填字段和非必傳字段,那如果在添加用戶的時候又不確定的字段傳入,程序應(yīng)該如何實現(xiàn)?

這個時候我們就需要使用動態(tài)標簽了。

<insert id="add2">
    insert into userinfo(username, password
    <if test="photo != null">
        ,photo
    </if>) values (#{username}, #{password}
    <if test="photo != null">
        ,#{photo}
    </if>
    );
</insert>

注意test中的,是傳入對象的屬性,不是數(shù)據(jù)庫字段

7.2 <trim>標簽

之前的插入功能,只是有一個字段為可選項,如果所有字段都是非必選項,就需要考慮用標簽結(jié)合標簽,對多個字段都采用動態(tài)生成的方式。

標簽當中有如下屬性:

  • prefix: 表示整個語句塊,以prefix值為前綴
  • suffix:表示整個語句塊,以suffix的值為后綴
  • prefixOverrides:表示整個語句塊要去除的前綴
  • suffixOverrides:表示整個語句塊要去除的后綴

使用方法如下:

<insert id="add3">
    insert into userinfo
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="username != null">
            username,
        </if>
        <if test="password != null">
            password,
        </if>
        <if test="photo != null">
            photo
        </if>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username != null">
                #{username},
            </if>
            <if test="password != null">
                #{password},
            </if>
            <if test="photo != null">
                #{photo}
            </if>
        </trim>
    </trim>
</insert>

以上SQL動態(tài)解析時,會將第一個trim部分如下處理:

  • 基于prefix配置,開始加上(
  • 基于suffix配置,結(jié)束部分加上)
  • 多個if組織的語句都以, 結(jié)尾,在最后拼接好的字符串還會以,結(jié)尾會基于suffixOverrides配置去掉最后一個,
  • if 中的test是傳入對象的屬性

7.3 <where>標簽

傳入對象時,根據(jù)屬性做where條件查詢,用戶對象中屬性不為null,都為查詢條件。

<select id="getUserById" resultMap="BaseMap">
    select * from userinfo
    <where>
        <if test="id != null">
            id = #{id}
        </if>
    </where>
</select>

7.4 <set>標簽

根據(jù)傳入的用戶對象屬性來更新用戶數(shù)據(jù),可以使用標簽來指定動態(tài)內(nèi)容

<update id="updateById" parameterType="org.example.model.User">
    update user
    <set>
        <if test="username != null">
            username=#{username},
        </if>
        <if test="password != null">
            password=#{password},
        </if>
        <if test="nickname != null">
            nickname=#{nickname},
        </if>
        <if test="sex != null">
            sex=#{sex},
        </if>
        <if test="birthday != null">
            birthday=#{birthday},
        </if>
        <if test="head != null">
            head=#{head},
        </if>
        <if test="createTime != null">
            create_time=#{createTime},
        </if>
    </set>
    where id=#{id}
</update>

7.5 <foreach>標簽

對集合進行遍歷時, 可以使用該標簽。<foreach>標簽有以下屬性。

  • collection:綁定方法參數(shù)中的集合,如List、Set、Map或數(shù)組對象
  • item:遍歷時的每一個對象
  • open:語句塊開頭的字符串
  • close:語句塊結(jié)束時的字符串

總結(jié) 

到此這篇關(guān)于Java Mybatis查詢數(shù)據(jù)庫的文章就介紹到這了,更多相關(guān)Java Mybatis查詢數(shù)據(jù)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論