mybatis讲解

MYbatis讲解

什么是 MyBatis?

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

随谈

目前我只是简单的讲解mybatis的使用,如果想学到更多可以去:mybatis中文文档

这是mybatis中文文档,所以的mybatis操作都可以在上面找到,还有很多源码之类的分析

学习mybatis之前我们需要简单的了解一下maven是什么maven安装与配置

入门

打开idea,创建一个maven项目

在这里插入图片描述

maven中导入依赖的jar包(pom.xml)

<!--  导入依赖  -->
    <dependencies>
        <!--   mysql驱动     -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--   mybatis的jar包     -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <!--   junit测试jar包    -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- lombok可以注解来注入实体类的get,set等方法,在实际开发中最好不用,会报一下莫名其妙的错,如果想学习知识什么的就很好用 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
        <!-- log4j日志jar包
 		(需要配置log4j.properties文件,这里我用的mybatis自带的日志就不用log4j了)
		-->
<!--        <dependency>-->
<!--            <groupId>log4j</groupId>-->
<!--            <artifactId>log4j</artifactId>-->
<!--            <version>1.2.17</version>-->
<!--        </dependency>-->
        <!--分页要用的jar包-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!-- mybatis逆向工程maven依赖 -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.7</version>
        </dependency>
    </dependencies>

maven资源导出问题(约定大于配置)

    <!--  在build中配置resources,来防止我们资源导出失败的问题) 
 	(maven扫描时不会自动引入xml或者properties文件,加入如下代码就可以在运行时自动导入文件)
	-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

maven解决utf-8乱码问题

有时xml文件中的<?xml version="1.0" encoding="UTF-8"?>标题会报格式错,需要手动改成<?xml version="1.0" encoding="UTF8"?>需要把 - 去掉,但在maven中配置如下代码就能解决问题

<!--  解决xml中乱码问题  -->
<!--  也可以把xml中的 utf-8 改为 utf8  -->
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

我的maven配置文件

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

    <!--  父工程  -->
    <!-- 在一个文件夹内再创建maven项目,会在modules中自动新增子工程,并可以用父工程的maven依赖 -->
    <groupId>org.example</groupId>
    <artifactId>Mybatis-Study</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>mybatis-01</module>
    </modules>

    <!--  导入依赖  -->
    <dependencies>
        <!--   mysql驱动     -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--   mybatis的jar包     -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <!--   junit测试jar包    -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- lombok可以注解来注入实体类的get,set等方法,在实际开发中最好不用,会报一下莫名其妙的错,如果想学习知识什么的就很好用 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
        <!-- log4j日志jar包 -->
<!--        <dependency>-->
<!--            <groupId>log4j</groupId>-->
<!--            <artifactId>log4j</artifactId>-->
<!--            <version>1.2.17</version>-->
<!--        </dependency>-->
        <!--分页要用的jar包-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!-- mybatis逆向工程依赖 -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.7</version>
        </dependency>
    </dependencies>


    <build>
        <!--  在build中配置resources,来防止我们资源导出失败的问题  -->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
        
        <!--逆向工程-->
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.7</version>
                <configuration>
                    <!-- 输出日志 -->
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    <!--  解决xml中乱码问题  -->
    <!--  也可以把xml中的 utf-8 改为 utf8  -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

全局配置文件(mybatis-config.xml)

必须按照如下顺序来配置子标签,mybatis源码按照这样执行的

<configuration> //(配置)
	<!-- 配置顺序如下
     properties  (属性)

     settings  (设置)

     typeAliases  (类别别名)

     typeHandlers  (类别处理器)

     objectFactory  (对象工厂)

     plugins  (插件)

     environments  (环境配置)
        environment  (环境变量)
            transactionManager  (事务管理器)
            dataSource  (数据源)

	databaseldProvider  (数据库厂商标识)

     mappers (映射器)
     -->
</configuration>

子标签 我只讲常用的,详解看官方文档 关于子标签的官方文档

< properties > 属性

用来调用properties文件,用${}占位符来快速引用数据源的消息

    <!--  引入外部配置文件  -->
    <properties resource="db.properties">
<!--        可以在内部添加值        -->
        <property name="username" value="root"/>
    </properties>
< settings > 设置

开启延迟加载(懒加载): 解决n+1问题

<setting name="lazyLoadingEnabled" value="true"/>

开启二级缓存(全局缓存)

<settings name="cacheEnabled" value="true"/>

开启日志

