0
点赞
收藏
分享

微信扫一扫

III-Mybatis

骑在牛背上看书 2022-02-20 阅读 84

文章目录

1.Mybatis

1.1JDBC操作

 //利用jdbc,完成新增的功能
    private static void method2() throws Exception{
        //1,注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2,获取数据库的连接
        //数据传输协议   数据库的ip 端口号 数据库名
        String url = "jdbc:mysql://localhost:3306/cgb2107";
        Connection c = DriverManager.getConnection(url,"root","root");
        //3,获取传输器
        Statement s = c.createStatement();
        //4,利用传输器执行  增删改的SQL
        //executeUpdate()用来执行增删改的SQL,只返回影响行数
        int rows = s.executeUpdate(
                "INSERT INTO emp(ename,job) VALUES('rose','副总')");
        //5,释放资源
        //r.close();//结果集
        s.close();//传输器
        c.close();//连接
    }

1.2Mybatis概述

  • MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java
    Objects,普通老式 Java 对象)为数据库中的记录。
  • MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation
    迁移到了google code,并且改名为MyBatis 。
  • 2013年11月迁移到Github。

特点:

  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。
  • sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射。
  • 提供对象关系映射标签,支持对象关系组建维护。
  • 提供xml标签,支持编写动态sql。

1.3数据映射

持久层:
1.数据表: 用户的数据信息, 持久化到本地磁盘中
2.POJO: 程序通过对象封装数据信息.

映射关系: 一个POJO对象要求映射一张数据表
1.对象名称  映射 数据表表名
2.对象的属性 映射 数据表中的字段

1.4环境搭建

1.4.1导入jar包文件

 <!--mybatis依赖包-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <!--jdbc依赖包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--添加lombok的包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

1.4.2编辑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">
<!--核心配置文件-->
<configuration>

    <!--环境配置标签-->
    <environments default="development">

        <!--编辑开发环境-->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&amp;useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true&amp;allowMultiQueries=true"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--Mybatis加载Mapper映射文件-->
    <mappers>
        <mapper resource="mybatis/mappers/UserMapper.xml"/>
    </mappers>
</configuration>

1.4.3编辑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">

<!--namespace是mybaits映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.UserMapper">
    <!--id 表示接口方法
        resultType 返回值结果类型
    -->
    <select id="findAll" resultType="com.jt.pojo.User">
        select * from demo_user
    </select>
</mapper>

1.5Mybatis运行原理

package com.jt;

import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
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 org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class TestMybatis {
    /**
     * 规则说明:
     *      1.创建SqlSessionFactory 工厂模式
     *      2.获取SqlSession 理解:数据库链接+传输器对象
     *      3.获取Mapper接口对象
     *      4.完成业务调用
     *      5.关闭链接
     */
    @Test
    public void demo1() throws IOException {
        //1.1 指定配置文件的根目录
        String resource = "mybatis-config.xml";
        //1.2 通过IO流 加载配置文件 org.apache.ibatis.io;包路径
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //1.3 实例化工厂对象
        SqlSessionFactory sqlSessionFactory =
                        new SqlSessionFactoryBuilder().build(inputStream);
        //2 获取SqlSession 通过sqlSession可以直接操作数据库
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //3 获取接口对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //4.调用接口方法
        List<User> userList = userMapper.findAll();
        System.out.println(userList);
        //5.暂时手动关闭链接
        sqlSession.close();
    }
}

2.SpringBoot简化Mybatis

2.1修改配置文件名称为.yml

在这里插入图片描述

2.2修改yml配置文件

#1.配置端口号  注意缩进!!!!!
server:
  port: 8090

#2.配置数据源
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    #yml文件 0不解析 如果字母以0开头则引号包裹
    #password: "0123456"
    password: root

