Mybatis

目录

ORM思想

常规JDBC的弊端

Mybatis

Mybatis特点

Mybatis入门案例

导入jar包

编辑POJO对象

编写xml形式的核心配置文件

编写持久层mapper的接口

编写接口实现类的xml形式的映射文件

核心配置文件中配置mybatis关联的映射文件

编写测试类进行测试

Mybatis调用流程

根据ID查询数据

编写业务接口

编辑xml映射文件

编辑测试API

mybatis入门操作

简化Mybatis操作

@BeforeEach注解说明

mybatis参数封装说明

报错说明:

常见封装策略

测试案例:

参数知识点总结:

#号和$符用法

规则说明

案例实现

Mybatis 常规CURD操作

新增、删除、更改操作

编写测试方法

编写业务接口

编写xml文件

总结

Mybatis中的转义标签

xml转义语法

编写测试方法

编写业务接口

编写xml文件

Mybatis集合用法--批量

需求分析

封装方式

编写测试方法

编写业务接口

编写xml文件

总结:

模糊查询说明

Mybatis的优化设置

Mybatis的核心配置文件是有顺序的

Mybatis的简化---别名

Mybatis的简化---SQL标签

Mybatis优化之开启驼峰映射规则

Mybatis之动态sql

IF-WHERE用法

动态sql----SET标签

动态Sql-choose when otherwise

resultType和resultMap用法

标签说明

编辑测试类

编辑接口

编辑xml映射文件

resultType的返回类型

对象类型

简单类型

Map类型

关联关系

常见的关联关系

一对一

一对多

Mybatis的缓存机制

什么是缓存机制

一级缓存

二级缓存


ORM思想

对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换

  • 概括: 用对象的方式操作数据库

  • 衍生:

    1. 对象应该与数据库中的表一一映射.

    2. 对象中的属性应该与表中的字段一一映射.

    3. 其中的映射应该由程序自动完成.无需人为干预.

常规JDBC的弊端

//利用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. 无论如何执行都必须获取数据库链接。 链接池: c3p0 druid HK链接池

    2. 操作sql语句时,步骤繁琐. 不便于学习记忆.

    3. 资源必须手动关闭.

  • 优点

    1. 操作数据库最快的方式就是JDBC. 协议 TCP

引出:

Mybatis

  1. MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射

  2. MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。(mybatis在内部将JDBC封装).

  3. MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

知识整理:

  1. 持久化:计算机在计算时,数据都在内存中.如果断电则数据清空,所以要求将内存数据保存到磁盘中. 概念.

  2. 持久层:程序通过Dao/Mapper 与数据库进行交互的层级代码 (Controller层 Service层 Dao/Mapper层) 具体操作.

小结: Mybatis是一个优秀的持久层框架,基于ORM设计思想,实现了以对象的方式操作数据库.

了解:Mybatis的ORM并不完全,只完成了结果集映射,但是Sql需要自己手写.所以也称之为半自动化的ORM映射框架.

Mybatis特点

  1. 简单易学

  2. 灵活

  3. 解除sql与程序代码的耦合

  4. 提供映射标签,支持对象与数据库的orm字段关系映射

  5. 提供对象关系映射标签,支持对象关系组建维护

  6. 提供xml标签,支持编写动态sql

Mybatis入门案例

准备资源:

导入jar包

 <!--引入插件lombok 自动的set/get/构造方法插件  -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
​
        <!--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>

编辑POJO对象

package com.jt.pojo;
​
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
​
import java.io.Serializable;
​
@Data//1.实现get/set/...方法
@Accessors(chain = true)//2.链式加载--->设置值
@NoArgsConstructor//3.无参构造
@AllArgsConstructor//4.有参构造
public class DemoUser implements Serializable{//5.实现序列化
        private Integer id;
        private String name;
        private Integer age;
        private String sex;
​
}

编写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>
​
    <!--环境配置标签  default 默认加载的环境 只能写一个-->
    <environments default="development">
