mybatis


title: 1 mybatis


mybatis_第1张图片

文章目录

      • 一、引言
        • 1.1 什么是框架?
        • 1.2 什么是ORM框架?
        • 1.3 使用JDBC完成ORM操作的缺点?
      • 二、MyBatis框架
        • 2.1 概念
        • 2.2 访问与下载
      • 三、构建Maven项目
        • 3.1 创建工程
        • 3.2 在工程下创建module
      • 四、MyBatis环境搭建【`重点`】
        • 4.1 pom.xml中引入MyBatis核心依赖
        • 4.2 创建MyBatis配置文件
      • 五、MyBatis开发步骤【`重点`】
        • 5.1 建表
        • 5.2 定义实体类
        • 5.3 定义DAO接口
        • 5.4 编写Mapper.xml
        • 5.5 注册Mapper
        • 5.6 测试一
        • 5.7 测试二【了解】
      • 六、细节补充
        • 6.1 解决mapper.xml存放在resources以外路径中的读取问题
        • 6.2 properties配置文件
        • 6.3 类型别名
        • 6.4 创建log4j配置文件
      • 七、MyBatis的CRUD操作【`重点`】
        • 7.1 查询
          • 7.1.1 序号参数绑定
          • 7.1.2 注解参数绑定【推荐】
          • 7.1.3 Map参数绑定
          • 7.1.4 对象参数绑定
          • 7.1.5 模糊查询
        • 7.2 删除
        • 7.3 修改
        • 7.4 添加
        • 7.5 主键回填
          • 7.5.1 通过last_insert_id()查询主键
          • 7.5.2 通过uuid()查询主键
      • 八、MyBatis工具类【`重点`】
        • 8.1 封装工具类
        • 8.2 测试工具类
      • 九、ORM映射【`重点`中的重点】
        • 9.1 MyBatis自动ORM失效
        • 9.2 方案一:列的别名
        • 9.3 方案二:结果映射(ResultMap - 查询结果的封装规则)
      • 十、MyBatis处理关联关系-多表连接【`重点`】
        • 10.1 OneToOne
        • 10.2 OneToMany
        • 10.3 ManyToMany
        • 10.4 关系总结
      • 十一、动态SQL【`重点`】
        • 11.1 < sql >
        • 11.2 < if >
        • 11.3 < where >
        • 11.4 < set >
        • 11.5 < trim >
        • 11.6 < foreach >
      • 十二、缓存(Cache)【`重点`】
        • 12.1 一级缓存
        • 12.2 二级缓存
          • 12.2.1 开启全局缓存
          • 12.2.2 指定Mapper缓存
          • 12.2.3 缓存清空并重新缓存
      • 十三、Druid连接池
        • 13.1 概念
        • 13.2 不同连接池对比
          • 13.2.1 测试环境
          • 13.2.2 基准测试结果对比
          • 13.2.3 测试结论
        • 13.3 配置pom.xml
        • 13.4 创建DruidDataSourceFactory
        • 13.5 修改mybatis-config.xml
      • 十四、PageHelper
        • 14.1 概念
        • 14.2 访问与下载
        • 14.3 开发步骤
          • 14.3.1 引入依赖
          • 14.3.2 配置MyBatis-config.xml
          • 14.3.3 PageHelper应用方式
        • 14.4 PageInfo对象
          • 14.4.1 PageInfo应用方式
          • 14.4.2 注意事项
          • 14.4.3 分页练习
      • 十五、补充【记住】
        • 15.1 MyBatis注解操作
          • 15.1.1 查询
          • 15.1.2 删除
          • 15.1.3 修改
          • 15.1.4 插入
        • 15.2 $符号的应用场景
          • 15.2.1 $符号参数绑定
          • 15.2.2 $符号注入攻击
        • 15.3 MyBatis处理关联关系-嵌套查询【了解】
          • 15.3.1 主表查询
          • 15.3.2 及联调用
          • 定义selectDepartmentById,并书写Mapper,实现根据部门ID查询部门信息,并及联查询该部门员工信息
          • 15.3.3 延迟加载
          • mybatis-config.xml中开启延迟加载
      • 十六. 逆向工程
          • 15.3.2 及联调用
          • 定义selectDepartmentById,并书写Mapper,实现根据部门ID查询部门信息,并及联查询该部门员工信息
          • 15.3.3 延迟加载
          • mybatis-config.xml中开启延迟加载
      • 十六. 逆向工程

一、引言


1.1 什么是框架?

工具类— >组件---- > 框架 -----> 平台

软件的半成品,解决了软件开发过程当中的普适性问题,从而简化了开发步骤,提供了开发的效率。