#3.配置Mybatis
mybatis:
  type-aliases-package: com.jt.pojo
  #将所有的映射文件全部加载
  mapper-locations: classpath:/mappers/*.xml
  #开启驼峰映射
  configuration:
    map-underscore-to-camel-case: true

#4.打印Sql com.jt.mapper下的Sql日志
logging:
  level:
    com.jt.mapper: debug

3.resultMap

当表中的字段与POJO中的属性名称不一致时,需要使用resultMap的方式进行映射.
resultType : 只能支持字段名称属性名称一致时才能自动映射.
resultMap: 可以支持 任意类型的映射 万能的结构

3.1编辑映射文件

<?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.jt.mapper.DogMapper">

    <select id="findAll" resultMap="dogRM">
        select * from dog
    </select>

    <resultMap id="dogRM" type="Dog">
        <!--ID:代表主键-->
        <id column="dog_id" property="dogId"/>
        <!--结果集-->
        <result column="dog_name" property="dogName"/>
        <!--<result column="age" property="age"/>-->
    </resultMap>
</mapper>

3.2开启驼峰规则映射

mybatis:
  #定义别名包
  type-aliases-package: com.jt.pojo
  #将所有的映射文件全部加载
  mapper-locations: classpath:/mappers/*.xml
  #开启驼峰映射
  configuration:
    map-underscore-to-camel-case: true

4.Mybatis关联查询

4.1关联查询sql

4.1.1笛卡尔积

特点: 只获取2张表的交集

SELECT * FROM emp,dept 
WHERE emp.dept_id = dept.dept_id

4.1.2连接查询

分类: 1.左连接 2.内连接 3.右连接

/*左连接  emp表当作主表 */
SELECT * FROM 
	emp 
		LEFT JOIN
	dept
		ON
	emp.dept_id = dept.dept_id

4.2封装关联关系

4.2.1封装Emp对象

package com.jt.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Emp implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    //关联关系: 一个员工对应一个部门
    private Dept dept;
    //private Integer deptId;
}

4.2.2封装Dept对象

package com.jt.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.List;
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable {
    private Integer deptId;
    private String deptName;
    //关联 一个部门下有多个员工
    private List<Emp> emps;
}

4.2.3编辑映射文件(一对一封装)

<?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.jt.mapper.EmpMapper">
    <!--
        规则:
            1.如果操作单表 一般使用resultType
            2.如果进行关联操作,使用resultMap
            3.如果是多表关联操作,则不允许出现重名字段.否则映射失败.
    -->
    <select id="findAll" resultMap="empRM">
        SELECT emp.id,emp.name,emp.age,dept.dept_id,
	    dept.dept_name
	    FROM emp,dept
	    WHERE emp.dept_id = dept.dept_id
    </select>

    <!--
        关于自动映射规则:
            1.没有关联映射时: 如果属性和字段同名,则可以省略不写.
            2.如果有关联映射: 则需要添加自动映射的开关autoMapping="true"
                           该注解只对当前对象有效 如果有多个对象,则需要添加多次
    -->
    <resultMap id="empRM" type="Emp" autoMapping="true">
        <!--主键是必填项-->
        <id column="id" property="id"/>
        <!--
            知识点:
                1.一对一关联封装 association标签
                2.必须指定属性的类型 javaType属性
                3.autoMapping="true" 自动映射
         -->
        <association property="dept" javaType="Dept" autoMapping="true">
            <!--主键必填项-->
            <id column="dept_id" property="deptId"/>
            <!--由于一起开启驼峰规则映射.所以下列的操作可以省略-->
            <!--<result column="dept_name" property="deptName"/>-->
        </association>
    </resultMap>
</mapper>

4.2.3编辑映射文件(一对多封装)

<?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.jt.mapper.DeptMapper">
    
    <select id="findAll" resultMap="deptRM">
        SELECT dept.dept_name,emp.*
	    FROM dept,emp
	    WHERE emp.dept_id = dept.dept_id
    </select>
    <resultMap id="deptRM" type="Dept" autoMapping="true">
        <!--主键必须标识-->
        <id column="dept_id" property="deptId"/>
        <!-- 一对多封装 固定搭配 ofType="" -->
        <collection property="emps" ofType="Emp" autoMapping="true">
            <id column="id" property="id"></id>
        </collection>
    </resultMap>