<setting name="logImpl" value="STDOUT_LOGGING"/>  //自带的日志
<setting name="logImpl" value="LOG4J"/>           //log4j日志 需要导jar包和配置log4j的资源 log4j.properties 文件
< typeAliases > 类别别名

取别名(一般来说给实体类取别名就行了)

//第一种方式   自定义
<typeAliases>
    <typeAlias type="com.zhao.pojo.Student" alias="student"/>
</typeAliases>
//第二种方式  mybatis自己配置  可以给自己的配置类取别名 别名就是 实体类名字 第一个字母为大写其他小写
    //如:第一个方法的 Student 实体类 在com.zhao.pojo包下 别名就是Student
<typeAliases>
   <package name="com.zhao.pojo"/>
</typeAliases>
< typeHandlers > 类别处理器

用于处理 Java 类型和 Jdbc 类型之间的转换,用的不多可以不管

< objectFactory > 对象工厂

用于创建对象实例,用的不多可以不管

< plugins > 插件

可以用来配置mybatis的插件,比如pageHelper分页插件:

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
    <property name="helperDialect" value="mysql"/>
    </plugin>
</plugins>
< environments > 环境配置
**< transactionManager > ** 事务管理器

在 MyBatis 中有两种事务管理器类型(也就是 type=”[JDBC|MANAGED]”):

  • JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置。 它依赖于从数据源得 到的连接来管理事务范围。

  • MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让 容器来管理事务的整个生命周期(比如 Spring 或 JEE 应用服务器的上下文) 默认 情况下它会关闭连接。 然而一些容器并不希望这样, 因此如果你需要从连接中停止 它,将 closeConnection 属性设置为 false。

< dataSource > 数据源
  • POOLED:采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现

  • UNPOOLED:采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。

  • JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样

    <!--注册JDBC-->
    <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>
< databaseldProvider > 数据库厂商标识

MyBatis 可以根据不同的数据库厂商执行不同的语句,用的不多可以不管

< mappers > 映射器

用来配置 mapper.xml 映射文件

mapper class : 可以自动映射同一个类下同一个名字的mapper.xml文件 :比如我的 dao 类下有个 叫 UserMapper 的接口文件和 UserMapper.xml文件,就可以映射到这个文件

mapper resource : 就是很笨的导入 UserMapper.xml 文件

package name :就是自动扫描 我写的 dao 下面的所有 Mapper.xml 文件

<!--绑定接口-->
    <mappers>
        <mapper class="com.zhao.dao.UserMapper"/>
        <mapper class="com.zhao.dao.ProviderMapper"/>
<!--        <mapper resource="com.zhao.dao.UserMapper.xml" />-->
<!--        <package name="com.zhao.dao"/>-->
    </mappers>

我的mybatis-config.xml配置(放resources文件里面)

<?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核心配置文件-->
<configuration>

    <!--  引入外部配置文件  -->
    <properties resource="db.properties">
<!--        可以在内部添加值        -->
        <property name="username" value="root"/>
    </properties>


    <!--设置-->
    <settings>
        <!--标准的log4j日志工厂实现-->
<!--        <setting name="logImpl" value="LOG4J"/>-->
        
        <!--我使用的mybatis自带的日志,可以看见sql的运行流程-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        
        <!--是否开启自动驼峰命名规则(camel case)映射(配合数据库使用)-->
<!--        <setting name="mapUnderscoreToCamelCase" value="true"/>-->
        <!--显示得到开启全局缓存-->
<!--        <setting name="cacheEnabled" value="true"/>-->
    </settings>


    <!--  可以给实体类起别名  -->
    <typeAliases>
        <package name="com.zhao.pojo" />
    </typeAliases>

    <!--mybatis分页插件配置-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <property name="helperDialect" value="mysql"/>
        </plugin>
    </plugins>

    <!--注册JDBC-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>  <!--调用db.properties配置文件的设置-->
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>   
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!--绑定接口-->
    <mappers>
        <mapper class="com.zhao.dao.UserMapper"/>
        <mapper class="com.zhao.dao.ProviderMapper"/>
<!--        <mapper resource="com.zhao.dao.UserMapper.xml" />-->
<!--        <package name="com.zhao.dao"/>-->
    </mappers>

</configuration>

db.properties配置文件(就是把<environments>中的jdbc配置拿出来)

driver=com.mysql.jdbc.Driver  #导入我之前写的jar包后 不需要改
url=jdbc:mysql://localhost:3306/smbms?useSSL=true&useUnicode=true&characterEncoding=UTF-8  #放自己的数据表
username=root
password=123456