1.2 什么是ORM框架?

  • ORM(Object Relational Mapping)对象关系映射,将程序中的一个对象与表中的一行数据一一对应。
  • ORM框架提供了持久化类与表的映射关系,在运行时参照映射文件的信息,把对象持久化到数据库中`。

1.3 使用JDBC完成ORM操作的缺点?

  • 存在大量的冗余代码。

  • 手工创建 Connection、Statement 等。

  • 手工将结果集封装成实体对象。

  • 查询效率低,没有对数据访问进行过优化(Not Cache)。

二、MyBatis框架


2.1 概念

  • MyBatis本是Apache软件基金会的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了Google Code,并且改名为MyBatis 。2013年11月迁移到Github。
  • MyBatis是一个优秀的基于Java的持久层框架,支持自定义SQL,存储过程和高级映射。
  • MyBatis对原有JDBC操作进行了封装,几乎消除了所有JDBC代码,使开发者只需关注 SQL 本身。
  • MyBatis可以使用简单的XML或Annotation来配置执行SQL,并自动完成ORM操作,将执行结果返回。

2.2 访问与下载

官方网站:http://www.mybatis.org/mybatis-3/

下载地址:https://github.com/mybatis/mybatis-3/releases/tag/mybatis-3.5.1

三、构建Maven项目


3.1 创建工程

创建空的工程
mybatis_第2张图片

3.2 在工程下创建module

mybatis_第3张图片

四、MyBatis环境搭建【重点


4.1 pom.xml中引入MyBatis核心依赖

在pom.xml中引入相关依赖



<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.0modelVersion>

    
    <groupId>com.qfgroupId>
    <artifactId>hello-mybatisartifactId>
    <version>1.0-SNAPSHOTversion>

    
    <dependencies>
        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.4.6version>
        dependency>

        
      <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>8.0.21version>
        dependency>
        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.12version>
        dependency>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
            <scope>testscope>
        dependency>
        
	  dependencies>
project>

4.2 创建MyBatis配置文件

创建并配置mybatis-config.xml


DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-config.dtd">


<configuration>
    
    <environments default="MySqlDB">
        
        <environment id="MySqlDB">
            
            <transactionManager type="JDBC"/>
            
       <dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSourceFactory">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                
                <property name="url" value="jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            dataSource>
        environment>
    environments>

    
    <mappers>
        
        <mapper resource="xxxMapper.xml"/>
    mappers>
configuration>
  • 注意:mapper.xml默认建议存放在resources中,路径不能以/开头

五、MyBatis开发步骤【重点


5.1 建表

create table t_users(
  id int primary key auto_increment,
  name varchar(50),
  password varchar(50),
  sex varchar(1),
  birthday datetime,
  registTime datetime
)default charset = utf8;

5.2 定义实体类

定义所需CURD操作的实体类

package com.glls.mybatis.pojo;

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

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Integer id;
    private String name;
    private String password;
    private String sex;
    private Date birthday;
    private Date registTime;

}

5.3 定义DAO接口

根据所需DAO定义接口、以及方法

package com.qf.mybatis.mapper;

import com.qf.mybatis.pojo.User;


public interface UserMapper {

    public User selectUserById(Integer id);

}

5.4 编写Mapper.xml

在resources目录中创建Mapper.xml文件


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.glls.mybatis.mapper.UserMapper">
    
    <select id="selectUserById" resultType="com.glls.mybatis.pojo.User" >
        
        select * from t_users where id = #{arg0}
    select>
mapper>

5.5 注册Mapper

将Mapper.xml注册到mybatis-config.xml中 这块配置 是写在主配置文件中

mybatis_第4张图片


<mappers>
    
    <mapper resource="UserMapper.xml">mapper>
mappers>

5.6 测试一

MyBatis的API操作方式

打开UserMapper接口 在这个接口身上 点右键 如下图操作

mybatis_第5张图片

mybatis_第6张图片

package com.glls.mybatis.mapper;

import com.glls.mybatis.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.Test;

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

import static org.junit.Assert.*;

/**
 * @date 2023/4/15
 * @desc
 * mybatis 入门案例
 *
 * 1.添加相关依赖
 * 2.主配置文件   cv
 *    需要注意  在主配置文件中的 映射文件的配置
 * 3.创建Mapper 接口
 *
 * 4. 创建 与Mapper 接口 与之对应的映射文件
 *
 * 5. 相关API的使用
 */
public class UserMapperTest {

    @Test
    public void selectUserById() throws IOException {

        //1. 加载mybatis 的主配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");

        //2. 创建SqlSessionFactory  连接对象工厂
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //3. 得到sqlSession 对象

        SqlSession sqlSession = sqlSessionFactory.openSession();

        //4. 调用sqlSession 的方法
        //User o = sqlSession.selectOne("com.glls.mybatis.mapper.UserMapper.selectUserById", 8);

        //接口指向实现类对象    底层 肯定是 基于 接口 和 映射文件 创建了 实现类的对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        User user = mapper.selectUserById(8);

        System.out.println(user);
    }
}

5.7 测试二【了解】

iBatis传统操作方式

package com.qf.mybatis.part1.basic;

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.Test;

import java.io.IOException;
import java.io.InputStream;

public class HelloMyBatis {

    @Test
    public void test2() throws IOException {
		//1.获得读取MyBatis配置文件的流对象
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

        //2.构建SqlSession连接对象的工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);

        //3.通过工厂获得连接对象
        SqlSession sqlSession = factory.openSession();

        //4.通过连接对象直接调用接口中的方法
		Object o = sqlSession.selectOne("com.qf.mybatis.part1.basic.UserMapper.selectUserById", 1);
      
      	System.out.println(o);
    }
}

六、细节补充


6.1 解决mapper.xml存放在resources以外路径中的读取问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tXN6iqhY-1683019801698)(Pictures/image-20230415174042785.png)]

在pom.xml文件最后追加< build >标签,以便可以将xml文件复制到classes中,并在程序运行时正确读取。

    <build>
        
        <resources>
            <resource>
                <directory>src/main/javadirectory>
                <includes>
                    <include>**/*.xmlinclude>
                includes>
            resource>
            <resource>
                <directory>src/main/resourcesdirectory>
                <includes>
                    <include>**/*.xmlinclude>
                    <include>**/*.propertiesinclude>
                    <include>**/*.iniinclude>
                includes>
            resource>
        resources>
    build>

6.2 properties配置文件

对于mybatis-config.xml的核心配置中,如果存在需要频繁改动的数据内容,可以提取到properties中。

#db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username=root
password=123456

修改mybatis-config.xml。


DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	
    <properties resource="db.properties" />

    <environments default="MySqlDB">
        <environment id="MySqlDB">
            <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>
        <mapper resource="UserMapper.xml" />
    mappers>
configuration>

6.3 类型别名

为实体类定义别名,提高书写效率。


DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <properties ... />
    
    
    <typeAliases>
        

        
        <package name="com.glls.mybatis.pojo"/>
    typeAliases>
  
  	...
configuration>

6.4 创建log4j配置文件

pom.xml添加log4j依赖


<dependency>
		<groupId>log4jgroupId>
		<artifactId>log4jartifactId>
		<version>1.2.17version>
dependency>

创建并配置log4j.properties

# Global logging configuration     全局的日志级别为 warn
log4j.rootLogger=warn, Console
# MyBatis logging configuration...   StudentMapper 这个包下的日志级别为   TRACE
log4j.logger.com.glls.mybatis.mapper.UserMapper=TRACE
# Console output...
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%5p %d [%t] - %m%n
级别 描述
ALL LEVEL 打开所有日志记录开关;是最低等级的,用于打开所有日志记录。
DEBUG 输出调试信息;指出细粒度信息事件对调试应用程序是非常有帮助的。
INFO 输出提示信息;消息在粗粒度级别上突出强调应用程序的运行过程。
WARN 输出警告信息;表明会出现潜在错误的情形。
ERROR 输出错误信息;指出虽然发生错误事件,但仍然不影响系统的继续运行。
FATAL 输出致命错误;指出每个严重的错误事件将会导致应用程序的退出。
OFF LEVEL 关闭所有日志记录开关;是最高等级的,用于关闭所有日志记录。

七、MyBatis的CRUD操作【重点


7.1 查询

标签:< select id=“” resultType=“” >

7.1.1 序号参数绑定
public interface UserMapper {
		//使用原生参数绑定
    public User selectUserByIdAndPwd(Integer id , String pwd);
}
<select id="selectUserByIdAndPwd" resultType="user">
    SELECT * FROM t_users
    WHERE id = #{arg0} AND password = #{arg1} 
select>

<select id="selectUserByIdAndPwd" resultType="user">
	SELECT * FROM t_users
    WHERE id = #{param1} AND password = #{param2} 
select>
7.1.2 注解参数绑定【推荐】
import org.apache.ibatis.annotations.Param; //引入注解

public interface UserMapper {
    //使用MyBatis提供的@Param进行参数绑定
    public User selectUserByIdAndPwd(@Param("id") Integer id , @Param("pwd") String pwd);
}
<select id="selectUserByIdAndPwd" resultType="user">
   SELECT * FROM t_users
        WHERE id = #{id} AND password = #{password} 
select>
7.1.4 对象参数绑定
public interface UserMapper {
    //使用对象属性进行参数绑定
    public User selectUserByUserInfo(User user);
}
<select id="selectUserByUserInfo" resultType="user">
    SELECT * FROM t_users
    WHERE id = #{id} AND password = #{password} 
select>
7.1.5 模糊查询
public interface UserMapper {
    public List<User> selectUsersByKeyword(@Param("keyword") String keyword);
}
<mapper namespace="com.qf.mybatis.part1.different.UserMapper">
    <select id="selectUsersByKeyword" resultType="user">
        SELECT * FROM t_users 
  		WHERE name LIKE concat('%',#{keyword},'%') 
    select>
mapper>

7.2 删除

标签:< delete id=“” parameterType=“” >

 <delete id="deleteUser" parameterType="int">
    DELETE FROM t_users
    WHERE id = #{id} 
delete>

7.3 修改

标签:< update id=“” parameterType=“” >

<update id="updateUser" parameterType="user">
    UPDATE t_users SET name=#{name}, password=#{password}, sex=#{sex}, birthday=#{birthday}
    WHERE id = #{id} 
update>

7.4 添加

标签:< insert id=“” parameterType=“” >


<insert id="insertUser" parameterType="user">
    INSERT INTO t_users VALUES(#{id},#{name},#{password},#{sex},#{birthday},NULL);
insert>


<insert id="insertUser" parameterType="user">
	
    INSERT INTO t_users VALUES(#{id},#{name},#{password},#{sex},#{birthday},NULL);
	INSERT INTO t_users VALUES(NULL,#{name},#{password},#{sex},#{birthday},NULL);
insert>

7.5 主键回填

标签:< selectKey id=“” parameterType=“” order=“AFTER|BEFORE”>

7.5.1 通过last_insert_id()查询主键
CREATE TABLE `t_product` (
  `productid` int(11) NOT NULL AUTO_INCREMENT,
  `productname` varchar(100) DEFAULT NULL,
  `brand` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`productid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
    private Integer productId;

    private String productName;

    private String brand;

}

