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

系列文章目录

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

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

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

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

文章目录

系列文章目录

前言

一 动态SQL

1.1 动态SQL概述

 1.2 if元素

1.3 where 、set 、trim元素 

1.3.1 where元素

1.3.2 set 元素

1.3.3 trim 元素

 1.元素模拟元素

2. 元素模拟元素

1.4 choose 、when 、 otherwise 元素

1.5 foreach元素

foreach标签

1.6 bind 元素

 二 关系映射

2.1 关联关系概述

2.2 一对一级联查询

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

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

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

2.2.4 创建Mapper接口与映射文件

2.2.5 创建测试类

2.3 一对多级联查询

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

2.3.2 创建实体类和表

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

2.3.4 创建Mapper接口与映射文件

2.3.5 创建测试类

2.4 多对多级联查询

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

2.4.2 创建实体类和表

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

2.4.4 创建Mapper接口与映射文件

2.4.5 创建测试类

2.5 三种关联映射总结

三 注解开发

3.1 注解开发概述

3.2 案例的实现步骤

3.2.1 导入依赖和工具类

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

3.2.3 创建实体类

3.2.4 创建StudentMapper接口

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子句中条件的筛选。

示例:

select * from tb_user where name = #{name} and age = #{age}

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

<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"字符串。 

<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始终有效。 

<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>元素功能的模拟。

<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>元素功能的模拟

<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>元素中的代码。

<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属性,代表此次循环的角标。

<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>元素后,可以在上下文使用“#{}“引用。

<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 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工具类:

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表的建表语句:

-- ----------------------------
-- 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表的建表语句:

-- ----------------------------
-- 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类:

package com.ambow.pojo;

import lombok.Data;

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

Student类:

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 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:

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

2.2.4 创建Mapper接口与映射文件

StudentMapper接口:

package com.ambow.mapper;

import com.ambow.pojo.Student;

import java.util.List;

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

StudentMapper.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 创建测试类

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类:

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

Student类:

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

myclass表的建表语句:

-- ----------------------------
-- 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表的建表语句:

-- ----------------------------
-- 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:

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

2.3.4 创建Mapper接口与映射文件

MyClassMapper接口:

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

MyClassMapper.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 创建测试类

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类:

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

Teacher类:

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表的建表语句:

-- ----------------------------
-- 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表的建表语句:

-- ----------------------------
-- 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表的建表语句:

-- ----------------------------
-- 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:

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

2.4.4 创建Mapper接口与映射文件

StudentMapper接口:

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

StudentMapper.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 创建测试类

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来编写。

<association property="card" javaType="card">

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

<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:

    <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>

工具类:

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 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

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test3
username=root
password=root

3.2.3 创建实体类

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

3.2.4 创建StudentMapper接口

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 编写测试类

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();
    }
}
​

总结

以上就是今天的内容~

欢迎大家点赞👍,收藏⭐,转发🚀,
如有问题、建议,请您在评论区留言💬哦。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/62615.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【计算机网络】网络基础(上)

文章目录 1. 网络发展认识协议 2.网络协议初识协议分层OSI七层模型 | TCP/IP网络传输基本流程情况1&#xff1a;同一个局域网(子网)数据在两台通信机器中如何流转协议报头的理解局域网通信原理(故事版本)一般原理数据碰撞结论 情况2&#xff1a;跨一个路由器的两个子网IP地址与…

分布式定时任务框架Quartz总结和实践(1)

一、概述 Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目&#xff0c;它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个&#xff0c;百个&#xff0c;甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或…

纯css实现登录表单动效

效果图&#xff1a; 代码展示 // 我这边用的是elementUI表单校验&#xff0c;更改的样式。 <el-form:model"form":rules"rules"ref"fromList":hide-required-asterisk"true"><el-form-item prop"account"><…

记一次 .NET某医疗器械清洗系统 卡死分析

一&#xff1a;背景 1. 讲故事 前段时间协助训练营里的一位朋友分析了一个程序卡死的问题&#xff0c;回过头来看这个案例比较经典&#xff0c;这篇稍微整理一下供后来者少踩坑吧。 二&#xff1a;WinDbg 分析 1. 为什么会卡死 因为是窗体程序&#xff0c;理所当然就是看主…

回归预测 | MATLAB实现SO-CNN-BiGRU蛇群算法优化卷积双向门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现SO-CNN-BiGRU蛇群算法优化卷积双向门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现SO-CNN-BiGRU蛇群算法优化卷积双向门控循环单元多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现SO-CNN-BiGRU蛇群算法…

14-1_Qt 5.9 C++开发指南_网络编程及主机信息查询_HostInfo

Qt 网络模块提供了用于编写 TCP/IP 客户端和服务器端程序的各种类&#xff0c;如用于 TCP 通信的QTcpSocket 和 QTcpServer&#xff0c;用于 UDP 通信的 QUdpSocket&#xff0c;还有用于实现 HTTP、FTP 等普通网络协议的高级类如 QNetworkRequest&#xff0c;QNetworkReply 和Q…

Java异常体系总结(上篇)

目录 1. 什么是异常&#xff1f; 2. 异常家族体系介绍 2.1 Error 2.2 Exception 2.2.1 运行时异常 2.2.2 编译时异常 2.2.3 Exception 分类总结 3. 从类加载的全过程深入理解编译时异常与运行时异常 3.1 类加载的全过程 3.2 什么是编译时异常&#xff1f; 3.3 什么是…