配置完后

在这里插入图片描述

使用接口实现CRUD操作

编写工具类(放utils工具包里面)

package com.zhao.utils;

//工具类
//Factiory(工厂模式)
//sqlSessionFactiory  -->   sqlSession

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

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            //使用Mybatis获取sqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream =  Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //既然有了 SqlSessionFactory,顾名思义,我们就可以从中获取SqkSession的实例了。
    //SqlSession 完全包含了面向数据库执行SQL命令所需的所有方法。

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }

}

接口

package com.zhao.dao;

import com.zhao.pojo.User;

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

public interface UserMapper {
    //查询全部用户
    List<User> getUserList();   //在mapper中的id要对象接口的名字

    //根据id查询用户
    User getUserById(int id);

    //insert一个用户
    int addUser(User user);

    //修改用户
    int updateUser(User user);

    //删除一个用户
    int daleteUser(int id);
}

Mapper.xml(写sql操作)

<?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 = 绑定一个对应的Dap/Mapper接口-->

<mapper namespace="com.zhao.dao.UserMapper">
    <!--  查询语句  -->
    <select id="getUserList" resultType="User">  <!--对应查询的名字-->
        select * from mybatis.user
    </select>

    <!--  resultType 返回类型  -->
    <!--parameterType 输入类型-->
    <select id="getUserById" parameterType="int" resultType="com.zhao.pojo.User">
        select * from mybatis.user where id = #{id}
    </select>

    <!--  增加  -->
    <insert id="addUser" parameterType="com.zhao.pojo.User">
        insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd})
    </insert>

    <!--  修改  -->
    <update id="updateUser" parameterType="com.zhao.pojo.User">
        update mybatis.user
        set name=#{name},pwd=#{pwd}
        where id = #{id};
    </update>

    <!--  刪除  -->
    <delete id="daleteUser" parameterType="int">
        delete
        from mybatis.user
        where id = #{id};
    </delete>
</mapper>

实体类

package com.zhao.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data                 //lombok注解可以快速生成get、set方法
@AllArgsConstructor   //生成有参构造
@NoArgsConstructor	  //生成无参构造
public class User {
    private int id;
    private String name;
    private String pwd;
}

测试类

package com.zhao.dao;

import com.zhao.pojo.User;
import com.zhao.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

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

public class UserMapperTest {

    @Test
    public void test(){

        //第一步:获取SqlSession对象
        SqlSession sqlSession = null;

        try{
            sqlSession = MybatisUtils.getSqlSession();
            //执行SQL
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            List<User> userList = userMapper.getUserList();

            for (User user : userList) {
                System.out.println(user);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //关闭sqlSession
            sqlSession.close();
        }
    }

    @Test
    public void getUserById(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        User user = mapper.getUserById(1);

        System.out.println(user);

        sqlSession.close();
    }

    //增删改需要提交事务,不提交事务数据库就不会有变化
    @Test
    public void addUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        int res = mapper.addUser(new User(5, "哈哈", "123456789"));
        if (res>0){
            System.out.println("插入成功!");
        }

        //提交事务
        sqlSession.commit();

        sqlSession.close();
    }

    @Test
    public void updateUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        int res = mapper.updateUser(new User(4, "呵呵", "123"));
        if (res>0){
            System.out.println("修改成功!");
        }

        //提交事务
        sqlSession.commit();

        sqlSession.close();
    }

    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        mapper.daleteUser(4);

        sqlSession.commit();
        sqlSession.close();
    }

}

注解开发(不需要mapper.xml文件)

我感觉CRUD没啥必要用注解,现阶段可以多手敲,而且如果要后期调配啥的注解很难得找(就是很难维护)没有直接写在Mapper.xml文件里面好找

值得一提的是 @Param 注解,若需要传入多个参数,可以结合 @Param 注解

​ 如:@Param(“uid”) int id 在mapper.xml文件中写sql时 只需要用 #{uid} 把传递参数时就可以把 id 值传给sql语句

   @Select("select * from user")
    List<User> getUsers();

    /*
     @Param 注解 可以引用多个值
     编写对应的sql语句时要对应 @Param 注解中的值
     只能用于基本类型 像 POJO(javaBean) 中的不能引用
    * */
    @Delete("deelete from user where id = #{uid} and name = #{uname}")
    int dedleteUser(@Param("uid") int id,@Param("uname") String name);