​
        <!--编辑开发环境  id是环境的唯一标识符-->
        <environment id="development">
            <!--事务管理器   利用JDBC控制事务-->
            <transactionManager type="JDBC"/>
            <!--mybatis默认采用数据库连接池的方式整合数据源-->
            <dataSource type="POOLED">
                <!--高版本数据库驱动    需要添加cj-->
                <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映射文件是有顺序的
     通过resource 加载指定xml映射文件
 -->
    <mappers>
        <mapper resource="mybatis/mappers/demoUserMapper.xml"/>
    </mappers>
</configuration>

编写持久层mapper的接口

package com.jt.mapper;
​
import com.jt.pojo.DemoUser;
​
import java.util.List;
​
/**
 *  说明:
 *      1.根据面向接口开发思想需要定义一个Mapper接口
 *      2.在接口中可以写方法,谁调用谁实现
 *      3.Mybatis中的实现类以xml文件形式存在
 */
public interface DemoUserMapper {
    //查询所有的User列表信息
    List<DemoUser> findAll();
​
    DemoUser findOne(int id);
}

编写接口实现类的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">
​
<!--xml映射文件 必须与接口一对一绑定
    namespace:指定需要绑定接口的名称,不能重复
-->
<mapper namespace="com.jt.mapper.DemoUserMapper">
​
    <!--实现接口中方法
            id: 需要与接口中的方法绑定,
            resultType: 返回值结果对象
                规则: sql语句不要添加多余的;号  Oracle数据库不能添加;号
    -->
    <select id="findAll" resultType="com.jt.pojo.DemoUser">
        select * from demo_user
    </select>
<!--  parameterType:参数类型
        resultType:返回值结果
        mybatis中通过 #{} 获取参数
  -->
    <select id="findOne" parameterType="int" resultType="com.jt.pojo.DemoUser" >
        select * from demo_user where id = #{id};
    </select>
</mapper>

核心配置文件中配置mybatis关联的映射文件

    <!--Mybatis加载Mapper映射文件
     mappers映射文件是有顺序的
     通过resource 加载指定xml映射文件
 -->
    <mappers>
        <mapper resource="mybatis/mappers/demoUserMapper.xml"/>
    </mappers>

编写测试类进行测试

package com.jt;
​
import com.jt.mapper.DemoUserMapper;
import com.jt.pojo.DemoUser;
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 {
​
    @Test
    public void testDemo1() throws IOException {
        /*创建SqlSessionFactory*/
        //指定配置文件地址
        String resource = "mybatis/mybatis-config.xml";
        //通过IO流 加载指定的配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //动态生成SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
​
        /*从SqlSessionFactory中获取sqlSession 类比  数据库链接*/
        SqlSession sqlSession = sqlSessionFactory.openSession();
​
        /*获取mapper接口,执行接口方法*/
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        //获取数据
        List<DemoUser> userList = demoUserMapper.findAll();
        System.out.println(userList);
        //关闭流
        sqlSession.close();
    }
    
    @Test
    public void findOne() throws IOException {
        String resource = "mybatis/mybatis-config.xml";
        //通过IO流 加载指定的配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //动态生成SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
​
        //获取接口
        DemoUserMapper mapper = sqlSession.getMapper(DemoUserMapper.class);
        int id=1;
        DemoUser demoUser = mapper.findOne(id);
        System.out.println(demoUser);
        sqlSession.close();
​
    }
​
}

Mybatis调用流程

根据ID查询数据

在入门案例中已经实现了,这里分离出来

编写业务接口

public interface DemoUserMapper {    //1.查询所有的表数据    public List<DemoUser> findAll();    DemoUser findOne(int id);}

编辑xml映射文件

