Java教程

Mybatis学习笔记

本文主要是介绍Mybatis学习笔记,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

MyBatis学习笔记

知识准备:

  • JDBC
  • Mysql
  • Maven
  • Junit

1、简介

1.1、什么是 MyBatis?

  • MyBatis 是一款优秀的持久层框架

  • 它支持自定义 SQL、存储过程以及高级映射。

  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

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

  • 原本是apache的一个开源项目iBatis,2010年改名为MyBatis

  • 2013年11月迁移到Github

如何活得Mybatis?

  • maven仓库
  • GitHub

1.2、持久化

数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程

  • 内存:断电即失

  • 数据库(jdbc),io持久化

  • 生活:冷藏,罐头

为什么需要持久化?

  • 一些对象 不能让他丢掉

  • 内存贵

1.3、持久层

Dao层、Service层、Controller层……

  • 完成持久化工作的代码块
  • 层的界限十分明显

1.4、为什么需要MyBatis?

  • 方便

  • 传统的JDBC代码太复杂,框架帮忙简化、自动化

  • 帮助程序员将数据存入到数据库中

    很多优点……

2、第一个MyBatis程序

思路:搭建环境—>导入MyBatis—>编写代码—>测试

2.1、搭建环境

-- 创建数据库并使用
create database mybatis;
use mybatis;

-- 创建表格
create table if not exists user(
id int(16) not null primary key,
name varchar(32) default null,
pwd varchar(64)
)engine=innodb default charset=utf8;

-- 插入数据
insert into user (id, name, pwd) values 
(1, "Tom", "123123"),
(2, "Bob", "123456"),
(3, "Rum", "666666");

新建项目

1、新建一个普通的maven项目

2、导入maven依赖

    <dependencies>
        <!--        mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.24</version>
        </dependency>

        <!--        mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>

        <!--        junit-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.8.0-M1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!--在build中配置resuorces,来防止我们的资源导出失败-->
    <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>false</filtering>
            </resource>
        </resources>
    </build>