<mapper namespace="com.glls.mybatis.mapper.ProductMapper">
    <insert id="insertProduct">
        /*主键回填    在插入语句执行之后  查询刚刚插入的 记录 的 id  赋值给 productId */
        <selectKey keyProperty="productId" resultType="int" order="AFTER" >
            select last_insert_id()
        selectKey>

        insert into t_product (productId,productName,brand) values (null,#{productName},#{brand})
    insert>
mapper>
7.5.2 通过uuid()查询主键
CREATE TABLE `t_order2` (
  `id` varchar(100) NOT NULL,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {

    private String id;
    
    private String name;
}
<mapper namespace="com.glls.mybatis.mapper.OrderMapper">

    <insert id="insertOrder">
        
        <selectKey keyProperty="id" resultType="string" order="BEFORE">
            select REPLACE(UUID(),'-','') 
        selectKey>

        insert into t_order2 (id,name) values (#{id},#{name});
    insert>
mapper>

八、MyBatis工具类【重点


8.1 封装工具类

  • Resource:用于获得读取配置文件的IO对象,耗费资源,建议通过IO一次性读取所有所需要的数据。

  • SqlSessionFactory:SqlSession工厂类,内存占用多,耗费资源,建议每个应用只创建一个对象。

  • SqlSession:相当于Connection,可控制事务,应为线程私有,不被多线程共享。

  • 将获得连接、关闭连接、提交事务、回滚事务、获得接口实现类等方法进行封装。

package com.qf.mybatis.part1.utils;

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.InputStream;

public class MyBatisUtils {

  	//获得SqlSession工厂
    private static SqlSessionFactory factory;

  	//创建ThreadLocal绑定当前线程中的SqlSession对象
    private static final ThreadLocal<SqlSession> tl = new ThreadLocal<SqlSession>();

    static {
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            factory = new SqlSessionFactoryBuilder().build(is);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获得连接(从tl中获得当前线程SqlSession)
    public static SqlSession openSession(){
        SqlSession session = tl.get();
        if(session == null){
            session = factory.openSession();
            tl.set(session);
        }
        return session;
    }

    //释放连接(释放当前线程中的SqlSession)
    public static void closeSession(){
        SqlSession session = tl.get();
        session.close();
        tl.remove();
    }

    //提交事务(提交当前线程中的SqlSession所管理的事务)
    public static void commit(){
        SqlSession session = openSession();
        session.commit();
        closeSession();
    }

    //回滚事务(回滚当前线程中的SqlSession所管理的事务)
    public static void rollback(){
        SqlSession session = openSession();
        session.rollback();
        closeSession();
    }

    //获得接口实现类对象
    public static <T extends Object> T getMapper(Class<T> clazz){
        SqlSession session = openSession();
        return session.getMapper(clazz);
    }
}

8.2 测试工具类

调用MyBatisUtils中的封装方法。

@Test
public void testUtils() {
    try {
				UserMapper userMapper = MyBatisUtils.getMapper(UserMapper.class);
				userMapper.deleteUser(15);
				MyBatisUtils.commit();
		} catch (Exception e) {
				MyBatisUtils.rollback();
				e.printStackTrace();
		}
}

九、ORM映射【重点中的重点】


9.1 MyBatis自动ORM失效

MyBatis只能自动维护库表”列名“与”属性名“相同时的一一对应关系,二者不同时,无法自动ORM。

自动ORM失效
mybatis_第7张图片

9.2 方案一:列的别名

在SQL中使用 as 为查询字段添加列别名,以匹配属性名。


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.glls.mybatis.mapper.ManagerMapper">


    <select id="selectManagerByIdAndPwd" resultType="com.glls.mybatis.pojo.Manager">
        select mgr_id as id,mgr_name as name,mgr_pwd as password from t_managers where mgr_id = #{id} and mgr_pwd=#{pwd}
    select>

mapper>

9.3 方案二:结果映射(ResultMap - 查询结果的封装规则)

通过< resultMap id=“” type=“” >映射,匹配列名与属性名。


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.glls.mybatis.mapper.ManagerMapper">


    <resultMap id="managerResultMap" type="manager">
        <id property="id" column="mgr_id">id>
        <result property="name" column="mgr_name">result>
        <result property="password" column="mgr_pwd">result>
    resultMap>

    <select id="selectManagerByIdAndPwd2" resultMap="managerResultMap">
        select * from t_managers where mgr_id = #{id} and mgr_pwd=#{pwd}
    select>
mapper>

十、MyBatis处理关联关系-多表连接【重点


实体间的关系:关联关系(拥有 has、属于 belong)

  • OneToOne:一对一关系(Passenger— Passport)

  • OneToMany:一对多关系(Employee — Department)

  • ManyToMany:多对多关系(Student — Subject)

Table建立外键关系
mybatis_第8张图片
Entity添加关系属性
mybatis_第9张图片
Mapper中将属性与列名对应
mybatis_第10张图片

10.1 OneToOne

SQL

DROP TABLE IF EXISTS `t_passenger`;

CREATE TABLE `t_passenger` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `sex` varchar(32) DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='乘客';

/*Data for the table `t_passenger` */

insert  into `t_passenger`(`id`,`name`,`sex`,`birthday`) values (1,'zs','男','2021-07-29'),(2,'lss','女','2021-07-28');


DROP TABLE IF EXISTS `t_passport`;

CREATE TABLE `t_passport` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nationality` varchar(32) DEFAULT NULL,
  `expire` date DEFAULT NULL,
  `passenger_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

/*Data for the table `t_passport` */

insert  into `t_passport`(`id`,`nationality`,`expire`,`passenger_id`) values (1,'中国','2023-07-29',1),(2,'韩国','2023-07-28',2);

pojo

package com.glls.mybatis.pojo;

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

import java.util.Date;

/**
 * @date 2023/4/17
 * @desc 乘客
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Passenger {

    private Integer id;

    private String name;

    private String sex;

    private Date birthday;

    private Passport passport;

    //private Integer passportId;
    //
    //private String nationality;
    //
    //private Date expire;


}

package com.glls.mybatis.pojo;

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

import java.util.Date;

/**
 * @date 2023/4/17
 * @desc  护照
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Passport {

    private Integer id;

    private String nationality;

    private Date expire;

    private  Integer passenger_id;

}

<mapper namespace="com.glls.mybatis.mapper.PassengerMapper">

  	
    <resultMap id="passengerResultMap" type="passenger">
        <id property="id" column="id"/>
        <result property="name" column="name" />
        <result property="sex" column="sex" />
        <result property="birthday" column="birthday" />

      		 
        <association property="passport" javaType="passport">
             <id property="id" column="passportId">id>
            <result property="nationality" column="nationality">result>
            <result property="expire" column="expire">result>
            <result property="passenger_id" column="passenger_id">result>
        association>
    resultMap>

  						  	
    <select id="selectPassengerById" resultMap="passengerResultMap">
        
        SELECT p1.id , p1.name , p1.sex , p1.birthday , p2.id as passportId , p2.nationality , p2.expire 			, p2.passenger_id
        FROM t_passengers p1 LEFT JOIN t_passports p2
        ON p1.id = p2.passenger_id
        WHERE p1.id = #{id}
    select>
mapper>
  • 注意:指定“一方”关系时(对象),使用< association javaType=“” >

作业: 查询 护照的时候 把对应的乘客 也查询出来

10.2 OneToMany

SQL参考

DROP TABLE IF EXISTS `t_departments`;

CREATE TABLE `t_departments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `location` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

/*Data for the table `t_departments` */

insert  into `t_departments`(`id`,`name`,`location`) values (1,'研发部','杭州'),(2,'市场部','上海');


@Data
@AllArgsConstructor
@NoArgsConstructor
public class Department {

    private Integer id;

    private String name;

    private String location;

}
DROP TABLE IF EXISTS `t_employees`;

CREATE TABLE `t_employees` (
  `eid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `salary` double DEFAULT NULL,
  `dept_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`eid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

/*Data for the table `t_employees` */

insert  into `t_employees`(`eid`,`name`,`salary`,`dept_id`) values (1,'zs',88888,1),(2,'ls',77777,1);
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {

    private Integer eid;

    private String name;

    private Double salary;

    private Integer dept_id;
}

DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.glls.mybatis.mapper.DepartmentMapper">
    
    <resultMap id="rs2" type="department">

        <id property="id" column="id">id>
        <result property="name" column="name">result>
        <result property="location" column="location">result>


        		
        <collection property="emps" ofType="employee">
            <id property="eid" column="eid">id>
            <result property="name" column="ename">result>
            <result property="salary" column="salary" />
            <result property="dept_id" column="dept_id" />
        collection>
    resultMap>
    
    <select id="findById" resultMap="rs2">
        
        select t1.*,t2.eid,t2.name as ename,t2.salary,t2.dept_id from
        t_departments t1 join t_employees t2
        on t1.id = t2.dept_id where t1.id = #{id};
    select>
mapper>
  • 注意:指定“多方”关系时(集合),使用< collection ofType=“” >

作业: 查询员工 同时 把 员工所属的部门信息查询出来

10.3 ManyToMany

SQL

DROP TABLE IF EXISTS `t_students`;

CREATE TABLE `t_students` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `sex` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

/*Data for the table `t_students` */

insert  into `t_students`(`id`,`name`,`sex`) values (1,'Tom','M'),(2,'Jack','M'),(3,'Marry','F'),(4,'Annie','F');
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Integer id;
    private String name;
    private String sex;

    //学科
    private List<Subject> subjects;
}
DROP TABLE IF EXISTS `t_subjects`;

CREATE TABLE `t_subjects` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `grade` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

/*Data for the table `t_subjects` */

insert  into `t_subjects`(`id`,`name`,`grade`) values (1,'JavaSe','1'),(2,'JavaWeb','2'),(3,'FrameWork','3'),(4,'MicroService','4');

中间表

DROP TABLE IF EXISTS `t_stu_sub`;

CREATE TABLE `t_stu_sub` (
  `student_id` int(11) DEFAULT NULL,
  `subject_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

/*Data for the table `t_stu_sub` */

insert  into `t_stu_sub`(`student_id`,`subject_id`) values (1,1),(1,2),(2,1),(3,1);
建立第三张关系表
mybatis_第11张图片

DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.glls.mybatis.mapper.StudentMapper">
    
    <resultMap id="rs3" type="student">
        <id property="id" column="id">id>
        <result property="name" column="name">result>
        <result property="sex" column="sex">result>
        <collection property="subjects" ofType="subject">
            <id property="id" column="subjectId">id>
            <result property="name" column="subjectName">result>
            <result property="grade" column="grade">result>
        collection>
    resultMap>
    
    <select id="findAll" resultMap="rs3" >
        select t1.*,t3.id as subjectId,t3.name as subjectName ,t3.grade from t_students t1
        join t_stu_sub t2 on t1.id = t2.student_id
        join t_subjects t3 on t2.subject_id = t3.id
    select>
mapper>
  • 注意:指定“多方”关系时(集合),使用< collection ofType=“” >

作业 查询学科信息 同时 把学科的学生信息查询出来

10.4 关系总结

一方,添加集合;多方,添加对象。

双方均可建立关系属性,建立关系属性后,对应的Mapper文件中需使用< ResultMap >完成多表映射。

持有对象关系属性,使用< association property=“dept” javaType=“department” >

持有集合关系属性,使用< collection property=“emps” ofType=“employee” >

十一、动态SQL【重点


MyBatis的映射文件中支持在基础SQL上添加一些逻辑操作,并动态拼接成完整的SQL之后再执行,以达到SQL复用、简化编程的效果。

准备表

DROP TABLE IF EXISTS `t_books`;

CREATE TABLE `t_books` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `author` varchar(32) DEFAULT NULL,
  `publish` date DEFAULT NULL,
  `sort` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

/*Data for the table `t_books` */

insert  into `t_books`(`id`,`name`,`author`,`publish`,`sort`) values (8,'springcloud','java','2022-07-08',3),(16,'springboot','尤雨曦2','2021-10-22',NULL),(18,'springmvc','xxxooo','2022-04-14',2),(21,'springmvc','xxxooo','2022-04-14',2),(22,'spring','xxx','2022-07-08',NULL),(23,'springmvc','123','2022-07-08',NULL),(25,'springcloud','xxx',NULL,NULL),(26,'vue3','尤雨曦',NULL,NULL),(27,'vue','尤雨曦',NULL,NULL);

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {

    private Integer id;

    private String name;

    private String author;

    private Date publish;

    private Integer sort;
}

11.1 < sql >


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.glls.mybatis.mapper.BookMapper">
    
    <sql id="books_field">
        SELECT id,name,author,publish,sort
    sql>
    <select id="selectBookByCondition" resultType="com.glls.mybatis.pojo.Book">
        
        <include refid="books_field">include>
        from t_books
    select>
mapper>

11.2 < if >

<select id="selectBookByCondition" resultType="com.glls.mybatis.pojo.Book">
        
        <include refid="books_field">include>
        from t_books
        <where>
        <if test="name!=null and name != ''">
            name=#{name}
        if>
        <if test="author!=null and author != '' ">
            and author=#{author}
        if>
        where>
    select>

11.3 < where >

<select id="selectBookByCondition" resultType="com.glls.mybatis.pojo.Book">
    SELECT id , name , author , publish , sort
    FROM t_books
    <where> 
        <if test="id != null"> 
            id = #{id}
        if>

        <if test="name != null">
            and name = #{name}
        if>

        <if test="author != null">
            and author = #{author}
        if>

        <if test="publish != null">
            and publish = #{publish}
        if>

        <if test="sort != null">
            and sort = #{sort}
        if>
    where>
select>

11.4 < set >

<update id="updateBookByCondition">
    UPDATE t_books
    <set>
        <if test="name != null">
            name = #{name} ,
        if>

        <if test="author != null">
            author = #{author} ,
        if>

        <if test="publish != null">
            publish = #{publish} ,
        if>

        <if test="sort != null">
            sort = #{sort} ,
        if>
    set>
    WHERE id = #{id}
update>

11.5 < trim >

< trim prefix=“” suffix=“” prefixOverrides=“” suffixOverrides=“” >代替< where > 、< set >

<select id="selectBookByCondition" resultType="com.qf.mybatis.day2.dynamic.Book">
		SELECT id,name,author,publish,sort
    FROM t_books
    <trim prefix="WHERE" prefixOverrides="AND|OR"> 
        <if test="id != null">
            and id = #{id}
        if>

        <if test="name != null">
            and name = #{name}
        if>

        <if test="author != null">
            and author = #{author}
        if>

        <if test="publish != null">
            and publish = #{publish}
        if>

        <if test="sort != null">
            and sort = #{sort}
        if>
		trim>
select>
<update id="updateBookByCondition">
		UPDATE t_books
		<trim prefix="SET" suffixOverrides=","> 
				<if test="name != null">
						name = #{name} ,
				if>

				<if test="author != null">
						author = #{author} ,
				if>

				<if test="publish != null">
						publish = #{publish} ,
				if>

				<if test="sort != null">
						sort = #{sort}
				if>
    trim>
		WHERE id = #{id}
update>

11.6 < foreach >

批量删除
<delete id="deleteBookByIds">
		DELETE FROM t_books
		WHERE id IN
		<foreach collection="list" open="(" separator="," close=")"  item="id" index="i">
				#{id}
		foreach>
delete>



-----批量添加
   <insert id="addBooks">
        insert into t_books values
        <foreach collection="list" item="book"  separator=",">
            (null,#{book.name},#{book.author},#{book.publish},#{book.sort})
        foreach>
    insert>
参数 描述 取值
collection 容器类型 list、array、map
open 起始符 (
close 结束符 )
separator 分隔符 ,
index 下标号 从0开始,依次递增
item 当前项 任意名称(循环中通过 #{任意名称} 表达式访问)

十二、缓存(Cache)【重点


内存中的一块存储空间,服务于某个应用程序,旨在将频繁读取的数据临时保存在内存中,便于二次快速访问。

无缓存:用户在访问相同数据时,需要发起多次对数据库的直接访问,导致产生大量IO、读写硬盘的操作,效率低下
mybatis_第12张图片
有缓存:首次访问时,查询数据库,将数据存储到缓存中;再次访问时,直接访问缓存,减少IO、硬盘读写次数、提高效率
mybatis_第13张图片

12.1 一级缓存

SqlSession级别的缓存,同一个SqlSession的发起多次同构查询,会将数据保存在一级缓存中。

  • 注意:无需任何配置,默认开启一级缓存。

在sqlsession 中有一个数据结构 是map 结构, 这个区域就是一级缓存区域,一级缓存区域中的 key 是由 sql 语句 方法参数 statement 等 组成的一个唯一值 对应的 value 就是 缓存内容 , 一级缓存 map 的生命周期 和当前 sqlSession 一致

12.2 二级缓存

SqlSessionFactory级别的缓存,同一个SqlSessionFactory构建的SqlSession发起的多次同构查询,会将数据保存在二级缓存中。

  • 注意:在sqlSession.commit()或者sqlSession.close()之后生效。

二级缓存指的是 同一个 namespace 下的 mapper 二级缓存的数据结构 也是一个 map 二级缓存 需要 手动开启

12.2.1 开启全局缓存

< settings >是MyBatis中极为重要的调整设置,他们会改变MyBatis的运行行为,其他详细配置可参考官方文档。

<configuration>
	<properties .../>
  	
  	
    <settings>
        <setting name="cacheEnabled" value="true"/> 
    settings>
  
  	<typeAliases>typeAliases>
configuration>
12.2.2 指定Mapper缓存
<mapper namespace="com.glls.mybatis.mapper.BookMapper">
    <cache /> 

      <select id="selectBookById" resultType="com.glls.mybatis.pojo.Book">
        select *  from t_books where id = #{id}
    select>
mapper>
@Test
    public void test(){
        //测试一级缓存
        BookMapper mapper = MyBatisUtils.getMapper(BookMapper.class);
        System.out.println("第一次查询");
        Book book = mapper.selectBookById(29);
        System.out.println("第二次查询");
        Book book1 = mapper.selectBookById(29);

        System.out.println(book1);

        MyBatisUtils.commit();
        System.out.println("第三次查询");
        BookMapper mapper1 = MyBatisUtils.getMapper(BookMapper.class);
        Book book3 = mapper1.selectBookById(29);
    }
12.2.3 缓存清空并重新缓存

增删改操作 会清空二级缓存

 @Test
    public void test2(){
        //测试 二级缓存
        BookMapper mapper = MyBatisUtils.getMapper(BookMapper.class);
        System.out.println("第一次查询,从数据库取数据");
        Book book = mapper.selectBookById(29);
        System.out.println("第二次查询,走一级缓存");
        Book book1 = mapper.selectBookById(29);

        MyBatisUtils.commit();

        System.out.println("第三次查询,走的是二级缓存");
        BookMapper mapper1 = MyBatisUtils.getMapper(BookMapper.class);
        Book book3 = mapper1.selectBookById(29);

        MyBatisUtils.commit();


        BookMapper mapper3 = MyBatisUtils.getMapper(BookMapper.class);

        mapper3.deleteBookById(16);
        MyBatisUtils.commit();

        System.out.println("第四次查询,走的还是二级缓存");
        BookMapper mapper2 = MyBatisUtils.getMapper(BookMapper.class);
        Book book4 = mapper2.selectBookById(29);

    }

十三、Druid连接池


13.1 概念

Druid 是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和 SQL 解析器组成。该项目主要是为了扩展 JDBC 的一些限制,可以让程序员实现一些特殊的需求,比如向密钥服务请求凭证、统计 SQL 信息、SQL 性能收集、SQL 注入检查、SQL 翻译等,程序员可以通过定制来实现自己需要的功能。

13.2 不同连接池对比

测试执行申请归还连接 1,000,000(一百万)次总耗时性能对比。

13.2.1 测试环境
环境 版本
OS OS X 10.8.2
CPU Intel i7 2GHz 4 Core
JVM Java Version 1.7.0_05
13.2.2 基准测试结果对比
JDBC-Conn Pool 1 Thread 2 threads 5 threads 10 threads 20 threads 50 threads
Druid 898 1,191 1,324 1,362 1,325 1,459
tomcat-jdbc 1,269 1,378 2,029 2,103 1,879 2,025
DBCP 2,324 5,055 5,446 5,471 5,524 5,415
BoneCP 3,738 3,150 3,194 5,681 11,018 23,125
jboss-datasource 4,377 2,988 3,680 3,980 32,708 37,742
C3P0 10,841 13,637 10,682 11,055 14,497 20,351
Proxool 16,337 16,187 18,310(Ex) 25,945 33,706(Ex) 39,501 (Ex)
13.2.3 测试结论
  • Druid 是性能最好的数据库连接池,tomcat-jdbc 和 druid 性能接近。
  • Proxool 在激烈并发时会抛异常,不适用。
  • C3P0 和 Proxool 都相当慢,影响 sql 执行效率。
  • BoneCP 性能并不优越,采用 LinkedTransferQueue 并没有能够获得性能提升。
  • 除了 bonecp,其他的在 JDK 7 上跑得比 JDK 6 上快。
  • jboss-datasource 虽然稳定,但性能很糟糕。

13.3 配置pom.xml

引入Druid依赖


<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>druidartifactId>
    <version>1.1.16version>
dependency>

13.4 创建DruidDataSourceFactory

MyDruidDataSourceFactory并继承PooledDataSourceFactory,并替换数据源。

package com.qf.mybatis.part2.utils;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;

public class MyDruidDataSourceFactory extends PooledDataSourceFactory {
    public MyDruidDataSourceFactory() {
        this.dataSource = new DruidDataSource();//替换数据源
    }
}

13.5 修改mybatis-config.xml

mybatis-config.xml中连接池相关配置。


<dataSource type="com.qf.mybatis.part2.utils.DruidDataSourceFactory">
    <property name="driverClass" value="${driver}"/>
    <property name="jdbcUrl" value="${url}"/>
    <property name="username" value="${username}"/>
    <property name="password" value="${password}"/> 
  
dataSource>

注意:< property name=“属性名” />属性名必须与com.alibaba.druid.pool.DruidAbstractDataSource中一致。

十四、PageHelper


14.1 概念

PageHelper是适用于MyBatis框架的一个分页插件,使用方式极为便捷,支持任何复杂的单表、多表分页查询操作。

14.2 访问与下载

官方网站:https://pagehelper.github.io/

下载地址:https://github.com/pagehelper/Mybatis-PageHelper

14.3 开发步骤

PageHelper中提供了多个分页操作的静态方法入口。

14.3.1 引入依赖

pom.xml中引入PageHelper依赖。

<dependency>
		<groupId>com.github.pagehelpergroupId>
		<artifactId>pagehelperartifactId>
		<version>5.1.10version>
dependency>
14.3.2 配置MyBatis-config.xml

在MyBatis-config.xml中添加< plugins >。

<configuration>
  	<typeAliases>typeAliases>
  
    <plugins>
        
        <plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
    plugins>
  
  	<environments>...environments>
configuration>
14.3.3 PageHelper应用方式

使用PageHelper提供的静态方法设置分页查询条件。

@Test
public void testPagehelper(){
		UserMapper userMapper = MyBatisUtils.getMapper(UserMapper.class);
		PageHelper.startPage(1,2);//使用PageHelper设置分页条件
		List<User> users = userMapper.selectAllUsers();
		for(User user : users){
				System.out.println(user);
		}
}

14.4 PageInfo对象

PageInfo对象中包含了分页操作中的所有相关数据。

PageInfo结构图
mybatis_第14张图片
14.4.1 PageInfo应用方式

使用PageInfo保存分页查询结果。

 @Test
    public void test(){

        BookMapper mapper = MyBatisUtils.getMapper(BookMapper.class);

        //在执行 查询语句之前
        //传入  页码  和  每页记录数
        PageHelper.startPage(2,3);
        //查询方法 要放在  PageHelper.startPage(2,2); 后面
        List<Book> books = mapper.selectBookByCondition(null);

        //把查询结果封装在 pageInfo 对象中
        PageInfo<Book> bookPageInfo = new PageInfo<>(books);
        //books.forEach(System.out::println);
       System.out.println(bookPageInfo);


    }
14.4.2 注意事项
  • 只有在PageHelper.startPage()方法之后的第一个查询会有执行分页。
  • 分页插件不支持带有“for update”的查询语句。
  • 分页插件不支持“嵌套查询”,由于嵌套结果方式会导致结果集被折叠,所以无法保证分页结果数量正确。。
14.4.3 分页练习

使用Servlet+JSP+MyBatis+分页插件,完成分页查询功能。

十五、补充【记住】


以下内容并非必备知识,了解即可。

15.1 MyBatis注解操作

通过在接口中直接添加MyBatis注解,完成CRUD。

  • 注意:接口注解定义完毕后,需将接口全限定名注册到mybatis-config.xml的< mappers >中。
  • 经验:注解模式属于硬编码到.java文件中,失去了使用配置文件外部修改的优势,可结合需求选用。
<mappers>
		
    
      
        <package name="com.glls.mybatis.mapper"/>
mappers>
15.1.1 查询
public interface UserMapper {
    @Select("SELECT * FROM t_users WHERE id = #{id}")
    public User selectUserById(Integer id);

    @Select("SELECT * FROM t_users WHERE id = #{id} AND password = #{pwd}")
    public User selectUserByIdAndPwd_annotation(@Param("id") Integer id, @Param("pwd") String password);
}
15.1.2 删除
@Delete(value = "DELETE FROM t_users WHERE id = #{id}")
public int deleteUser(Integer id);
15.1.3 修改
@Update("UPDATE t_users SET name = #{name} , password = #{password} , salary = #{salary} , birthday = #{birthday} WHERE id = #{id}")
public int updateUser(User user);
15.1.4 插入
@Insert("INSERT INTO t_users VALUES(#{id},#{name},#{password},#{salary},#{birthday},null)")
public int insertUser(User user);

@Options(useGeneratedKeys = true , keyProperty = "id") // 自增key,回显主键为id
@Insert("INSERT INTO t_users VALUES(#{id},#{name},#{password},#{salary},#{birthday},null)")
public int insertUserGeneratedKeys(User user);

15.2 $符号的应用场景

${attribute} 属于字符串拼接SQL,而非预编译占位符,会有注入攻击问题,不建议在常规SQL中使用,常用于可解决动态生降序问题。

15.2.1 $符号参数绑定
public List<User> selectAllUsers1(User user); // ${name} ${id} 可获取user中的属性值
public List<User> selectAllUsers2(@Param("rule") String rule); //必须使用@Param否则会作为属性解析
<select id="selectAllUsers1" resultType="user">
	SELECT * FROM t_users 
    WHERE name = '${name}' or id = ${id} 
select>
<select id="selectAllUsers2" resultType="user">
	SELECT * FROM t_users 
  	ORDER BY id ${rule} 
select>
User user = new User(....);
List<User> ulist1 = userDAO.selectAllUsers1(user); //调用时传入user对象

List<User> ulist2 = userMapper.selectAllUsers2("desc"); //调用时传入asc | desc
15.2.2 $符号注入攻击
<select id="selectUsersByKeyword" resultType="user">
	SELECT * FROM t_user
  	WHERE name = '${name}' 
select>
注入攻击,拼接的内容,改变了原sql语义,被攻击!
注入

15.3 MyBatis处理关联关系-嵌套查询【了解】

思路:查询部门信息时,及联查询所属的员工信息。

  • DepartmentDao接口中定义selectDepartmentById,并实现Mapper。
  • EmployeeDao接口中定义selectEmployeesByDeptId,并实现Mapper,
  • 当selectDepartmentById被执行时,通过< collection >调用selectEmployeesByDeptId方法,并传入条件参数。
15.3.1 主表查询

定义selectEmployeesByDeptId,并书写Mapper,实现根据部门ID查询员工信息

public interface EmployeeDao {
    /**
     * 根据部门编号查询员工信息
     * @param id 部门编号
     * @return 该部门中的所有员工
     */
   public List<Employee> selectEmployeeByDeptId(Integer id);
}
<mapper namespace="com.qf.mybatis.part2.one2many.EmployeeDao">
    
     <select id="selectEmployeeByDeptId" resultType="com.glls.mybatis.pojo.Employee">
            select * from t_employees where dept_id = #{id}
    select>
mapper>
15.3.2 及联调用
定义selectDepartmentById,并书写Mapper,实现根据部门ID查询部门信息,并及联查询该部门员工信息
public interface DepartmentMapper {

    /**
     * 根据id查询部门信息  同时  把部门的员工也查出来
     * @param id
     * @return
     */
    public Department findDepartmentById(Integer id);
}

<mapper namespace="com.glls.mybatis.mapper.DepartmentMapper">
    <resultMap id="departmentResultMap" type="department">
        <id property="id" column="id">id>
        <result property="name" column="name">result>
        <result property="location" column="location">result>

        
        <collection property="emps" ofType="employee" column="id" select="com.glls.mybatis.mapper.EmployeeMapper.selectEmployeeByDeptId">collection>
    resultMap>


    <select id="findDepartmentById" resultMap="departmentResultMap">
        SELECT id , name , location
        FROM t_departments
        WHERE id = #{id}
    select>
mapper>
15.3.3 延迟加载
mybatis-config.xml中开启延迟加载
<settings>
		<setting name="lazyLoadingEnabled" value="true"/> 
settings>
  • 注意:开启延迟加载后,如果不使用及联数据,则不会触发及联查询操作,有利于加快查询速度、节省内存资源。

十六. 逆向工程

比较实用

使用mybatis逆向工程生成代码的方式有多种 ,但是生成的代码都差不多,所以这里咱们介绍一种,生成代码的细节 咱不用管,主要掌握生成的代码如何使用

这里咱们使用mybatis的插件 生成的代码

mybatis_第15张图片 mybatis_第16张图片

生成代码如下

mybatis_第17张图片

ByDeptId(Integer id);
}


```xml

    
     

15.3.2 及联调用
定义selectDepartmentById,并书写Mapper,实现根据部门ID查询部门信息,并及联查询该部门员工信息
public interface DepartmentMapper {

    /**
     * 根据id查询部门信息  同时  把部门的员工也查出来
     * @param id
     * @return
     */
    public Department findDepartmentById(Integer id);
}

<mapper namespace="com.glls.mybatis.mapper.DepartmentMapper">
    <resultMap id="departmentResultMap" type="department">
        <id property="id" column="id">id>
        <result property="name" column="name">result>
        <result property="location" column="location">result>

        
        <collection property="emps" ofType="employee" column="id" select="com.glls.mybatis.mapper.EmployeeMapper.selectEmployeeByDeptId">collection>
    resultMap>


    <select id="findDepartmentById" resultMap="departmentResultMap">
        SELECT id , name , location
        FROM t_departments
        WHERE id = #{id}
    select>
mapper>
15.3.3 延迟加载
mybatis-config.xml中开启延迟加载
<settings>
		<setting name="lazyLoadingEnabled" value="true"/> 
settings>
  • 注意:开启延迟加载后,如果不使用及联数据,则不会触发及联查询操作,有利于加快查询速度、节省内存资源。

十六. 逆向工程

比较实用

使用mybatis逆向工程生成代码的方式有多种 ,但是生成的代码都差不多,所以这里咱们介绍一种,生成代码的细节 咱不用管,主要掌握生成的代码如何使用

这里咱们使用mybatis的插件 生成的代码

mybatis_第18张图片 mybatis_第19张图片

生成代码如下

mybatis_第20张图片

mapper 接口中生成了 常用的 方法, xml 映射文件中 生成了对应的 statement

你可能感兴趣的:(Java第三阶段,mybatis,java,maven)