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>

测试

这里写图片描述

源码:https://github.com/huajianzh/spring/tree/master/springdemo

[附]

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的名字是那个就在#{}使用那个

展开阅读全文

没有更多推荐了,返回首页