 <!--         parameterType: 参数类型         mybatis中通过 #{} 获取参数         resultType: 返回值结果对象    -->    <select id="findOne" parameterType="int" resultType="com.jt.pojo.DemoUser">        select * from demo_user where id = #{id}    </select>

编辑测试API

/***     *  需求: 根据ID查询数据库记录   id=1的数据     */    @Test    public void testFindOne() throws IOException {        //指定配置文件地址        String resource = "mybatis/mybatis-config.xml";        //通过IO流 加载指定的配置文件        InputStream inputStream = Resources.getResourceAsStream(resource);        //动态生成SqlSessionFactory        SqlSessionFactory sqlSessionFactory =                new SqlSessionFactoryBuilder().build(inputStream);        SqlSession sqlSession = sqlSessionFactory.openSession();        //获取接口        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);        int id = 1;        DemoUser demoUser = demoUserMapper.findOne(id);        System.out.println(demoUser);        //关闭链接        sqlSession.close();    }

mybatis入门操作

简化Mybatis操作

public class TestMybatis2 {
    //定义公共的属性
    private SqlSessionFactory sqlSessionFactory;
    @BeforeEach
    public void init() throws IOException {
        String resources = "mybatis/mybatis-config.xml";
        InputStream inputStream =Resources.getResourceAsStream(resources);
         sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void testMybatis(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        List<DemoUser> list = demoUserMapper.findAll();
        System.out.println(list);
        sqlSession.close();
    }

@BeforeEach注解说明

该注解的作用是在执行@Test方法前调用. 是测试方法提供的测试API

mybatis参数封装说明

报错说明:

  • 规则:

    1. mybatis如果遇到多值传参时,默认条件是采用下标的方式获取数据.

    2. mybatis天生只支持单值传参,如果遇到多值的问题,则应该将多值封装为单值.

常见封装策略

  1. 封装为实体对象

  2. 更为常用方式:Map集合

  3. 如果传递的数据有多个,使用注解 @Param 封装为Map集合

    使用方式: List<DemoUser> findSA3(@Param("sex") String sex, @Param("age") int age);

测试案例:

编写测试方法

 //1.封装为实体对象
    @Test
    public void find1(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        //编程思想:面向对象
        DemoUser csc = new DemoUser();
        csc.setAge(18).setSex("女");
        List<DemoUser> list = demoUserMapper.findSA(csc);
        System.out.println(list);
        sqlSession.close();
    }
    //2.封装为Map集合
    @Test
    public void find2(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        Map<String,Object> map = new HashMap<>();
        map.put("sex", "女");
        map.put("age", 18);
        List<DemoUser> list = demoUserMapper.findSA2(map);
        System.out.println(list);
        sqlSession.close();
    }
    //3.使用注解@Param封装
    @Test
    public void find3(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        String sex = "女";
        int age = 18;
        List<DemoUser> list = demoUserMapper.findSA3(sex,age);
        System.out.println(list);
        sqlSession.close();
    }

编写业务接口

public interface DemoUserMapper {
    List<DemoUser> findSA(DemoUser csc);
    List<DemoUser> findSA2(Map<String, Object> map);
    //利用注解@Param将参数封装为Map集合
    List<DemoUser> findSA3(@Param("sex") String sex, @Param("age") int age);
   }

编写xml映射文件

 <!--
        查询sex=女 and age > 18岁
        参数: DemoUser user 意图:传递属性的
        规则: 如果传递的参数是对象,则通过#{属性} 可以直接获取数据.
    -->
    <select id="findBySA" resultType="com.jt.pojo.DemoUser">
        select * from demo_user where sex= #{sex} and age > #{age}
    </select>

    <!--
        如果参数被@Param("sex") String sex修饰
        则#{参数key}即可获取数据
    -->
    <select id="findBySA2" resultType="com.jt.pojo.DemoUser">
        select * from demo_user where sex= #{sex} and age > #{age}
    </select>

    <!--
        Map<String, Object> map
            sex=女  age=18
        规则: 如果参数是一个map集合,则通过#{key}获取数据.
    -->
    <select id="findBySA3" resultType="com.jt.pojo.DemoUser">
        select * from demo_user where sex= #{sex} and age > #{age}
    </select>

参数知识点总结:

  1. 如果参数采用对象封装,则可以使用#{属性}取值.

  2. 如果参数有多个,可以封装为map实现参数的传递. 可以利用#{key}获取数据

  3. 也可以使用@Param将多个参数封装为map, 利用#{key}的方式获取数据

#号和$符用法

规则说明

  1. 使用#{} 获取数据时,默认有预编译的效果.防止sql注入攻击.

  2. mybatis使用#{}获取数据时,默认为数据添加一对""号.

  3. 当以字段名称为参数时,一般使用${},但是这样的sql慎用. 可能出现sql注入攻击问题.

注意:一般条件下,能用#{},尽量不用${}

案例实现

编写测试方法

/**
     *需求:按照指定的age排序
     *  sql:select * from demo_user order by age
     *  #号 与 $符用法:
     *
     */
    @Test
    public void testFindOrder(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        String csc = "age";
        List<DemoUser> list = demoUserMapper.findFO(csc);
        System.out.println(list);
        sqlSession.close();
    }

编写业务接口

public interface DemoUserMapper {
List<DemoUser> findFO(String csc);
    }

编写xml文件

   <select id="findFO" resultType="com.jt.pojo.DemoUser">
        select * from demo_user order by ${csc}
    </select>

Mybatis 常规CURD操作

新增、删除、更改操作

编写测试方法

 /**
     * 需求:实现用户入库的操作
     */
    @Test
    public void saveUser(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        DemoUser demoUser = new DemoUser(null,"常世超",18,"女" );
        int rows= demoUserMapper.saveUser(demoUser);
        if(rows>0){
            System.out.println("影响的行数"+rows);
            sqlSession.commit();
        }

        sqlSession.close();
    }

    /**
     * 作业:
     *      1.把id=1的数据 name 改为 "守山大使"   age=5000
     *      2.将name="常世超"的数据 删除
     */
    @Test
    public void updateUser(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        DemoUser demoUser = new DemoUser(1, "守山大使", 5000, "");
        int rows = demoUserMapper.updateUser(demoUser);
        if(rows>0){
            System.out.println("影响行数"+rows);
            sqlSession.commit();
        }
        sqlSession.close();
    }
    @Test
    public void deleteUser(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        String name = "常世超";
        demoUserMapper.deleteUser(name);
        System.out.println("删除成功");
        sqlSession.close();
    }

编写业务接口

public interface DemoUserMapper {  
	int saveUser(DemoUser demoUser);
    int updateUser(DemoUser demoUser);
   	void deleteUser(String name);
}

编写xml文件

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

    <update id="updateUser">
        update demo_user set name = #{name} ,age = #{age} where id =#{id}
    </update>

    <delete id="deleteUser">
        delete from demo_user where name =#{name}
    </delete>

总结

  1. 编写删除、更改、新增操作时,需要提交事务---》mybatis会自动回滚事务

  2. 提交事务的两种方式:

    1. SqlSession sqlSession = sqlSessionFactory.openSession(true);

    2. sqlSession.commit();

Mybatis中的转义标签

xml转义语法

xml文件中的转义字符:
        &gt;  > 大于
        &lt;  < 小于
        &amp;  & 号
    说明:如果sql中有大量的转义字符 建议使用转义标签体
    语法: <![CDATA[  xxx内容 报文   ]]>

编写测试方法

 /**
     * 需求: 查询age> 18 and age< 100 的用户信息.
     * 规则: 如果不能使用对象封装,则一般使用Map集合
     */
    @Test
    public void testSelect01(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        Map<String,Object> map = new HashMap<>();
        map.put("minAge",18);
        map.put("maxAge",100);
        List<DemoUser> userList = demoUserMapper.findByAge(map);
        System.out.println(userList);
        sqlSession.close();
    }

编写业务接口

public interface DemoUserMapper {
    List<DemoUser> findByAge(HashMap<String, Object> map);
}

编写xml文件

<select id="findByAge" resultType="com.jt.pojo.DemoUser">
<!--	select * from demo_user where age >#{minAge} and age &lt; #{maxAge}-->
    	<![CDATA[ select * from demo_user where age >#{minAge} and age < #{maxAge} ]]>
</select>

Mybatis集合用法--批量

需求分析

  • 要求批量的删除数据库中的记录.

  • 规则: 如果遇到相同的多个数据,则一般采用集合的方式封装数据

封装方式

  1. array

  2. list

  3. map<list>

编写测试方法

 //1.array封装
    @Test
    public void deleteIds(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        int[] ids = {231,232,233};
        demoUserMapper.deleteIds(ids);
        System.out.println("删除操作成功");
        sqlSession.close();
    }
    //2.list封装
    @Test
    public void deleteList(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        List list = new ArrayList();
        list.add(231);
        list.add(232);
        list.add(233);
        demoUserMapper.deleteList(list);
        System.out.println("删除操作成功");
        sqlSession.close();
    }
    //3.map封装
    @Test
    public void deleteMap(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        List list = new ArrayList();
        list.add(231);
        list.add(232);
        list.add(233);
        Map map = new HashMap();
        map.put("ids", list);
        demoUserMapper.deleteMap(map);
        System.out.println("删除操作成功");
        sqlSession.close();
    }

编写业务接口

public interface DemoUserMapper {    
	void deleteIds(int[] ids);
    void deleteList(List list);
 	void deleteMap(Map map);
}

编写xml文件

   <delete id="deleteIds">
        delete from demo_user where id in
        <foreach collection="array" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>

    <delete id="deleteList">
        delete from demo_user where id in
        <foreach collection="list" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>

    <delete id="deleteMap">
        delete from demo_user where id in
        <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>

总结:

批量删除数据
难点:如果使用#{集合}获取的是集合的对象,删除无效
思路:将数组拆分为单个数据===》通过遍历数组的方式获取
语法:mybatis中为了遍历方便,提供了遍历的标签 ===》foreach
    关于标签参数的说明:
        1.collection
            1).如果参数传参为数组,       则collection="array"
            2).如果参数传参为list集合,   则collection="list"
            3).如果参数传参为map集合,    则collection="map集合中的key值"
    关于标签属性的说明:
        1.collection    集合的名称
        2.item          每次遍历的数据的性参变量
        3.open          循环开始的标签
        4.close         循环结束的标签
        5.separator     循环遍历的分割符
        6.index         循环遍历下标

模糊查询说明

需求: 查询name中包含"精"的数据.并且按照年龄降序排列

  1. 在传参为:String = "%精%"

  2. 在SQL语句中:select * from demo_user where name like "%"#{name}"%"

Mybatis的优化设置

Mybatis的核心配置文件是有顺序的

顺序为:

The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".

Mybatis的简化---别名

  1. 别名标签

  2. 别名包

  3. 使用注解定义别名

别名标签

位置:核心配置文件中

说明:只对某个类生效

<typeAliases>
    <typeAlias type="com.jt.pojo.DemoUser" alias="DemoUser"></typeAlias>
</typeAliases>
<!--
	type:	pojo对象全路径
	alias:	别名
-->

别名包

位置:核心配置文件中

说明:对包下的所有对象类生效

<typeAliases>
    <package name="com.jt.pojo"/>
</typeAliases>

使用注解

位置:POJO类上

说明:只对某个类生效

@Alias("DemoUser")--->起别名
public class DemoUser implements Serializable{//5.实现序列化
        private Integer id;
        private String name;
        private Integer age;
        private String sex;
}

Mybatis的简化---SQL标签

说明

mybatis的xml映射文件中会有大量的Sql语句. 随着业务的增加,Sql语句的数量也会增加. 其中有部分"Sql片段"则可能重复. 如果想简化Sql语句,则可以使用Sql标签简化操作.

例子:

select id,name,age,sex from demo_user where id = 1
select id,name,age,sex from demo_user where name = xxx

sql标签的用法

<!-- 提取公共的sql-->    
<sql id="demo_user_sql">
         select id,name,age,sex from demo_user
</sql>

<!--    include :   代表包含sql标签   refid : 引用sql标签ID -->

    <select id="findAll" resultType="DemoUser">
        <include refid="demo_user_sql"/>
    </select>

sql标签的优点和缺点

优点:

  1. 使用Sql标签可以节省xml的文件大小.

  2. 代码的结构相对简单.

缺点:

  1. Sql只能抽取公共的Sql语句,局限性稍大.

  2. 如果大量的使用Sql标签,则代码的可读性差

Mybatis优化之开启驼峰映射规则

说明:

在mybatis映射数据时,经常出现字段名称与属性名称不一致的现象. 但是其中一部分可以采用驼峰规则的方式完成自动映射. 所以有如下的配置

编写xml核心配置文件

位置:核心配置文件中configuration配置标签之下

 <!--Mybatis的核心配置-->
    <settings>
        <!--开启了驼峰映射规则 dept_id 自动映射到 deptId -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

Mybatis之动态sql

IF-WHERE用法

需求:根据user对象查询数据.要求根据对象中不为null的属性充当where条件.实现动态的查询

解释:

用户可以根据用户名查询数据、也可以根据用户名+身份证号查询数据、也可以跟据3个条件查询

编辑测试方法

    /**
     * 封装DemoUser的对象,根据对象中不为null的属性查询
     */
    @Test
    public void testWhere(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        DemoUser demoUser = new DemoUser();
        demoUser.setName("金角大王")
                .setAge(3000)
                .setSex("男");
       List<DemoUser> list = demoUserMapper.findWhere(demoUser);
        System.out.println(list);
        sqlSession.close();
    }

编辑接口

public interface DemoUserMapper {
    List<DemoUser> findWhere(DemoUser demoUser);
}

编辑xml映射文件

    <!--动态Sql案例
        思路: 如果数据不为null,mybatis才会当做条件
        if标签说明:
            test: 判断的条件 直接写属性即可
        where标签: 去除条件中多余的 and 或者 or的
        说明: if和 where 几乎一起出现.
    -->
    <select id="findWhere" resultType="DemoUser">
        select id,name,age,sex from demo_user
            <where>
                <if test="name != null"> name = #{name}</if>
                <if test="age != null"> and age = #{age}</if>
                <if test="sex != null"> and sex = #{sex}</if>
            </where>
    </select>

动态sql----SET标签

说明:根据对象不为null的属性当做set条件

编辑测试方法

    /**
     * 根据ID,动态的实现数据的更新
     */
    @Test
    public void testUpdateSet(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        DemoUser demoUser = new DemoUser();
        demoUser.setName("黑黑")
                .setId(1)
                .setSex("女")
                .setAge(10000);
         demoUserMapper.findUpdateSet(demoUser);
        System.out.println("修改成功");
        sqlSession.close();
    }

编辑接口

public interface DemoUserMapper {
        void findUpdateSet(DemoUser demoUser);
}

编辑xml文件

<!--
    规则:根据对象不为null的属性当做set条件
    set标签说明:
        去除set条件中多余的 , 号
-->
    <update id="findUpdateSet">
        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>

动态Sql-choose when otherwise

需求:

根据条件实现数据的查询. 如果存在name则按照name查询,否则按照sex查询.
补充说明:
条件: name = “张三” , sex=“男”
select * from demo_user where name = #{name}

编写测试类

 /**
     * 需求:如果存在name则按照name查询,否则按照sex查询
     */
    @Test
    public void testSelectChoose(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        DemoUser demoUser = new DemoUser();
        demoUser.setName("白骨精").setSex("女");
        List<DemoUser> list = demoUserMapper.findChoose(demoUser);
        System.out.println(list);
        sqlSession.close();
    }

编写接口

public interface DemoUserMapper {
    List<DemoUser> findChoose(DemoUser demoUser);
}

编写xml映射文件

<!--
    需求:如果不想将全部的条件当做if的判断,则mybatis提供了分支结构
    语法说明:
            choose:代表分支结构,只有一个条件生效
            when:指定判断的条件,和if类似
            otherwise:如果上述的条件都不满足时,该行代码有效
-->
    <select id="findChoose" resultType="DemoUser">
        select * from demo_user
            <where>
                <choose>
                    <when test="name != null">name = #{name}</when>
                    <otherwise>sex = #{sex}</otherwise>
                </choose>
            </where>
    </select>

resultType和resultMap用法

标签说明

resultType说明: 当结果集中的字段名称,如果与属性的名称一致时,才会实现自动的数据封装

resultMap说明: 当结果集中的字段名称,与对象中的属性不一致时,可以使用resultMap实现自定义的封装

编辑测试类

@Test
    public void testFindDept(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> list = deptMapper.findAll();
        System.out.println(list);
        sqlSession.close();
    }

编辑接口

public interface DemoUserMapper {
    List<Dept> findAll();
}

编辑xml映射文件

<!--
       ORM思想:对象关系映射
        字段:dept_id  dept_name
        属性:deptId   deptName
        resultType说明:
                当结果集中的字段名称,如果与属性的名称一致时,才会实现自动数据封装
        resultMap说明:
                当结果集中的字段名称,如果与属性的名称不一致时,可以自定义封装

-->
    <select id="findAll" resultMap="DeptRM">
        select * from dept
    </select>
<!--
    自定义映射关系
    语法:
        1.id标签:代表主键配置信息
            1.)column:结果集中的字段
            2.)property:对象中的属性
        2.result标签:除了主键之外的配置信息
-->
    <resultMap id="DeptRM" type="Dept">
        <id column="dept_id" property="deptId"></id>
        <result column="dept_name" property="deptName"/>
    </resultMap>

resultType的返回类型

对象类型