</mapper>

5.总结

知识点1

 /**
     * 知识点:
     *      1.如果是多个参数传递,则一般采用对象的方式封装.
     */
    @Test
    public void testFindByNA(){
        String name = "孙尚香";
        int age = 18;
        User user = new User();
        user.setName(name).setAge(age);
        List<User> userList = userMapper.findUserByNA(user);
        System.out.println(userList);
    }

知识点2

<!-- 根据name和age查询数据
         知识点: 别名包
                在配置文件中指定包路径: 可以自动的实现包路径的拼接
         resultType规则:
               1. 首先根据别名包匹配.设定..
               2. 如果匹配不成功,则按照路径匹配.
         参数传递的规则:
                1. 如果是单个参数,则使用#{key}  获取的参数的值
                2. 如果是对象参数,则使用#{属性} 获取的是属性值
      -->
    <select id="findUserByNA" resultType="User">
        select * from demo_user where
        name = #{name} and age = #{age}
    </select>

知识点3:Map封装对象

 /**
     * 知识点3:
     *      说明: 如果多个参数不方便使用 User对象封装时,应该使用万能的集合Map
     */
    @Test
    public void testFindByAge(){
        int minAge = 18;
        int maxAge = 100;
        Map<String,Integer> map = new HashMap<>();
        map.put("minAge",minAge);
        map.put("maxAge",maxAge);
        List<User> userList = userMapper.findUserByAge(map);
        System.out.println(userList);
    }

知识点4:转义标签

 <!--
        根据年龄查询数据
        语法:  如果传递的参数是Map, 则使用#{key}
        xml转译字符:
                    1. >  &gt;
                    2. <  &lt;
                    3. & &amp;
                    4. 万能转译字符
                       <![CDATA[ 转移内容  ]]>
     -->
    <select id="findUserByAge" resultType="User">
        <![CDATA[
             select * from demo_user
                where age  > #{minAge} and   age  < #{maxAge}
           ]]>
    </select>

知识点5:@Param实现数据封装

 /**
     * 知识点4:
     *      利用注解实现数据的封装
     */
    @Test
    public void testFindByAge2(){
        int minAge = 18;
        int maxAge = 100;
        List<User> userList = userMapper.findUserByAge2(minAge,maxAge);
        System.out.println(userList);
    }

    //原则:Mybatis只支持单值传参 将多值封装为单值
    //注解:@Param("key") int minAge(值)
    // 作用:将数据封装为Map
    List<User> findUserByAge2(@Param("minAge") int minAge, @Param("maxAge") int maxAge);

知识点6:模糊查询

 /**
     * 知识点5:
     *      利用注解实现数据的封装
     */
    @Test
    public void testFindUserByLike(){
        String name = "%" + "君" + "%";
        List<User> userList = userMapper.findUserByLike(name);
        System.out.println(userList);
    }

<!--模糊查询  特别注意表名的大小写问题!!!!!
        windows系统中: 不区分大小写
        Linux系统中:   区分大小写问题.
    -->
    <select id="findUserByLike" resultType="User">
        SELECT * FROM demo_user WHERE NAME LIKE #{name}
    </select>
	
	方式2: xml配置文件动态拼接%
	 <!--模糊查询  特别注意表名的大小写问题!!!!!
        windows系统中: 不区分大小写
        Linux系统中:   区分大小写问题.
        语法:  "%"     这样的方式
    -->
    <select id="findUserByLike" resultType="User">
        SELECT * FROM demo_user WHERE NAME LIKE "%"#{name}"%"
    </select>

知识点7:Sql标签

说明: Sql语句中经常出现重复的数据.如果每次重复的内容都自己手写.则开发的效率低.
优化: 将公共的Sql进行抽取
优势: Sql标签可以节省代码
缺点: 可读性变差了, 如果是关联操作 则根据情况而定.

     <!--Sql标签: 抽取公共的Sql语句 -->
    <sql id="tableColumn">
        id,name,age,sex
    </sql>