主键返回(增加操作时返回主键信息)

1.使用 useGeneratedKeyskeyProperty 属性

<insert id="test2" parameterType="Address" useGeneratedKeys="true" keyProperty="id">
	insert into smbms_address (contact,addressDesc,tel) values (#{contactName},#{desc},#{phone})
</insert>

2.使用**< selectKey >**子标签

<insert id="test2" parameterType="Address">
	insert into smbms_address (contact,addressDesc,tel) values (#{contactName},#{desc},#{phone})
	<selectKey keyProperty="id" order="AFTER" resultType="int" >  <!--after:在执行sql语句后执行-->
		SELECT LAST_INSERT_ID();
	</selectKey>
</insert>

此时可以用**< selectKey >标签,设置其order属性为BEFORE**,并在标签体内写上生成主键的SQL语句,这样在插入之前,会先处理**< selectKey >**,生成主键,再执行真正的插入操作。

**< selectKey >**标签其实就是一条SQL,这条SQL的执行,可以放在主SQL执行之前或之后,并且会将其执行得到的结果封装到入参的Java对象的指定属性上。注意 **< selectKey >子标签只能用在< insert >< update >**标签中。上面的 LAST_INSERT_ID() 实际上是MySQL提供的一个函数,可以用来获取最近插入或更新的记录的主键id。

测试类

    @Test
    public void test2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        AddressMapper mapper = sqlSession.getMapper(AddressMapper.class);
        Address address = new Address();
        address.setContactName("苏文绩");
        address.setDesc("重庆");
        address.setPhone("12346789");
        int i = mapper.test2(address);
        System.out.println(address.getId());
        sqlSession.commit();
        sqlSession.close();
    }

关联查询(一对多,多对一)查询

多对一:对象:association

​ 解决问题(实体类中:一个实体类对应另一个实体类):private Teacher teacher;

<?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.zhao.dao.StudentMapper">
    <!--
    思路:
        1.查询所有的学生信息
        2.根据查询出来的学生的tid,寻找对应的老师
        (类似 子查询)
    -->
    <select id="getStudent" resultMap="StudentTeacher">
--         select s.id,s.name,t.name from student s,teacher t where s.tid = t.id;
        select * from student
    </select>
    <resultMap id="StudentTeacher" type="com.zhao.pojo.Student">
        <!-- 定义主键 ,非常重要。如果是多个字段,则定义多个id -->
        <!-- property:主键在pojo中的属性名 -->
        <!-- column:主键在数据库中的列名 -->
        <result property="id" column="id" />
        <result property="name" column="name" />
        <!--
        复杂的属性,我们需要单独处理
        对象( pojo ( javaBean )): association
        集合: collection
        -->
        <association property="teacher" column="tid" javaType="com.zhao.pojo.Teacher" select="getTeacher" />
    </resultMap>
    <select id="getTeacher" resultType="Teacher">
        select * from teacher where id = #{id}
    </select>
<!--===========================================================================================================-->
    <!--按照结果嵌套处理-->
    <select id="getStudent2" resultMap="StudentTeacher2">
        select s.id sid,s.name sname,t.name tname,t.id teacherId
        from student s,teacher t
        where s.tid = t.id;
    </select>
    
    <resultMap id="StudentTeacher2" type="com.zhao.pojo.Student">
        <result property="id" column="sid" />
        <result property="name" column="sname" />
        <association property="teacher" javaType="com.zhao.pojo.Teacher" >
            <result property="id" column="teacherId" />
            <result property="name" column="tname" />
        </association>
    </resultMap>
</mapper>

一对多:集合:collection

​ 解决问题(实体类中:一个实体类对应一个List):private List< Student > students;

<?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.zhao.dao.TeacherMapper">
    <select id="getTeacher" resultMap="TeacherStudent">
        select s.id sid,s.name sname,t.name tname,t.id tid
        from student s,teacher t
        where s.tid = t.id and t.id = #{id}
    </select>    
    <resultMap id="TeacherStudent" type="com.zhao.pojo.Teacher">
        <result property="id" column="tid" />
        <result property="name" column="tname" />
        <!--
        复杂的属性,我们需要单独处理 对象:association 集合:collection
        javaType=“” 指定属性的类型
        集合中的泛型信息,我们使用ofType获取
        -->
        <collection property="students" ofType="Student">
            <result property="id" column="sid" />
            <result property="name" column="sname" />
            <result property="tid" column="tid" />
        </collection>
    </resultMap>
</mapper>

动态SQL

比如在以前的开发中,由于不确定查询参数是否存在,许多人会使用类似于where 1 = 1 来作为前缀,然后后面用AND 拼接要查询的参数,这样,就算要查询的参数为空,也能够正确执行查询,如果不加1 = 1,则如果查询参数为空,SQL语句就会变成SELECT * FROM student where,SQL不合法。

if
<!-- 示例 -->
<select id="find" resultType="student" parameterType="student">
        SELECT * FROM student WHERE age >= 18
        <if test="name != null and name != ''">
            AND name like '%${name}%'
        </if>
</select>
choose
<!-- choose 和 when , otherwise 是配套标签 
类似于java中的switch,只会选中满足条件的一个
-->
<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>
trim:基本使用where和set
where

标签只会在至少有一个子元素返回了SQL语句时,才会向SQL语句中添加WHERE,并且如果WHERE之后是以AND或OR开头,会自动将其删掉

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>
set

在至少有一个子元素返回了SQL语句时,才会向SQL语句中添加SET,并且如果SET之后是以,开头的话,会自动将其删掉

	<update id="updateBlog" parameterType="map">
        update mybatis.blog
        <set>
            <if test="title !=null">
                title=#{title},
            </if>
            <if test="author !=null">
                author=#{author}
            </if>
        </set>
        where id=#{id}
    </update>
sql

可将重复的SQL片段提取出来,然后在需要的地方,使用**< include >**标签进行引用,实现了代码的复用

<select id="findUser" parameterType="user" resultType="user">
	SELECT * FROM user
	<include refid="whereClause"/>
</select>

<sql id="whereClause">
     <where>
         <if test user != null>
         	AND username like '%${user.name}%'
         </if>
     </where>
</sql>
bind

mybatis的动态SQL都是用OGNL表达式进行解析的,如果需要创建OGNL表达式以外的变量,可以用bind标签

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>
foreach

用来做迭代拼接的,通常会与SQL语句中的IN查询条件结合使用,注意,到parameterType为List(链表)或者Array(数组),后面在引用时,参数名必须为list或者array。如在foreach标签中,collection属性则为需要迭代的集合,由于入参是个List,所以参数名必须为list

<select id="batchFind" resultType="student" parameterType="list">
        SELECT * FROM student WHERE id in
        <foreach collection="list" item="item" open="(" separator="," close=")">
          #{item}
        </foreach>
</select>

缓存

一级缓存

默认开启,同一个SqlSesion级别共享的缓存,在一个SqlSession的生命周期内,执行2次相同的SQL查询,则第二次SQL查询会直接取缓存的数据,而不走数 据库,当然,若第一次和第二次相同的SQL查询之间,执行了DML(INSERT/UPDATE/DELETE),则一级缓存会被清空,第二次查询相同SQL仍然会走数据库

  • 一级缓存在下面情况会被清除

    • 在同一个SqlSession下执行增删改操作时(不必提交),会清除一级缓存

    • SqlSession提交或关闭时(关闭时会自动提交),会清除一级缓存

    • 对mapper.xml中的某个CRUD标签,设置属性flushCache=true,这样会导致该MappedStatement的一级缓存,二级缓存都失效(一个CRUD标签在mybatis中会被封装成一个MappedStatement)

    • 在全局配置文件中设置 < setting name=“localCacheScope” value=“STATEMENT”/>,这样会使一级缓存失效,二级缓存不受影响

二级缓存

默认关闭,可通过全局配置文件中的< settings name=“cacheEnabled” value=“true”/>开启二级缓存总开关,然后在某个具体的mapper.xml中增加< cache />,即开启了该mapper.xml的二级缓存。二级缓存是mapper级别的缓存,粒度比一级缓存大,多个SqlSession可以共享同一个mapper的二级缓存。注意开启二级缓存后,SqlSession需要提交,查询的数据才会被刷新到二级缓存当中

插件:PageHelper分页插件

注意:在编写mapper.xml的时候,SQL语句的结尾不要带上;,因为PageHelper插件是在SQL末尾拼接LIMIT关键字来进行分页的,若SQL语句带上了;,就会造成SQL语法错误

在pom.xml配置maven依赖

<dependency>
	<groupId>com.github.pagehelper</groupId>
	<artifactId>pagehelper</artifactId>
	<version>5.1.6</version>
</dependency>

在mybatis全局配置文件里面添加插件的标签

<plugins>
	<plugin interceptor="com.github.pagehelper.PageInterceptor">
		<property name="helperDialect" value="mysql"/>
	</plugin>
</plugins>

测试类

    @Test
    public void test1(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        PageHelper.startPage(2,3);    //第二页,三条数据
        /*要在打印出来之前写,不然就直接打印出来全部了*/

        List<User> users = mapper.test1();
        users.forEach(System.out::println);
        sqlSession.close();
    }
结果

我用了日志,出了红色框中的选项,其他的都是日志,日志也就是使用了动态代理,看java执行了哪些操作

在这里插入图片描述

逆向工程

在maven中配置依赖和添加插件

依赖

        <!-- mybatis逆向工程maven依赖 -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.7</version>
        </dependency>

插件

<!--逆向工程插件-->
	<build>
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.7</version>
                <configuration>
                    <!-- 输出日志 -->
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
        </plugins>
    </build>

在resources下面创建一个文件叫 generatorConfig.xml

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NsXzw69G-1647414513112)(C:\Users\18358\AppData\Roaming\Typora\typora-user-images\image-20220316120445246.png)]