2.2、创建一个模块

  • 编写mybatis的核心配置文件

    <?xml version="1.0" encoding="GBK" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
    <!--    <mappers>-->
    <!--        <mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
    <!--    </mappers>-->
        <mappers>
    <!--        每一个Mapper.xml都需要在MyBatis核心配置文件中注册-->
            <mapper resource="com/lxyker/dao/UserMapper.xml"/>
        </mappers>
    </configuration>
    
  • 编写mybatis工具类

    package com.lxyker.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.IOException;
    import java.io.InputStream;
    
    //sqlSessionFactory --> sqlSession
    public class MyBatisUtils {
        private static SqlSessionFactory sqlSessionFactory;
        static {
            try {
                // 使用MyBatis第一步
                // 从官网拿过来的固定句式,目的是为了获取sqlSessionFactory对象
                String resource = "Mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了
         * SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
         */
    
        public static SqlSession getSqlSession() {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            return sqlSession;
        }
    }
    

2.3、编写代码

  • 实体类

    package com.lxyker.pojo;
    
    public class User {
        private int id;
        private String name;
        private String pwd;
    
        public User() {
        }
    
        public User(int id, String name, String pwd) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    }
    
  • Dao接口

    public interface UserDao {
        List<User> getUserList();
    }
    
  • 接口实现类(由原来的 UserDaoImpl.java 换成了 Mapper 配置文件)

    <?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 = 绑定一个对应的 Dao/Mapper 接口-->
    <mapper namespace="com.lxyker.dao.UserDao">
        <!--    select标签中写查询语句-->
        <!--    resultType是返回值类型-->
        <select id="getUserList" resultType="com.lxyker.pojo.User">
            select * from mybatis.user;
        </select>
    </mapper>
    

2.4、测试

注意点:

MapperRegistry 核心配置文件中注册 mappers

    <mappers>
<!--        每一个Mapper.xml都需要在MyBatis核心配置文件中注册-->
        <mapper resource="com/lxyker/dao/UserMapper.xml"/>
    </mappers>
  • junit测试
package com.lxyker.dao;

import com.lxyker.pojo.User;
import com.lxyker.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;

import java.util.List;

class UserDaoTest {
    @Test
    public void test() {
//        获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

//        方式一:getMapper
//        UserDao mapper = sqlSession.getMapper(UserDao.class);
//        List<User> userList = mapper.getUserList();

//        方式二(不推荐):
        List<User> userList = sqlSession.selectList("com.lxyker.dao.UserDao.getUserList");

        for (User user : userList) {
            System.out.println(user);
        }

//        关闭 SqlSession
        sqlSession.close();
    }
}

3、CRUD

3.1、namespace

namespace中的包名 要和 Dao/Mapper 接口的包名一致

3.2 操作步骤

选择 查询语句

  • id:对应的是namespace中的方法名
  • resultType:sql语句执行的返回值
  • parameterType:参数类型

⒈编写接口

public interface UserMapper {
    List<User> getUserList();

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

    //    插入用户
    int addUser(User user);

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

    //    删除用户
    int delUser(int id);
}

⒉编写对应的mapper中的sql语句

<mapper namespace="com.lxyker.dao.UserMapper">
    <!--    select标签中写查询语句-->
    <!--    resultType返回值类型-->
    <select id="getUserList" resultType="com.lxyker.pojo.User">
        select *
        from mybatis.user;
    </select>

    <select id="getUserById" parameterType="int" resultType="com.lxyker.pojo.User">
        select *
        from mybatis.user
        where id = #{id};
    </select>

    <!--对象中的属性可以直接取出来-->
    <insert id="addUser" parameterType="com.lxyker.pojo.User">
        insert into mybatis.user (id, name, pwd)
        values (#{id}, #{name}, #{pwd});
    </insert>

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

    <!--    删除用户-->
    <delete id="delUser" parameterType="Integer">
        delete
        from mybatis.user
        where id =
              #{id};
    </delete>
</mapper>

⒊测试

	@Test
    public void test2() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserById(1);
        System.out.println(user);

        sqlSession.close();
    }

    @Test
    public void test3() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.addUser(new User(4, "Marry", "000000"));
//        增删改 需要提交事务
        sqlSession.commit();

        sqlSession.close();
    }

    @Test
    public void testUpdate() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updateUser(new User(4, "Mogala", "000111"));

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

    @Test
    public void testDel() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.delUser(4);
        sqlSession.commit();
        sqlSession.close();
    }

3.3、万能map

假设实体类或数据库表中的字段/参数过多,此时应该考虑使用map

UserMapper 接口:

int updateUser2(Map<String, Object> map);

UserMapper.xml:

<update id="updateUser2" parameterType="map">
    update mybatis.user set id = #{uid} where name = #{uname};
</update>

测试类:

@Test
public void testUpdateMap(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    HashMap<String, Object> map = new HashMap<>();
    map.put("uid", 4);
    map.put("uname", "Marry");
    mapper.updateUser2(map);
    sqlSession.commit();
    sqlSession.close();
}

4、配置解析

4.1、核心配置文件

  • mybatis-config.xml

  • MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

    configuration(配置)
    	properties(属性)
    	settings(设置)
    	typeAliases(类型别名)
    	typeHandlers(类型处理器)
    	objectFactory(对象工厂)
    	plugins(插件)
    	environments(环境配置)
    		environment(环境变量)
    			transactionManager(事务管理器)
    			dataSource(数据源)
    	databaseIdProvider(数据库厂商标识)
    	mappers(映射器)
    

4.2、环境配置(environments)

MyBatis 可以配置成适应多种环境

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境

MyBatis 默认的事务管理器就是 JDBC,连接池:POOLED

4.3、属性(properties)

我们可以通过 properties 属性来实现引用配置文件

这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。

编写配置文件 db.properties

driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username = root
password = 123456

在核心配置文件 mybatis-config.xml 中引入

<!--    引入外部配置文件。顺序要在前面-->
<properties resource="db.properties"/>

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

4.4、类型别名(typeAliases)

  • 类型别名是为 Java 类型设置的一个短的名字
  • 存在的意义仅在于用来减少完全限定名的冗余
    <typeAliases>
        <typeAlias type="com.lxyker.pojo.User" alias="User"/>
    </typeAliases>

也可以指定一个包名,MyBatis会在包名下面搜索需要的 Java Bean,比如:

扫描实体类的包,它的默认别名就是这个类的 首字母小写的类名

    <typeAliases>
<!--        <typeAlias type="com.lxyker.pojo.User" alias="User"/>-->
        <package name="com.lxyker.pojo"/>
    </typeAliases>

在实体类比较少的时候,使用第一种方式

如果实体类较多,建议使用第二种方式

第二种方式,在类上加注解,可以自定义别名:

@Alias("myUser")
public class User {
	……

4.5、设置

设置名描述有效值默认值
cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true | falsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | falsefalse
logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置

4.6、映射器(mappers)

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

4.7、生命周期和作用域

生命周期 和 作用域,是至关重要的,因为错误的使用会导致非常严重的并发问题

SqlSessionFactoryBuilder

  • 一旦创建了 sqlSessionFactory,就不再需要它了
  • 局部变量

SqlSessionFactory

  • 可以当作 数据库连接池
  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
  • 因此 SqlSessionFactory 的最佳作用域是应用作用域
  • 最简单的就是使用单例模式或者静态单例模式

SqlSession

  • 连接到连接池的一个请求
  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳作用域是请求或方法作用域
  • 用完之后需要赶紧关闭,否则资源被占用

在这里插入图片描述

这里面的每一个Mapper,就代表一个具体的业务!

5、解决属性名和字段名不一致的问题

数据库中的字段

idnamepwd

新建一个项目,测试实体类字段不一致的情况

public class User {
    private int id;
    private String name;
    private String password;
…………

可以看到,数据库中的字段pwd,在User类中却是password,此时在测试类中打印查询到的数据:

User{id=1, name='Tom', password='null'}

解决方法:

  • 起别名

    <select id="getUserById" parameterType="int" resultType="User">
        select id, name, pwd as password
        from mybatis.user
        where id = #{id};
    </select>
    

5.1、resultMap

结果集映射

<!--column 数据库中的字段,property 实体类中的属性-->
<resultMap id="myUserMap" type="User">
    <result column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="pwd" property="password"/>
</resultMap>
<select id="getUserById" parameterType="int" resultMap="myUserMap">
    select *
    from mybatis.user
    where id = #{id};
</select>
  • resultMap元素是 MyBatis 中最重要最强大的元素
  • resultMap 的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的只需要描述它们的关系就行了。

6、日志

6.1、日志工厂

如果一个数据库操作出现了异常,我们需要排错,此时需要日志。

在 MyBatis 中具体使用哪个日志实现,在设置中设定。

STDOUT_LOGGING 标准日志输出

LOG4J

在核心配置文件 mybatis-config.xml 中,做如下配置:

    <settings>
        <!--        标准的日志工厂:-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

此时运行测试,可以看到控制台输出部分:

Opening JDBC Connection
Created connection 1174586025.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4602c2a9]
==>  Preparing: select * from mybatis.user where id = ?;
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, Tom, 123123
<==      Total: 1
User{id=1, name='Tom', password='123123'}
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4602c2a9]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4602c2a9]
Returned connection 1174586025 to pool.

Process finished with exit code 0

6.2、LOG4J

什么是 LOG4J ?

  • Log4j是Apache的一个开源项目
  • 通过使用Log4j,可以控制日志信息输送的目的地(控制台、文件、GUI 组件 等)
  • 可以控制每一条日志的输出格式
  • 控制输出的日志级别
  • 可以通过 配置文件 的方式灵活配置

1、先导入 log4j 的包

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

2、新建 log4j.properties 文件:

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=【%c】-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/lxyker.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=【%p】【%d{yy-MM-dd}】【%c】%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

3、配置 log4j 为日志的实现

    <settings>
        <!--        标准的日志工厂:-->
<!--        <setting name="logImpl" value="STDOUT_LOGGING"/>-->
        
        <setting name="logImpl" value="LOG4J"/>
    </settings>

4、运行测试类

6.3、LOG4J 的简单使用

1、在要使用 LOG4J 的类中,导入包

2、获取日志对象,方法参数为 当前类的class

static Logger logger = Logger.getLogger(UserMapperTest.class);

7、分页

分页的目的?

  • 可以减少一次请求 数据的处理量