  • 接口的返回值是对象

  • 接口返回值是list集合,mybatis会把student对象放入list集合中

  • resultType 指定查询数据封装到那个对象中

定义接口

Student selectById(Integer id );

编辑xml映射文件

<select id = "selectById" resultType="Student">
    select id,name,age  from student where id = #{id}
</select>

<!--
	resultType使用的java类型的全限定名称,或者别名。
	表示的意思是:mybatis执行sql,把ResultSet中的数据转为Student类型的对象
Mybatis的操作:
	1. 调用Student的无参构造函数,创建对象
		Student student = new Student();//使用反射创建对象
	2. 同名的列赋值给同名的属性
		student.setId(ResultSet.getInt("id"))
		student.setName(ResultSet.getString("name"))
	3. 得到java对象
-->

简单类型

  • xml文件中执行sql语句,得到的一个值(一行一列)

  • resultType 需要指定java.long包下的数据类型

定义接口

public interface DemoUserMapper {
   long  countStudent();
}

编辑xml映射文件

<select id = "countStudent" resultType="java.lang.Long">
    select count(*) from student
</select>

Map类型

  • 执行sql语句得到的是一个Map结构数据,Mybatis执行sql,把ResultSet转为map

    sql执行结果, 列名做map的key,列值做value

    sql执行得到的是一行记录,转为map结构是正确的

    dao接口返回是一个map,sql语句最多能获取一行记录,多余一行是错误的

  • resultType 需要指定java.util.HashMap

定义接口

//查询结构返回是一个map
public interface DemoUserMapper {
  Map<Object,Object> selectMap(Integer id);
}

编辑xml映射文件

<select id = "countStudent" resultType="java.util.HashMap">
    select id,name from student where id = #{id}
</select>

关联关系

常见的关联关系

  1. 一对一

  2. 一对多

  3. 多对多

一对一

规则:使用对象封装

关联查询实现一对一查询

编写测试类

  /**
     * 完成一对一映射
     * 规定:一个员工对应一个部门
     * 选取方向:员工方
     * 需求:需要在员工中,完成部门的封装
     */
    @Test
    public void testOneToOne(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list = empMapper.findAll();
        System.out.println(list);
        sqlSession.close();
    }

编写接口

public interface EmpMapper {
    List<Emp> findAll();
    }

编写xml映射文件

<select id="findAll" resultMap="empRM">
        select e.id,e.name,e.age,d.dept_id,d.dept_name
	                from emp e,dept d
	                where e.dept_id = d.dept_id
    </select>
<!--
    规则:
        1.如果映射的字段与对象的属性一致,则可以省略不写。
        2.最好保留主键的信息
        3.如果需要封装单个对象,则使用association标签
            3.1.property代表对象的属性(名)
            3.2.javaType指定属性的类型,注意路径
        4.如果遇到关联封装,必须全部配置映射关系。
          如果属性与字段名称一致,可以使用autoMapping="true"来实现自动映射
-->
    <resultMap id="empRM" type="Emp" autoMapping="true">
        <id column="id" property="id"/>
<!--        完成dept对象的封装-->
        <association property="dept" javaType="Dept">
            <id column="dept_id" property="deptId"/>
            <result column="dept_name" property="deptName"/>
        </association>
    </resultMap>

子查询实现一对一查询

编写测试类