知识点8:集合参数写法,动态

	select * from demo_user  where id in (1,2,3,5,7........)
//前端: URL?id=1,2,3,4,5 获取之后一般采用数组接收
    @Test
    public void testFindListByIn(){
        int[] array = {1,2,3,5,7};
        List<User> userList = userMapper.findListByIn(array);
        System.out.println(userList);
    }
	 <!--
        关于Mybatis的遍历的写法
        foreach:
            1. collection 需要遍历的集合
                   1.1 数组      关键字: array/list
                   1.2 list集合  关键字: list/array
                   1.3 Map<key,array/list>  关键字:key
            2. open/close  循环体的开始和结束 可以写到循环之外简化标签
            3. item  当前遍历数据的变量名
            4. separator 分割符
    -->
    <select id="findListByIn" resultType="User">
        select * from demo_user  where id in (
            <foreach collection="array" item="id" separator=",">
                #{id}
            </foreach>
        )
    </select>

知识点9:用户新增

@Test
    public void testInsertUser(){
        User user = new User();
        user.setName("张三").setAge(18).setSex("男");
        userMapper.saveUser(user);
        System.out.println("新增成功!!!!");
    }

 <insert id="saveUser">
        insert into demo_user(id,name,age,sex)
                value (null, #{name},#{age},#{sex})
    </insert>

知识点10:动态Sql-where

package com.jt;

import com.jt.mapper.UserMapper;
import com.jt.mapper.UserMapper2;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SpringBootTest
public class TestMybatis2 {

    @Autowired
    private UserMapper2 userMapper;

    /**
     * 案例1: 测试动态sql
     */
    @Test
    public void testDemo1(){
        User user = new User();
        user.setAge(18).setSex("女"); //动态变化的数据
        List<User> userList = userMapper.findUserList(user);
        System.out.println(userList);
    }
}


<?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.jt.mapper.UserMapper2">

    <!--
        动态Sql: 根据对象中不为null的属性当作where条件
        语法:
               1.如果判断成立,则动态拼接条件
               <if test="id !=null ">条件</if>
               2.where标签  去除where后边多余的一个and/or
    -->
    <select id="findUserList" resultType="User">
        select * from demo_user
        <where>
            <if test="id !=null ">id = #{id}</if>
            <if test="name !=null">and name = #{name}</if>
            <if test="age !=null ">and age = #{age}</if>
            <if test="sex !=null ">and sex = #{sex}</if>
        </where>
    </select>
</mapper>

知识点11:动态Sql-set

//执行动态的更新操作
    //根据对象中不为null的元素,充当set条件. where id=xxx
    @Test
    public void testDemo2(){
        User user = new User();
        user.setId(231).setName("冬天").setAge(18);
        userMapper.updateUser(user);
        System.out.println("更新成功!!!");
    }

<!--根据对象中不为null的元素,充当set条件.-->
    <update id="updateUser">
        update demo_user
            <set>
                <if test="name !=null">name = #{name},</if>
                <if test="age !=null">age = #{age},</if>
                <if test="sex !=null">sex = #{sex}</if>
            </set>
            where id = #{id}
    </update>

知识点12:动态Sql-choose、when、otherwise

说明: 如果不想使用所有的条件可以使用choose 类似于java中的switch 语法:
如果name有值,则按照name查询,否则按照sex查询数据.

@Test
    public void testDemo3(){
        User user = new User();
        user.setName(null).setAge(null).setSex("女");
        List<User> userList = userMapper.findUserByNS(user);
        System.out.println(userList);
    }

 <select id="findUserByNS" resultType="User">
        select * from demo_user
            <where>
                <choose>
                    <when test="name !=null">
                        name = #{name}
                    </when>
                    <when test="age !=null">
                        age = #{age}
                    </when>
                    <otherwise>
                        sex = #{sex}
                    </otherwise>
                </choose>
            </where>
    </select>

举报

相关推荐

0 条评论