MySQl中使用的 limit

select * from user limit startIndex, pageSize;
select * from user limit 3;		-- 相当于 limit 0, 3;

7.1、使用 MyBatis 实现分页。核心 SQL

1、接口

    //    分页
    List<User> getUserByLimit(Map<String, Integer> map);

2、Mapper.xml

    <!--    分页-->
    <select id="getUserByLimit" parameterType="map" resultType="user" resultMap="myUserMap">
        select *
        from mybatis.user
        limit #{startIndex}, #{pageSize};
    </select>

3、测试

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

        HashMap<String, Integer> map = new HashMap<>();
        map.put("startIndex", 0);
        map.put("pageSize", 1);
        List<User> userList = mapper.getUserByLimit(map);

        for (User user : userList) {
            System.out.println(user);
        }

        sqlSession.close();
    }

8、使用注解开发

8.1、面向接口编程

8.2、注解开发

1、在接口上添加注解

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

2、需要在核心配置文件中绑定接口

<!--    绑定接口-->
<mappers>
    <mapper class="com.lxyker.dao.UserMapper"/>
</mappers>

3、测试

本质:反射机制

底层:动态代理

8.3、CRUD

我们可以在工具类创建的时候实现自动提交事务

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

接口中写方法,添加注解

测试类测试

关于@Param()注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不需要加
  • 在SQL中引用的就是我们这里的 @Param(“uid”) 中设置的属性名

8.4、MyBatis 执行流程

9、Lombok

插件使用步骤:

在项目中导入Lombok的jar包(maven)

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
    <scope>provided</scope>
</dependency>

在实体类上加注解即可:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String name;
    private String password;
}

10、多对一的处理

在这里插入图片描述

  • 对于学生而言,多个学生 关联 一个老师 多对一
  • 对于老师而言,一个老师 集合 多个学生 一对多

案例:

  • 创建表格
create table teacher(
	id int(10) not null,
	name varchar(30) default null,
	primary key (id)
)engine=innodb default charset=utf8;

insert into teacher (id, name) values (1, "刘老师");

create table student(
	id int(10) not null,
	name varchar(30) default null,
	tid int(10) default null,
	primary key (id),
	key fktid (tid),
	constraint fktid foreign key (tid) references teacher(id)
)engine=innodb default charset=utf8;

insert into student(id, name, tid) values(1, "小明", 1);
insert into student(id, name, tid) values(2, "小花", 1);
insert into student(id, name, tid) values(3, "小红", 1);
insert into student(id, name, tid) values(4, "小龙", 1);
insert into student(id, name, tid) values(5, "小刚", 1);

测试环境搭建:

  • 导入Lombok

  • 新建实体类 Teacher 和 Student

    package com.lxyker.pojo;
    
    import lombok.Data;
    
    @Data
    public class Teacher {
        private int id;
        private String name;
    }
    --------------------------------------------------------------
    package com.lxyker.pojo;
    
    import lombok.Data;
    
    @Data
    public class Student {
        private int id;
        private String name;
    
    //    学生需要关联一个老师
    //    private int tid;
        private Teacher teacher;
    }
    
  • 建立 Mapper 接口

    public interface TeacherMapper {
        @Select("select * from teacher where id = #{id}")
        Teacher getTeacherById(@Param("id") int id);
    }
    
  • 建立 Mapper.xml 文件

    <?xml version="1.0" encoding="UTF8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.lxyker.dao.TeacherMapper">
    </mapper>
    
  • 在核心配置文件中绑定注册我们的 Mapper 接口或文件

        <mappers>
            <mapper class="com.lxyker.dao.TeacherMapper"/>
            <mapper class="com.lxyker.dao.StudentMapper"/>
        </mappers>
    
  • 测试查询是否成功

    public class TeacherMapperTest {
        @Test
        public void myTest1() {
            SqlSession sqlSession = MyBatisUtils.getSqlSession();
            TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
            Teacher teacherById = mapper.getTeacherById(1);
            System.out.println(teacherById);
            sqlSession.close();
        }
    }
    

查询所有的学生信息,以及对应的老师的信息

  • 按照查询嵌套处理:
<mapper namespace="com.lxyker.dao.StudentMapper">

    <!--    思路:
            1、查询所有的学生信息
            2、根据查询到的学生tid,寻找对应的老师
    -->
    <select id="getStus" resultMap="StuTea">
        select * from student;
    </select>

    <resultMap id="StuTea" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--    <result property="" column="id"/>   复杂的属性需要单独处理:  对象:associate   集合:collection  -->
        <association property="teacher" column="tid" javaType="Teacher" select="getTea"/>
    </resultMap>

    <select id="getTea" resultType="Teacher">
        select * from teacher where id = #{id};
    </select>
</mapper>
  • 按照结果嵌套处理
<select id="getStus2" resultMap="StuTea2">
    select s.id sid, s.name sname, t.name tname
    from student s,
         teacher t
    where s.tid = t.id;
</select>
<resultMap id="StuTea2" type="Student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>

11、一对多的处理

实体类:

@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}
--------------------------------------------------------
@Data
public class Teacher {
    private int id;
    private String name;

    //    一个老师集合多个学生
    private List<Student> students;
}

Mapper.xml:

<mapper namespace="com.lxyker.dao.TeacherMapper">
    <select id="getTeacher" resultMap="TeaStu">
        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 = #{tid};
    </select>

    <resultMap id="TeaStu" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
<!--        复杂的属性,我们需要单独处理      对象 用 association    集合 用 collection-->
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>
</mapper>

12、动态SQL

动态SQL就是指根据不同的条件生成不同的SQL语句

搭建环境

create table blog
(
    id          int(16)  not null comment '博客id',
    title       varchar(128) not null comment '博客标题',
    author      varchar(32)  not null comment '博客作者',
    create_time datetime     not null comment '创建时间',
    views       int(32)      not null comment '浏览量'
) engine = innodb
  default charset = utf8;

创建基础工程

导入jar包

编写配置文件

编写实体类

@Data
public class Blog {
    private int id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}

编写实体类对应的 Mapper 接口和 Mapper.xml 文件

if

    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from blog where 1=1
        <if test="title != null">
            and title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </select>

根据传入的参数不同而查询到不同的结果

    @Test
    public void test2() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        HashMap<Object, Object> map = new HashMap<>();
//        map.put("title", "简单Java");
        map.put("author", "张三");
        List<Blog> blogs = mapper.queryBlogIF(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }

        sqlSession.close();
    }

choose (when, otherwise)

<select id="queryBlogChoose" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <choose>
            <when test="title != null">
                title = #{title}
            </when>
            <when test="author != null">
                and author = #{author}
            </when>
            <otherwise>
                and views = #{views}
            </otherwise>
        </choose>
    </where>
</select>

trim (where, set)

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

<where>标签能够帮助SQL中多余的 and or 语句

<set>标签去掉SQL中多余的逗号,

SQL片段

有时我们需要将一些功能的公共部分抽取出来,以供复用。

  • 使用<sql>标签抽取公共的部分
  • 在需要使用的地方<include>标签
<sql id="if-tit-aut">
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>

<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from blog where 1=1
    <include refid="if-tit-aut"/>
</select>

Foreach

select * from user where 1=1 and (id=1 or id=2 or id=3);

13、缓存

查询 需要连接数据库,耗资源

当一次查询的结果,让它暂存到一个直接可取的地方,再次查询时即可不用连接数据库,提高利用率

title = #{title} and author = #{author} and views = #{views} ```

trim (where, set)

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

<where>标签能够帮助SQL中多余的 and or 语句

<set>标签去掉SQL中多余的逗号,

SQL片段

有时我们需要将一些功能的公共部分抽取出来,以供复用。

  • 使用<sql>标签抽取公共的部分
  • 在需要使用的地方<include>标签
<sql id="if-tit-aut">
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>

<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from blog where 1=1
    <include refid="if-tit-aut"/>
</select>

Foreach

select * from user where 1=1 and (id=1 or id=2 or id=3);

13、缓存

查询 需要连接数据库,耗资源

当一次查询的结果,让它暂存到一个直接可取的地方,再次查询时即可不用连接数据库,提高利用率

一级缓存默认开启,只在一次 sqlSession 中有效

这篇关于Mybatis学习笔记的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!