    @Test
    public void testOneToOne2(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list = empMapper.findAllWhere();
        System.out.println(list);
        sqlSession.close();
    }

编写接口

    List<Emp> findAllWhere();

编写xml映射文件

<!--
    子查询的说明:
            1.column="子查询的字段信息"
            2.select= "sql的ID" 作用:根据column中的数据 实现子查询!!!
-->
    <resultMap id="empRM2" type="emp" autoMapping="true">
        <id column="id" property="id"/>
        <association property="dept" javaType="Dept" column="dept_id" select="findDept"/>
    </resultMap>
    <select id="findDept" resultMap="deptRM">
        select * from dept where dept_id = #{dept_id}
    </select>
    <resultMap id="deptRM" type="Dept">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
    </resultMap>

关联查询与子查询的区别

<!--
    关联查询:通过大量的sql语句,实现数据的关联查询。其中sql语句复杂,封装简单
    子查询:通过子查询的方式实现复杂的数据封装。其中sql几乎都是单表查询,sql简单。但是数据封装复杂
-->

一对多

编写测试文件

    @Test
    public void testOneToMore(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DeptMapper deptMapper= sqlSession.getMapper(DeptMapper.class);
        List<Dept> list = deptMapper.findDept();
        System.out.println(list);
        sqlSession.close();
    }

编写接口

List<Dept> findDept();

编写xml文件

<!--
        1.关于一对多   数据封装说明:
            collection:封装集合的固定写法
                property:指定属性
                ofType: 封装list集合的泛型对象
        2.如果开启驼峰映射规则,可以简化赋值过程
        3.autoMapping="true"    自动实现映射
-->
    <select id="findDept" resultMap="CSC">
        SELECT d.dept_id , d.dept_name , e.id , e.name, e.age FROM
                dept d
	                    LEFT JOIN
                emp e
	                    ON d.dept_id = e.dept_id
    </select>
    <resultMap id="CSC" type="Dept" autoMapping="true">
        <id column="dept_id" property="deptId"/>
<!--        <id column="dept_name" property="deptName"/>-->
        <collection property="emps" ofType="Emp" autoMapping="true">
            <id column="id" property="id"/>
        </collection>
    </resultMap>

Mybatis的缓存机制

什么是缓存机制

