IDEA项目实践——动态SQL、关系映射、注解开发

系列文章目录

IDEA项目实践------创建Java项目以及创建Maven项目案例、使用数据库连接池创建项目简介

IDEWA项目实践------mybatis的一些基本原理以及案例

IDEA项目实践------动态SQL、关系映射、注解开发

IDEA创建项目的操作步骤以及在虚拟机里面创建Scala的项目简单介绍_intellij 创建scala

文章目录

系列文章目录

前言

[一 动态SQL](#一 动态SQL)

[1.1 动态SQL概述](#1.1 动态SQL概述)

[1.2 if元素](#1.2 if元素)

[1.3 where 、set 、trim元素](#1.3 where 、set 、trim元素)

[1.3.1 where元素](#1.3.1 where元素)

[1.3.2 set 元素](#1.3.2 set 元素)

[1.3.3 trim 元素](#1.3.3 trim 元素)

1.元素模拟元素

[2. 元素模拟元素](#2. 元素模拟元素)

[1.4 choose 、when 、 otherwise 元素](#1.4 choose 、when 、 otherwise 元素)

[1.5 foreach元素](#1.5 foreach元素)

foreach标签

[1.6 bind 元素](#1.6 bind 元素)

[二 关系映射](#二 关系映射)

[2.1 关联关系概述](#2.1 关联关系概述)

[2.2 一对一级联查询](#2.2 一对一级联查询)

[2.2.1 准备工作(依赖和工具类)](#2.2.1 准备工作(依赖和工具类))

[2.2.2 创建数据库的表与实体类](#2.2.2 创建数据库的表与实体类)

[2.2.3 编写MyBatis配置文件与数据库配置文件](#2.2.3 编写MyBatis配置文件与数据库配置文件)

[2.2.4 创建Mapper接口与映射文件](#2.2.4 创建Mapper接口与映射文件)

[2.2.5 创建测试类](#2.2.5 创建测试类)

[2.3 一对多级联查询](#2.3 一对多级联查询)

[2.3.1 准备工作(依赖和工具类)](#2.3.1 准备工作(依赖和工具类))

[2.3.2 创建实体类和表](#2.3.2 创建实体类和表)

[2.3.3 编写MyBatis配置文件与数据库配置文件](#2.3.3 编写MyBatis配置文件与数据库配置文件)

[2.3.4 创建Mapper接口与映射文件](#2.3.4 创建Mapper接口与映射文件)

[2.3.5 创建测试类](#2.3.5 创建测试类)

[2.4 多对多级联查询](#2.4 多对多级联查询)

[2.4.1 准备工作(依赖和工具类)](#2.4.1 准备工作(依赖和工具类))

[2.4.2 创建实体类和表](#2.4.2 创建实体类和表)

[2.4.3 编写MyBatis配置文件与数据库配置文件](#2.4.3 编写MyBatis配置文件与数据库配置文件)

[2.4.4 创建Mapper接口与映射文件](#2.4.4 创建Mapper接口与映射文件)

[2.4.5 创建测试类](#2.4.5 创建测试类)

[2.5 三种关联映射总结](#2.5 三种关联映射总结)

[三 注解开发](#三 注解开发)

[3.1 注解开发概述](#3.1 注解开发概述)

[3.2 案例的实现步骤](#3.2 案例的实现步骤)

[3.2.1 导入依赖和工具类](#3.2.1 导入依赖和工具类)

[3.2.2 创建MyBatis配置文件和数据库配置文件](#3.2.2 创建MyBatis配置文件和数据库配置文件)

[3.2.3 创建实体类](#3.2.3 创建实体类)

[3.2.4 创建StudentMapper接口](#3.2.4 创建StudentMapper接口)

[3.2.5 编写测试类](#3.2.5 编写测试类)

总结


前言

本文主要介绍MyBatis当中的动态SQL、关系映射、注解开发,以及相关的案例讲解。

一 动态SQL

动态SQL,即通过MyBatis 提供的各种标签对条件作出判断已实现动态拼接SQL语句。条件判断使用的表达式为OGNL表达式。

在项目开发中,动态SQL可以解决很多不确定因素导致的SQL语句不同的问题。动态SQL可以简单高效的进行编码。

注意事项

在mapper的动态SQL中如出现大于号,小于号,大于等于号,小于等于号,最好将其转换为实体符号,否则,XML可能会出现解析出错问题,特别是小于号 (<),在XML中绝对不能出现 ,否则一定出错

官方文档:mybatis -- MyBatis 3 | 动态 SQL

1.1 动态SQL概述

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

动态SQL是MyBatis提供的拼接SQL语句的强大机制。

元素 说明
<if> 判断某个条件是否符合,符合则拼接此SQL语句
<choose>、<when>、<otherwise> 判断多个条件是否符合,符合则拼接此SQL语句
<where>、<set>、<trim> 限定语句,用于限制SQL语句的格式
<foreach> 循环语句,用于循环拼接SQL语句
<bind> 命名元素,用于创建一个变量,以便后续重复使用

1.2 if元素

不确定多条件查询------ if、where 标签

  • if 标签:条件判断
    • test 属性:逻辑表达式
  • where 标签
    • 作用:
      1. 替换where关键字
      2. 会动态的去掉第一个条件前的 and
      3. 如果所有的参数没有值则不加where关键字
      4. 注意:需要给每个条件前都加上 and 关键字

<if>元素主要用于条件判断,如果此条件成功,则把此元素中的SQL语句拼接。<if>元素常用于where子句中条件的筛选。

示例:

sql 复制代码
select * from tb_user where name = #{name} and age = #{age}

如果name属性与age属性有其中一个为空时,查询语句就会报错,为解决此问题,需要判断name与age属性是否为空,如果为空则不附加对应的筛选条件。利用<if>元素可以判断属性是否为空。

XML 复制代码
<select id="selectUser" resultType="user">
    select * from tb_user where
    <if test="null != name and '' != name">
        name = #{name}
    </if>
    <if test="null != age and '' != age">
        and age = #{age}
    </if>
</select>

使用Junit单元测试,同时通过日志,测试各种情况。

以下为小的模块讲解

此处的if里面的判断条件,可以多写个and,需要在where条件里面补充1=1恒等式解决只输入性别SQL语句错误的情况。

1.3 where 、set 、trim元素

1.3.1 where元素

<where>:当<where>元素中存在内容时,自动拼接"where"字符串,并且将<where>元素中的第一个"and"字符串删除;当<where>元素中没有内容时,将删除<where>元素自身,即不拼接"where"字符串。

XML 复制代码
<select id="selectUser" resultType="user">
     select * from tb_user 
	<where>
		<if test="null != name and '' != name">
			and name = #{name}
		</if>
		<if test="null != age and '' != age">
			and age = #{age}
		</if>
	</where>
</select>

对1.2 里面的if元素那块代码的一种优化方法

1.3.2 set 元素

<set>用于更新操作的SQL语句的拼接。

<set>元素用于更新操作的SQL拼接,当<set>元素中存在内容时,自动拼接"set"字符串,并且将<set>元素中最后的","字符串删除。当<set>元素中没有内容时,<set>元素将会删除自身,即不拼接"set""字符串。此处需要注意的是,当"set"字符串被删除时,SQL语句会报错,此时可以在<set>元素中添加id=#{id}"来保持SQL始终有效。

XML 复制代码
<update id="updateuser" >
       update tb_user 
       <set>
           <if test="null != name and '' != name">
               name = #{name},
           </if>
           <if test="null != age and '' != age">
               age = #{age},
           </if>
       </set>
       where id = #{id}
</update>

两个字段之间使用逗号隔开,判断条件并不是书写的最后一个,通过set动态的删除最后设置的那个逗号。

1.3.3 trim 元素

<trim>元素的使用方法较复杂,拼装SQL语句的灵活性极强,可以模拟<where>、<set>的功能。

1.<trim>元素模拟<set>元素

通过<trim>元素的prefix属性,给需要拼接的SQL添加"set"字符串前缀,通过<trim>元素的suffixOverrides属性,将SQL语句最后的","字符串删除,完成<set>元素功能的模拟。

XML 复制代码
<update id="updateuser" >
    update tb_user
    <trim prefix="set" suffixOverrides=",">
        <if test="null != name and '' != name">
            name = #{name},
        </if>
        <if test="null != age and '' != age">
            age = #{age},
        </if>
    </trim>
    where id = #{id}
</update>

2. <trim>元素模拟<where>元素

通过<trim>元素的prefix属性,为需要拼接的SQL添加"where"字符串前缀,通过<trim>元素的prefixOverrides属性,将SQL前面的"and"字符串删除,完成<where>元素功能的模拟

XML 复制代码
<select id="selectUserTrim" resultType="user">
    select * from tb_user 
    <trim prefixOverrides="and" prefix="where">
        <if test="null != name and '' != name">
            and name = #{name}
        </if>
        <if test="null != age and '' != age">
            and age = #{age}
        </if>
    </trim>
</select>

1.4 choose 、when 、 otherwise 元素

不确定单个条件查询------choose (when, otherwise) 标签

<choose>元素表示选择拼接其中一段代码,其中需要使用<when>元素判断是否拼接此段代码,从上至下,只要有一个<when>元素符合条件,便拼接此段代码,退出<choose>元素;当所有<when>元素都不符合条件时,拼接<otherwise>元素中的代码。

XML 复制代码
<select id="selectUserChoose" resultType="user">
    select * from tb_user 
    <where>
        <choose>
            <when test="null != name">
                and name = #{name}
            </when>
            <when test="null != age and '' != age">
                and age = #{age}
            </when>
            <otherwise>
                and id = #{id}
            </otherwise>
        </choose>
    </where>
</select>

1.5 foreach元素

<foreach>元素中的collection属性负责引入需要循环的集合,open属性负责设置拼接SQL的前缀,close属性负责设置拼接SQL的后缀,separator属性负责设置每个循环中元素的分割符,item代表循环中的每一个元素,除此之外,还有index属性,代表此次循环的角标。

XML 复制代码
<select id="selectUserForEach" resultType="user">
    select * from tb_user where id in 
    <foreach collection="idList" open="(" close=")" separator="," item="id">
        #{id}
    </foreach>
</select>

查询到的数据作为集合返回

循环里面传进去的参数为集合

映射文件传参的时候,单个是任意的字符可能会找不到,通过添加注解**@param("list")**获取

如果为string类型,也需要加入注解**@param("keyword")**

oreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!

提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值

foreach标签

foreach 标签:用来迭代任何可迭代的对象(如数组,集合)。

1.6 bind 元素

<bind>元素为命名元素,它可以创建一个变量井将其绑定到上下文中,方便后续重复使用,在以上代码中,使用<bind>元素设置了一个变量,值为'%'+name+'%',注意此时的name为从user类中获取的参数,并非name字符串。设置<bind>元素后,可以在上下文使用"#{}"引用。

XML 复制代码
<select id="selectUserBind" resultType="user">
    <bind name="bindName" value="'%'+name+'%'"/>
    SELECT * FROM tb_user 
    <if test="age!=null">
        /*相当于where name like '%'+#{name}+'%'*/
        where name like #{bindeName}
    </if>
</select>

二 关系映射

2.1 关联关系概述

表与表之间的关系可以分为三种,分别为"一对一","一对多"和"多对多"。

在"一对一"的关系中:A表中的一条数据只能与B表中的一条数据关联,反过来同样成立,比如学生卡与学生。

在"一对多""的关系中,A表中的一条数据可以与B表中多条数据关联,但是B表中的每个数据都只能有A表中的一条记录对应。比如班级和学生,每个班级对应多个学生,但是每个学生只能对应一个班级。

在"多对多"的关系中,A表中的一条数据可以与B表中的多条数据关联,B表中的每个数据可以与A表中的多条记录对应。比如老师和学生,一个学生可以对应多个老师,一个老师也可以对应多个学生。

【关联映射:本质上是告诉你多表查询的字段,如何映射到实体类的属性上。】

2.2 一对一级联查询

案例实现步骤

2.2.1 准备工作(依赖和工具类)

pom.xml:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ambow</groupId>
    <artifactId>mybatis07</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- mybatis的依赖 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <!-- mysql-connector-java 的依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!-- lombok 的依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <!--            <scope>provided</scope>-->
        </dependency>
        <!-- junit的依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>

定义一个MyBatisUtil工具类:

java 复制代码
package com.ambow.util;

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 java.io.IOException;
import java.io.InputStream;

public class MyBatisUtil {

    private static SqlSessionFactoryBuilder builder;
    private static SqlSessionFactory sqlSessionFactory;

    //静态代码块 - 类加载的时候,只执行一次
    static {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取SqlSessionFactory - 工厂对象
        builder = new SqlSessionFactoryBuilder();
        System.out.println(builder);
        sqlSessionFactory = builder.build(inputStream);
        System.out.println(sqlSessionFactory);
    }

    //获取SqlSession
    public static SqlSession getSqlSession(){
        //获取SqlSession - 连接对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }

    //关闭SqlSession
    public static void closeSqlSession(SqlSession session){
        if (session != null) {
            session.close();
        }
    }

}

2.2.2 创建数据库的表与实体类

创建表和实体类

card表的建表语句:

sql 复制代码
-- ----------------------------
-- Table structure for card
-- ----------------------------
DROP TABLE IF EXISTS `card`;
CREATE TABLE `card` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `card_number` int(11) DEFAULT NULL,
  `sid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of card
-- ----------------------------
INSERT INTO `card` VALUES ('1', '178283992', '3');
INSERT INTO `card` VALUES ('2', '123624573', '2');
INSERT INTO `card` VALUES ('3', '234122212', '1');

student表的建表语句:

sql 复制代码
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `cid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '张三', '3');
INSERT INTO `student` VALUES ('2', '李四', '2');
INSERT INTO `student` VALUES ('3', '王五', '1');

Card类:

java 复制代码
package com.ambow.pojo;

import lombok.Data;

@Data
public class Card {
    Integer id;
    String cardNumber;
}

Student类:

java 复制代码
package com.ambow.pojo;

import lombok.Data;

@Data
public class Student {
    Integer id;
    String name;
    Card card; //每个学生都有一个学生卡 card
    //Integer cid;
}

2.2.3 编写MyBatis配置文件与数据库配置文件

mybatis-config.xml:

XML 复制代码
<?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">
<!--MyBatis的核心配置文件-->
<configuration>
    <properties resource="jdbc.properties" />

    <!--设置-->
    <settings>
        <!--开启数据库日志检测-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--开启驼峰命名法-->
        <setting name="mapUnderscoreToCamelCase" value="true" />
    </settings>

    <!--类型别名-->
    <typeAliases>
        <package name="com.ambow.pojo" />
    </typeAliases>

    <!--配置环境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!--配置映射器-->
    <mappers>
        <!-- 4.将包内的映射器接口实现全部注册为映射器【推荐】 -->
        <package name="com.ambow.mapper" />
    </mappers>
</configuration>

jdbc.properties:

XML 复制代码
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
username=root
password=root

2.2.4 创建Mapper接口与映射文件

StudentMapper接口:

java 复制代码
package com.ambow.mapper;

import com.ambow.pojo.Student;

import java.util.List;

public interface StudentMapper {
    /*查询*/
    List<Student> selectStudent();
}

StudentMapper.xml:

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.ambow.mapper.StudentMapper">

    <resultMap id="studentMap" type="student">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <association property="card" javaType="card">
            <id column="cid" property="id" />
            <result column="card_number" property="cardNumber" />
        </association>
    </resultMap>


    <select id="selectStudent" resultMap="studentMap">
        SELECT s.id,name,cid,card_number
        FROM student s JOIN card c
                            ON s.cid = c.id
    </select>
</mapper>

2.2.5 创建测试类

java 复制代码
package com.ambow.test;

import com.ambow.mapper.StudentMapper;
import com.ambow.pojo.Student;
import com.ambow.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class AssociateTest {

    @Test
    public void test01(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        List<Student> students = mapper.selectStudent();
        for (Student student : students) {
            System.out.println(student);
        }

        sqlSession.close();
    }
}

2.3 一对多级联查询

案例实现步骤

2.3.1 准备工作(依赖和工具类)

pom.xml:

复制代码
同上一案例

MyBatisUtil:

复制代码
同上一案例

2.3.2 创建实体类和表

MyClass类:

java 复制代码
package com.ambow.pojo;
​
import lombok.Data;
​
import java.util.List;
​
@Data
public class MyClass {
    Integer id;
    String className;
    List<Student> student;
}

Student类:

java 复制代码
package com.ambow.pojo;
​
import lombok.Data;
​
@Data
public class Student {
    Integer id;
    String name;
}

myclass表的建表语句:

sql 复制代码
-- ----------------------------
-- Table structure for myclass
-- ----------------------------
DROP TABLE IF EXISTS `myclass`;
CREATE TABLE `myclass` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `class_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
​
-- ----------------------------
-- Records of myclass
-- ----------------------------
INSERT INTO `myclass` VALUES ('1', '一班');
INSERT INTO `myclass` VALUES ('2', '二班');
INSERT INTO `myclass` VALUES ('3', '三班');

student表的建表语句:

sql 复制代码
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `cid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
​
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '张三', '1');
INSERT INTO `student` VALUES ('2', '李四', '2');
INSERT INTO `student` VALUES ('3', '王五', '1');
INSERT INTO `student` VALUES ('4', '赵六', '3');
INSERT INTO `student` VALUES ('5', '蜀七', '1');
INSERT INTO `student` VALUES ('6', '魏八', '3');

2.3.3 编写MyBatis配置文件与数据库配置文件

mybatis-config.xml:

复制代码
同上一案例

jdbc.properties:

sql 复制代码
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
username=root
password=root

2.3.4 创建Mapper接口与映射文件

MyClassMapper接口:

java 复制代码
package com.ambow.mapper;
​
import com.ambow.pojo.MyClass;
​
import java.util.List;
​
public interface MyClassMapper {
    /*查询*/
    List<MyClass> selectMyClass();
}

MyClassMapper.xml:

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.ambow.mapper.MyClassMapper">
​
    <resultMap id="myClassMap" type="myClass">
        <id column="cid" property="id" />
        <result column="class_name" property="className" />
        <collection property="student" ofType="student">
            <id column="sid" property="id" />
            <result column="name" property="name" />
        </collection>
    </resultMap>
​
​
    <select id="selectMyClass" resultMap="myClassMap">
        SELECT c.id cid,class_name,s.id sid,`name`
        FROM myclass c JOIN student s
                            ON c.id = s.cid
    </select>
​
​
</mapper>

2.3.5 创建测试类

java 复制代码
package com.ambow.test;
​
import com.ambow.mapper.MyClassMapper;
import com.ambow.pojo.MyClass;
import com.ambow.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
​
import java.util.List;
​
public class CollectionTest {
    @Test
    public void test01(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        MyClassMapper mapper = sqlSession.getMapper(MyClassMapper.class);
​
        List<MyClass> myClasses = mapper.selectMyClass();
        for (MyClass myClass : myClasses) {
            System.out.println(myClass);
        }
​
        sqlSession.close();
    }
}
​

2.4 多对多级联查询

案例实现步骤

2.4.1 准备工作(依赖和工具类)

pom.xml:

复制代码
同上一案例

MyBatisUtil:

复制代码
同上一案例

2.4.2 创建实体类和表

Student类:

java 复制代码
package com.ambow.pojo;
​
import lombok.Data;
​
import java.util.List;
​
@Data
public class Student {
    Integer id;
    String name;
    List<Teacher> teachers;
}

Teacher类:

java 复制代码
package com.ambow.pojo;
​
import lombok.Data;
​
import java.util.List;
​
@Data
public class Teacher {
    Integer id;
    String courseName;
    String name;
    List<Student> students;
}

student表的建表语句:

sql 复制代码
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
​
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '张三');
INSERT INTO `student` VALUES ('2', '李四');
INSERT INTO `student` VALUES ('3', '王五');

teacher表的建表语句:

sql 复制代码
-- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `course_name` varchar(255) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
​
-- ----------------------------
-- Records of teacher
-- ----------------------------
INSERT INTO `teacher` VALUES ('1', '语文', '刘伟');
INSERT INTO `teacher` VALUES ('2', '语文', '张帅');
INSERT INTO `teacher` VALUES ('3', '数学', '赵凯');
INSERT INTO `teacher` VALUES ('4', '英语', '刘波');
INSERT INTO `teacher` VALUES ('5', '英语', '英丽');

student_teacher表的建表语句:

sql 复制代码
-- ----------------------------
-- Table structure for student_teacher
-- ----------------------------
DROP TABLE IF EXISTS `student_teacher`;
CREATE TABLE `student_teacher` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `t_id` int(11) DEFAULT NULL,
  `s_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
​
-- ----------------------------
-- Records of student_teacher
-- ----------------------------
INSERT INTO `student_teacher` VALUES ('1', '1', '1');
INSERT INTO `student_teacher` VALUES ('2', '3', '1');
INSERT INTO `student_teacher` VALUES ('3', '5', '1');
INSERT INTO `student_teacher` VALUES ('4', '2', '2');
INSERT INTO `student_teacher` VALUES ('5', '3', '2');
INSERT INTO `student_teacher` VALUES ('6', '4', '2');
INSERT INTO `student_teacher` VALUES ('7', '1', '3');
INSERT INTO `student_teacher` VALUES ('8', '3', '3');
INSERT INTO `student_teacher` VALUES ('9', '4', '3');

2.4.3 编写MyBatis配置文件与数据库配置文件

mybatis-config.xml:

复制代码
同上一案例

jdbc.properties:

sql 复制代码
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
username=root
password=root

2.4.4 创建Mapper接口与映射文件

StudentMapper接口:

java 复制代码
package com.ambow.mapper;
​
import com.ambow.pojo.Student;
​
import java.util.List;
​
public interface StudentMapper {
    /*查询*/
    List<Student> selectStudent();
}

StudentMapper.xml:

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.ambow.mapper.StudentMapper">
​
    <resultMap id="studentMap" type="student">
        <id column="sid" property="id" />
        <result column="sname" property="name" />
        <collection property="teachers" ofType="teacher">
            <id column="tid" property="id" />
            <result column="course_name" property="courseName" />
            <result column="tname" property="name" />
        </collection>
    </resultMap>
​
    <select id="selectStudent" resultMap="studentMap">
        SELECT s.id sid,s.name sname,t.id tid,t.course_name,t.name tname
        FROM student s join student_teacher st on st.s_id = s.id
                       join teacher t on t.id = st.t_id
        ORDER BY s.id
    </select>
​
</mapper>

2.4.5 创建测试类

java 复制代码
package com.ambow.test;
​
import com.ambow.mapper.StudentMapper;
import com.ambow.pojo.Student;
import com.ambow.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
​
import java.util.List;
​
public class CollectionTest {
    @Test
    public void test01(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
​
        List<Student> students = mapper.selectStudent();
        for (Student student : students) {
            System.out.println(student);
        }
​
        sqlSession.close();
    }
}

2.5 三种关联映射总结

三种关联映射的实体类创建是不同,对应的查询条件是不一样的。

对于一对一关系,使用的是下面这一段,需要用到association和javatype来编写。

XML 复制代码
<association property="card" javaType="card">

对于一对多和多对多他们两者采用的是下面的这一段,使用的是collection和oftype来书写。

XML 复制代码
<collection property="student" ofType="student">

这是两者的区别。

还有一点在于创建实体类的时候,不同的对应关系创建的实体类是不同的,编写代码时要注意这两点区别与不同。

三 注解开发

3.1 注解开发概述

在MyBatis当中,除了XML映射文件创建SQL语句的方式,还可以通过注解直接编写SQL语句。使用注解开发时,无需创建映射文件,直接在Mapper接口文件的方法上通过注解编写SQL语句即可。MyBatis提供了若干注解来支持注解开发。

注解 说明
@Select 查询操作注解
@Insert 插入操作注解
@Update 更新操作注解
@Delete 删除操作注解
@Param 标注传入参数名称

在注解开发中,将注解直接放在Mapper接口文件的方法上,代表此方法对应的操作。

使用@Select注解完成查询功能的编写,查询的SQL语句直接写在注解中,其他注解,如修改、增加和删除注解,使用方法与@Select注解相同。

向SQL语句中传参的方式有三种:

  1. 传入对象:SQL语句通过对象中的属性名取值;

  2. 传入Map集合:SQL语句通过Map集合中的键来取值;

  3. 传入基本数据类型的参数,并通过@Param注解标注参数名:SQL语句通过@Param注解标注的参数名来取值;

    1. 只有一个参数的时候:sql语句在取值的时候,参数名可以任意

    2. 如果有两个参数,则参数的默认命名规则,如下:

      • 默认参数名:arg0,arg1,...

      • 默认参数名:param1,param2,...

在此需要注意的是,MyBatis注解开发 除了简单的增删改查外,还有一对多,多对多等级联查询的映射方法,因为一对多,多对多等问题需要复杂的配置,一般使用XML映射文件编写,在实际开发中,SQL语句比较复杂时,一般将注解方式与XML方式混合使用,复杂SQL使用XML映射文件编写,简单SQL使用注解开发。

总结:

  • 简单SQL使用注解开发

  • 复杂SQL使用XML映射文件编写

3.2 案例的实现步骤

3.2.1 导入依赖和工具类

pom.xml:

XML 复制代码
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <java.version>1.8</java.version>
    </properties>
​
    <dependencies>
        <!-- mybatis的依赖 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <!-- mysql-connector-java 的依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!-- lombok 的依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <!--            <scope>provided</scope>-->
        </dependency>
        <!-- junit的依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
​
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>

工具类:

java 复制代码
package com.ambow.util;
​
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 java.io.IOException;
import java.io.InputStream;
​
public class MyBatisUtil {
​
    private static SqlSessionFactoryBuilder builder;
    private static SqlSessionFactory sqlSessionFactory;
​
    //静态代码块 - 类加载的时候,只执行一次
    static {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取SqlSessionFactory - 工厂对象
        builder = new SqlSessionFactoryBuilder();
        System.out.println(builder);
        sqlSessionFactory = builder.build(inputStream);
        System.out.println(sqlSessionFactory);
    }
​
    //获取SqlSession
    public static SqlSession getSqlSession(){
        //获取SqlSession - 连接对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }
​
    //关闭SqlSession
    public static void closeSqlSession(SqlSession session){
        if (session != null) {
            session.close();
        }
    }
​
}

3.2.2 创建MyBatis配置文件和数据库配置文件

mybatis-config.xml

XML 复制代码
<?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">
<!--MyBatis的核心配置文件-->
<configuration>
    <properties resource="jdbc.properties" />
​
    <!--设置-->
    <settings>
        <!--开启数据库日志检测-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--开启驼峰命名法-->
        <setting name="mapUnderscoreToCamelCase" value="true" />
    </settings>
​
    <!--类型别名-->
    <typeAliases>
        <package name="com.ambow.pojo" />
    </typeAliases>
​
    <!--配置环境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
​
    <!--配置映射器-->
    <mappers>
        <!-- 4.将包内的映射器接口实现全部注册为映射器【推荐】 -->
        <package name="com.ambow.dao" />
    </mappers>
</configuration>

jdbc.properties

XML 复制代码
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test3
username=root
password=root

3.2.3 创建实体类

java 复制代码
package com.ambow.pojo;
​
import lombok.Data;
​
@Data
public class Student {
    Integer id;
    String name;
​
}

3.2.4 创建StudentMapper接口

java 复制代码
package com.ambow.dao;
​
import com.ambow.pojo.Student;
import org.apache.ibatis.annotations.*;
​
import java.util.List;
import java.util.Map;
​
public interface StudentMapper {
​
    /*查询*/
    @Select("select * from student")
    List<Student> getAllStudent();
​
    /*查询单个记录*/
    /*
        只有一个参数的时候:sql语句在取值的时候,参数名可以任意
     */
    @Select("select * from student where id = #{testId}")
    Student getStudentById(int testId);
​
    //@Select("select * from student where id = #{id}")
    //Student getStudentById(@Param("id") int testId);
​
    /*新增*/
    @Insert("insert into student (name) values(#{name})")
    int addStudent(Student student);
​
    /*修改*/
    /*
        如果有两个参数,则参数的默认命名规则,如下:
            默认参数名:arg0,arg1,...
            默认参数名:param1,param2,...
​
     */
    //@Update("update student set name = #{arg1} where id = #{arg0}")
    //@Update("update student set name = #{param2} where id = #{param1}")
    //int updateStudent(int id,String name);
​
​
    @Update("update student set name = #{name} where id = #{id}")
    //int updateStudent(@Param("id") int id,@Param("name") String name);
    int updateStudent(Map map);
​
    /*删除*/
    @Delete("delete from student where id = #{id}")
    int deleteStudent(@Param("id") int id);
​
}
​

3.2.5 编写测试类

java 复制代码
package com.ambow.test;
​
import com.ambow.dao.StudentMapper;
import com.ambow.pojo.Student;
import com.ambow.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
​
import java.util.HashMap;
import java.util.List;
​
public class AnnotationTest {
    @Test
    public void test01(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
​
        List<Student> students = mapper.getAllStudent();
        for (Student student : students) {
            System.out.println(student);
        }
​
        sqlSession.close();
    }
​
    @Test
    public void test02(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
​
        Student student = mapper.getStudentById(1);
        System.out.println(student);
​
        sqlSession.close();
    }
​
​
    @Test
    public void test03(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
​
        Student student = new Student();
        student.setName("Tom");
        mapper.addStudent(student);
​
        sqlSession.commit();
        sqlSession.close();
    }
​
    @Test
    public void test04(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
​
        //mapper.updateStudent(5,"Tom");
        HashMap map = new HashMap();
        map.put("id",3);
        map.put("name","Cat");
        mapper.updateStudent(map);
​
        sqlSession.commit();
        sqlSession.close();
    }
​
    @Test
    public void test05(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
​
        mapper.deleteStudent(5);
​
        sqlSession.commit();
        sqlSession.close();
    }
}
​

总结

以上就是今天的内容~

欢迎大家点赞👍,收藏⭐,转发🚀,

如有问题、建议,请您在评论区留言💬哦。

最后:转载请注明出处!!!

相关推荐
XiaoLeisj1 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck1 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei1 小时前
java的类加载机制的学习
java·学习
师太,答应老衲吧2 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
Yaml43 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~3 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616883 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
Channing Lewis3 小时前
salesforce case可以新建一个roll up 字段,统计出这个case下的email数量吗
数据库·salesforce
追风林3 小时前
mac 本地docker-mysql主从复制部署
mysql·macos·docker
aloha_7893 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot