1. 程式人生 > >4、SpringBoot+Mybatis多表操作以及增刪改查

4、SpringBoot+Mybatis多表操作以及增刪改查

Mybatis整合成功之後,接下來了解一下增刪改查的配置以及多表操作,先從增刪改查開始

為了方便後面的多表操作,現在針對資料表的配置我這裡全部在xml中配置(暫時不用註解的方式了),先看一下目前的工程結構(注意包名)
這裡寫圖片描述
首先為了瞭解增刪改查的操作,我這裡將針對資料庫中的一個文章表進行操作,文章表結構如下:
這裡寫圖片描述
sql語句

CREATE TABLE `diary` (
  `_id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `content` varchar(255) DEFAULT
NULL, `pub_time` datetime DEFAULT NULL, `user_id` int(11) NOT NULL DEFAULT '1', PRIMARY KEY (`_id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;

編寫文章操作Mapper類

package com.example.demo.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import
com.example.demo.bean.Diary; @Mapper public interface DiaryMapper { /** * 獲取文章內容 * * @param id * 文章id * @return */ public Diary getDiaryById(@Param("id") Integer id); /** * 獲取文章內容 * * @param id * 文章id * @return
*/
public Diary getDiaryById2(@Param("id") Integer id); /** * 獲取所有文章 * * @return */ public List<Diary> getAllDiary(); /** * 新增文章 */ public Integer addDiary(Diary d); /** * 更新文章 * * @param d */ public Integer updateDiary(Diary d); /** * 刪除文章 * @param id * @return */ public Integer deleteDiary(@Param("id") Integer id); }

查詢部分比較複雜,可以後面再看,先搞定簡單的

編寫結果對映檔案(xml)

在src/main/resource/com/example/demo/mapper/下建立對映檔案,這裡我直接用操作介面類名首字母小寫來作為檔名,diaryMapper .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.demo.mapper.DiaryMapper">

    <update id="updateDiary" parameterType="com.example.demo.bean.Diary">
        update diary set
        title=#{title},content=#{content},pub_time=#{pubTime}
        where _id=#{id}
    </update>

    <delete id="deleteDiary" parameterType="int">
        delete from diary where
        _id=#{id}
    </delete>
    <insert id="addDiary" useGeneratedKeys="true" keyProperty="id"
        parameterType="com.example.demo.bean.Diary">
        insert into diary(title,content,pub_time,user_id)
        values(#{title},#{content},#{pubTime},#{userId})
    </insert>
    ...先省略查詢部分...
</mapper>

首先mapper其實描述的是一個操作介面,如這裡就是描述著com.example.demo.mapper.DiaryMapper這個介面,namespace屬性直接用包名.類名錶示即可

namespace="com.example.demo.mapper.DiaryMapper"

下面其他Mapper介面也一樣,分別對應一個mapper xml檔案即可

這裡標籤都比較簡單,從標籤名就可以看出來具體的操作了(這不是廢話嘛…),接著主要看一下標籤內的屬性:

id:可以理解為對應Java檔案中的方法名
parameterType:可以理解為該方法的引數型別,無引數可以不寫

標籤括起來的就是sql語句,其中需要引用方法引數時可以使用#{引數名}
來引用,如Java中的方法為:

public Integer deleteDiary(@Param("id") Integer mId);

這裡用@Param(“id”)標註了引數mId,因此如果要在sql中引用mId的值則可以直接用#{id}

delete from diary where _id=#{id}

這裡插入資料的方法是Diary文章物件:

public Integer addDiary(Diary d);

預設情況下,引數是物件時在寫sql語句時可以直接用物件的屬性作為引數

insert into diary(title,content,pub_time,user_id) values(#{title},#{content},#{pubTime},#{userId})

注意:增刪改的結果可以返回一個int型別,一般操作成功會大於0,否則會返回0

運用

package com.example.demo.controller;

import java.sql.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.example.demo.bean.Diary;
import com.example.demo.bean.User;
import com.example.demo.mapper.DiaryMapper;

@RestController
public class DiaryMappingController {
    @Autowired
    DiaryMapper diaryMapper;

    ...省略其他...

    @RequestMapping("/add_diary")
    public String addDiary(String title, String content, int userId) {
        Diary d = new Diary(title,content,new Date(System.currentTimeMillis()),userId);
        int row = diaryMapper.addDiary(d);
        if (row > 0) {
            return "success";
        } else {
            return "fail";
        }
    }
}

關於查詢以及多表查詢

為了體現多表查詢的環境,這裡在資料庫中新增了使用者表、標籤表、文章標籤對應表

--使用者表(一個文章由一個使用者釋出)
CREATE TABLE `users` (
  `_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `psw` varchar(255) NOT NULL,
  `sex` varchar(2) DEFAULT NULL,
  `sign` varchar(255) DEFAULT NULL,
  `photo` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT '0',
  PRIMARY KEY (`_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

--標籤表
CREATE TABLE `tags` (
  `_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `creator` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

--文章標籤對應表(一個文章可以有多個標籤)
CREATE TABLE `diary_tags` (
  `diary_id` int(11) NOT NULL,
  `tag_id` int(11) NOT NULL,
  `extras` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

同時針對這些資料在Java中也定義了相應的型別來接收

User.java描述使用者型別,表示文章釋出者資訊

package com.example.demo.bean;

public class User {
    private int id;
    private String name;
    private String sex;
    private String sign;
    private String photo;
    private int age;
    ...省略getter/setter...
}

Tag.java標籤型別,表示文章所在的標籤

package com.example.demo.bean;

/**
 * 標籤
 * @author Administrator
 *
 */
public class Tag {
    private int id;
    private String name;
    ...省略getter/setter...
}

Diary.java文章型別,描述了文章資訊以及作者、所處的標籤等

package com.example.demo.bean;

import java.sql.Date;
import java.util.List;

public class Diary {
    private int id;
    private String title;
    private String content;
    private Date pubTime;
    private int userId;
    private User user; //作者資訊
    private List<Tag> tags; //所處的標籤,一個文章可以屬於不同的標籤
    ...省略getter/setter...
    public Diary(String title, String content, Date pubTime, int userId) {
        this.title = title;
        this.content = content;
        this.pubTime = pubTime;
        this.userId = userId;
    }
    public Diary() {
    }
}

針對上面這個複雜的結構(文章中有一個作者資訊,同時有多個標籤資訊),如果要找出一個文章的完整資訊,那麼需要通過文章表中的user_id欄位到users表中查詢使用者資訊,同時還需要通過文章表的id到diary_tags表中找到所關聯的標籤(找到標籤id)然後再從tags表中獲取標籤列表。因此查詢的mapper配置如下

...省略前面的增刪改的配置...
<resultMap type="com.example.demo.bean.Diary" id="DiaryMap">
        <id property="id" column="_id" />
        <result property="title" column="title" />
        <result property="content" column="content" />
        <result property="pubTime" column="pub_time" javaType="java.sql.Date" />
        <association property="user" column="user_id"
            javaType="com.example.demo.bean.User">
            <id property="id" column="uId" />
            <result property="name" column="name" />
            <result property="sex" column="sex" />
            <result property="sign" column="sign" />
            <result property="photo" column="photo" />
            <result property="age" column="age" />
        </association>
        <collection property="tags" ofType="com.example.demo.bean.Tags"
            column="_id" select="com.example.demo.mapper.TagMapper.getTagsByDiaryId">
        </collection>
    </resultMap>

    <select id="getDiaryById" parameterType="int" resultMap="DiaryMap">
        select
        d._id,d.title,d.content,d.pub_time,d.user_id,u._id as
        uId,u.name,u.sex,u.sign,u.photo,u.age
        from diary d left join users u on
        d.user_id=u._id where d._id=#{id}
    </select>

    <select id="getAllDiary" resultMap="DiaryMap">
        select
        d._id,d.title,d.content,d.pub_time,d.user_id,u._id as
        uId,u.name,u.sex,u.sign,u.photo,u.age
        from diary d left join users u on
        d.user_id=u._id
    </select>

    <resultMap type="com.example.demo.bean.Diary" id="DiaryMap2">
        <id property="id" column="_id" />
        <result property="title" column="title" />
        <result property="content" column="content" />
        <result property="pubTime" column="pub_time" javaType="java.sql.Date" />
        <result property="userId" column="user_id" />
        <association property="user" column="user_id"
            javaType="com.example.demo.bean.User" select="com.example.demo.mapper.UserMapper.getUserById">
        </association>
        <collection property="tags" ofType="com.example.demo.bean.Tags"
            column="_id" select="com.example.demo.mapper.TagMapper.getTagsByDiaryId">
        </collection>
    </resultMap>

    <select id="getDiaryById2" parameterType="int" resultMap="DiaryMap2">
        select
        * from diary where _id=#{id}
    </select>

resultMap標籤配置的是查詢結果,type表示結果返回型別,id則表示該結果處理的一個獨一無二名稱而已
resultMap中的屬性

id標籤:主鍵對映
result標籤:普通屬性的對映
association標籤:關聯其他查詢一個物件的對映,如當前環境的作者資訊
collection標籤:關聯其他查詢的集合,如當前環境的標籤列表
標籤上的屬性
property表示Java物件中的屬性名
column表示對應的查詢結果中資料庫欄位名
select表示該結果的其他查詢方法(子查詢)

對映結果的關聯是有select標籤中的resultMap屬性來關聯的,該屬性值對應一個resultMap標籤的id
對應關係如下:
這裡寫圖片描述

其他類以及對映檔案的情況
UserMapper.java處理使用者表的使用者資訊操作類,這裡練習的時候也可以全部寫到同一個類中,現在分開主要是為了後面新增方法的需要

package com.example.demo.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.example.demo.bean.User;

@Mapper
public interface UserMapper {

    /**
     * 根據id獲取使用者資訊
     * @param id
     * @return
     */
    public User getUserById(@Param("id") int id);
}

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.example.demo.mapper.UserMapper">
    <resultMap type="com.example.demo.bean.User" id="UserMap">
        <id property="id" column="_id" />
        <result property="name" column="name" />
        <result property="sex" column="sex" />
        <result property="sign" column="sign" />
        <result property="photo" column="photo" />
        <result property="age" column="age" />
    </resultMap>
    <select id="getUserById" parameterType="int" resultMap="UserMap">
        select * from users where _id=#{id}
    </select>
</mapper>

TagMapper.java

package com.example.demo.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.example.demo.bean.Tag;

@Mapper
public interface TagMapper {

    /**
     * 根據文章id獲取標籤列表 
     * @param diaryId
     * @return
     */
    public List<Tag> getTagsByDiaryId(@Param("d_id") int diaryId);
}

tagMapper.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.demo.mapper.TagMapper">

    <resultMap type="com.example.demo.bean.Tag" id="TagMap">
        <id property="id" column="_id" />
        <result property="name" column="name" />
    </resultMap>

    <select id="getTagsByDiaryId" parameterType="int" resultMap="TagMap">
        select * from tags where _id in (select tag_id from diary_tags where diary_id=#{d_id})
    </select>
</mapper>

測試

這裡寫圖片描述

[附]

MyBatis傳入多個引數的問題

針對多個引數的情況,parameterType可以不用指定

1、可以直接使用#{引數下標}的方式訪問

public List<XXXBean> getXXXBeanList(String xxId, String xxCode);  

<select id="getXXXBeanList" resultType="XXBean">
  select t.* from tableName where id = #{0} and name = #{1}  
</select>  

2、之際在方法引數中使用@Parm宣告各個引數的別名

public AddrInfo getAddrInfo(@Param("corpId")int corpId, @Param("addrId")int addrId);

<select id="getAddrInfo"  resultMap="com.xxx.xxx.AddrInfo">
       SELECT * FROM addr_info 
    where addr_id=#{addrId} and corp_id=#{corpId}
</select>

3、封裝List

public List<XXXBean> getXXXBeanList(List<String> list);  

<select id="getXXXBeanList" resultType="XXBean">
  select 欄位... from XXX where id in
  <foreach item="item" index="index" collection="list" open="(" separator="," close=")">  
    #{item}  
  </foreach>  
</select>  

foreach 最後的效果是select 欄位... from XXX where id in ('1','2','3','4') 

4、使用Map攜帶多個引數

public List<XXXBean> getXXXBeanList(HashMap map);  

<select id="getXXXBeanList" parameterType="hashmap" resultType="XXBean">
  select 欄位... from XXX where id=#{xxId} code = #{xxCode}  
</select>  

其中hashmap是mybatis自己配置好的直接使用就行。map中key的名字是那個就在#{}使用那個