  • 引入缓存可以有效降低用户访问物理设备的频次.提高用户响应速度.

  • 扩展: 1.mybatis自身缓存 一级缓存/二级缓存 2.Redis缓存 读取10万次/秒, 写 8.6万次/秒

一级缓存

概念说明: Mybatis默认开启一级缓存, 一级缓存可以在同一个SqlSession对象中查询相同的数据,可以实现数据的共享(缓存操作).

缓存测试

    /**
     * Mybatis一级缓存:默认开启
     *          规则:同一个SqlSession内部有效
     *                不同的SqlSession内部无效
     *          测试:
     *              看sql执行几次
     *              执行一次有缓存
     */
    @Test
    public void cache1(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list1 = empMapper.findAll();
        List<Emp> list2 = empMapper.findAll();
        List<Emp> list3 = empMapper.findAll();
        System.out.println(list1==list2);
        sqlSession.close();
    }

二级缓存

说明: 二级缓存mybatis中默认也是开启的.但是需要手动标识. 二级缓存可以在同一个SqlSessionFactory内部有效.

注:要启动全局的二级缓存,需要在其SQL映射文件中添加

<cache/>

缓存测试

    /**
     * 二级缓存说明:
     *      SqlSession查询数据之后,会将缓存信息保存到一级缓存中,但是不会立即将数据交给二级缓存保存
     *      如果需要使用二级缓存,则必须将SqlSession业务逻辑执行成功之后,再关闭
     */
    @Test
    public void cache2(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
        empMapper.findAll();
        sqlSession.close();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        EmpMapper empMapper2 = sqlSession2.getMapper(EmpMapper.class);
        empMapper2.findAll();
        sqlSession2.close();
    }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值