OpenCV中图像变换

一、介绍 transform()&#xff1a;Transposes a matrix. perspectiveTransform()&#xff1a;Performs the perspective matrix transformation of vectors. warpAffine()&#xff1a;Applies an affine transformation to an image. warpPerspective()&#xff1a;Applies a p…

振弦传感器信号转换器应用山体滑坡安全监测

振弦传感器信号转换器应用山体滑坡安全监测 随着人类文明的进步&#xff0c;自然灾害对人们的生活和财产安全造成的威胁也越来越大。山体滑坡作为自然灾害中的一种&#xff0c;给人们的生活和财产安全带来了极大的威胁。因此&#xff0c;进行山体滑坡的安全监测显得尤为重要。振…

标准IO和直接IO

标准IO访问方式 直接IO访问方式&#xff08;open O_DIRECT绕过内核缓冲区直接访问&#xff0c;有效避免CPU和内存多余时间的开销) 注意:直接I/0的缺点就是如果访问的数据不在应用程序缓存中&#xff0c;那么每次数据都会直接从磁盘进行加载&#xff0c;这种直接加载会非常缓慢…

Kubespray-offline v2.21.0-1 下载 Kubespray v2.22.1 离线部署 kubernetes v1.25.6

文章目录 1. 目标2. 预备条件3. vcenter 创建虚拟机4. 系统初始化4.1 配置网卡4.2 配置主机名4.3 内核参数 5. 打快照6. 安装 git7. 配置科学8. 安装 docker9. 下载介质9.1 下载安装 docker 介质9.2 下载 kubespray-offline-ansible 介质9.3 下载 kubernetes 介质 10. 搬运介质…

Selenium入门详细教程+实例演示

目录 1.Selenium概述 1.1什么是Selenium 1.2Selenium的优势 1.3Selenium WebDriver原理 2.Selenium环境搭建 3.Selenium 简单示例 4.八大元素定位 4.1定位方式 4.2定位方式的用法 5.Selenium API 5.1WebDriver 常用 API 5.2WebElement 常用 API 5.3代码示例 6.元素等待机…

DNSlog注入(利用DNSlog平台将SQL盲注变成回显注入)

前言什么是UNC什么是DNSlog注入DNSlog注入的条件防止DNSlog注入的几个措施 sqli-labs试验 前言 前几天面试的时候&#xff0c;面试官问我知不知道OOB&#xff08;带外数据&#xff09;。 当时我蒙了&#xff0c;确实没听说过这个东西&#xff0c;然后面试官告诉我原来dnslog注入…

Vue3 第一节 Vue3简介以及创建Vue3工程

1.Vue3简介以及Vue3带来了什么 2.创建Vue3.0工程并分析Vue3工程结构 3.setup函数 4.ref函数 5.reactive函数 一.Vue3简介以及Vue3带来了什么 ① Vue3简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff0…

[腾讯云Cloud Studio实战训练营]基于Cloud Studio完成图书管理系统

[腾讯云Cloud Studio实战训练营]基于Cloud Studio完成图书管理系统 ⭐前言&#x1f31c;Cloud Studio产品介绍1.登录2.创建工作空间3.工作空间界面简介4.环境的使用 ⭐实验实操&#x1f31c;Cloud Studio实现图书管理系统1.实验目的 2. 实验过程2.实验环境3.源码讲解3.1添加数据…

postgresql 使用之 存储架构 触摸真实数据的存储结构以及组织形式,存入数据库的数据原来在这里

存储架构 ​专栏内容&#xff1a; postgresql内核源码分析 手写数据库toadb 并发编程 个人主页&#xff1a;我的主页 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 概述 postgresql 数据库服务运行时&#xff0c;数据在磁…

【IMX6ULL驱动开发学习】22.IMX6ULL开发板读取ADC(以MQ-135为例)

IMX6ULL一共有两个ADC&#xff0c;每个ADC都有八个通道&#xff0c;但他们共用一个ADC控制器 1.设备树 在imx6ull.dtsi文件中已经帮我们定义好了adc1的节点部分信息 adc1: adc02198000 {compatible "fsl,imx6ul-adc", "fsl,vf610-adc";reg <0x0219…

Jenkins工具系列 —— 插件 钉钉发送消息

文章目录 安装插件 Ding TalkJenkins 配置钉钉机器人钉钉APP配置项目中启动钉钉通知功能 安装插件 Ding Talk 点击 左侧的 Manage Jenkins —> Plugins ——> 左侧的 Available plugins Jenkins 配置钉钉机器人 点击 左侧的 Manage Jenkins &#xff0c;拉到最后 钉…

【Segment Anything Model】四:预处理自己的数据集接入SAM

文章目录 1️⃣预备知识2️⃣实现思路&#x1f538;脚本预处理得到包含embedd和GT的npz&#x1f538;编写Dataset类3️⃣代码&#x1f538;实现脚本预处理得到包含embedd和GT的npz代码&#x1f538;实现Dataset的代码 1️⃣预备知识 欢迎订阅本专栏&#xff08;为爱发电&#…

基于SPSSPRO实现层次分析法(AHP)

层次分析法&#xff0c;简称AHP&#xff0c;是指将与决策总是有关的元素分解成目标、准则、方案等层次&#xff0c;在此基础之上进行定性和定量分析的决策方法。&#xff08;摘自百度百科&#xff09; 层次分析法有着广泛使用&#xff0c;涉及到的平台也多种多样&#xff0c;今…