generatorConfig.xml 中的配置

需要修改的地方:我用 注释出来

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <!--导入属性配置-->
    <properties resource="db.properties"/>                                   <!--========改自己的properties的名字=========-->

    <!-- 指定数据库驱动的jdbc驱动jar包的位置 -->
    <classPathEntry location="D:\idea\Maven\apache-maven-3.8.4\maven-repo\mysql\mysql-connector-java\5.1.47\mysql-connector-java-5.1.47.jar" />                                                                       <!--========改驱动jar包位置=========-->
    <!-- context 是逆向工程的主要配置信息 -->
    <!-- id:起个名字 -->
    <!-- targetRuntime:设置生成的文件适用于那个 mybatis 版本 -->
    <context id="default" targetRuntime="MyBatis3">
        <!--optional,旨在创建class时,对注释进行控制-->
        <commentGenerator>
            <property name="suppressDate" value="true" />
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!--jdbc的数据库连接-->                                                 <!--========改properties中对应的名字=========-->
        <jdbcConnection driverClass="${driver}"                                    
                        connectionURL="${url}"
                        userId="${username}"
                        password="${password}">
        </jdbcConnection> 
        <!--非必须,类型处理器,在数据库类型和java类型之间的转换控制-->
        <javaTypeResolver>
            <!-- 默认情况下数据库中的 decimal,bigInt 在 Java 对应是 sql 下的 BigDecimal 类 -->
            <!-- 不是 double 和 long 类型 -->
            <!-- 使用常用的基本类型代替 sql 包下的引用类型 -->
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- targetPackage:生成的实体类所在的包 -->
        <!-- targetProject:生成的实体类所在的硬盘位置 -->                                  <!--=========改路径========-->
        <javaModelGenerator targetPackage="com.zhao.pojo"
                            targetProject=".\src\main\java">
            <!-- 是否允许子包 -->
            <property name="enableSubPackages" value="false" />
            <!-- 是否清理从数据库中查询出的字符串左右两边的空白字符 -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!-- targetPackage 和 targetProject:生成的 mapper.xml 文件的包和位置 -->                <!--========改路径=========-->
        <sqlMapGenerator targetPackage="com.zhao.dao"                                    
                         targetProject=".\src\main\java">
            <!-- 针对数据库的一个配置,是否把 schema 作为字包名 -->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>

        <!-- targetPackage 和 targetProject:生成的 mapper接口文件的包和位置 -->                <!--========改路径=========-->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.zhao.dao" targetProject=".\src\main\java">
            <!-- 针对 oracle 数据库的一个配置,是否把 schema 作为子包名 -->
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>
        <!-- 这里指定要生成的数据库中的表 -->
        <!-- tableName:对应表名  domainObjectName:对应自己想创建的类名 -->
        <table tableName="smbms_address" domainObjectName="Address"/>                      <!--========改=========-->
        <table tableName="smbms_bill" domainObjectName="Bill"/>
    </context>
</generatorConfiguration>

idea右侧有个maven打开,双击mybatis-generator:generate

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JuCfWpV5-1647414513113)(C:\Users\18358\AppData\Roaming\Typora\typora-user-images\image-20220316140251027.png)]

运行完成,逆向工程结束

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3w005rxn-1647414513114)(C:\Users\18358\AppData\Roaming\Typora\typora-user-images\image-20220316140529240.png)]
有讲的不好的地方,欢迎大家指出

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我认不到你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值