栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

一文学会MyBatis,MyBatis最简单的入门教程(万字好文)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一文学会MyBatis,MyBatis最简单的入门教程(万字好文)

文章目录
  • 1 MyBatis框架的概述
    • 1.1 三层架构
    • 1.2 三层架构请求的处理流程
    • 1.3 为什么要使用三层
    • 1.4 三层架构模式和框架
    • 1.5 框架
    • 1.6 框架解决的问题
    • 1.7 jdbc访问数据库的优缺点
    • 1.8 MyBatis框架
  • 2 MyBatis框架快速入门
    • 2.1 使用MyBatis准备
    • 2.2 搭建MyBatis项目八步
      • 2.2.1 创建mysql数据库和表
      • 2.2.2 在idea中创建一个空项目
      • 2.2.3 修改pom.xml文件
      • 2.2.4 创建一个实体类Student
      • 2.2.5 创建Dao接口,定义操作数据库的方法
      • 2.2.6 创建xml文件(mapper文件),写sql语句
      • 2.2.7 创建mybatis的主配置文件(xml文件):只有一个,放在resources目录下
      • 2.2.8 创建测试的内容
    • 2.3 MyBatis使用占位符
    • 2.4 MyBatis使用日志
      • 2.4.1 日志的介绍
      • 2.4.2 添加学生数据
      • 2.4.3 使用占位符
    • 2.5 MyBatis的一些重要对象
      • 2.51.Resources
      • 2.5.2 SqlSessionFactoryBuilder
      • 2.5.3 SqlSessionFactory
      • 2.5.4 SqlSession对象
    • 2.6 mapper和主配置文件创建模板
  • 3 MyBatis框架之dao代理
    • 3.1 传统dao方法
      • 3.1.1 创建工具类
      • 3.1.2 查询多条数据
      • 3.1.3 使用传统的dao执行sql
    • 3.2 MyBatis使用动态代理
      • 3.2.1 引出代理技术
      • 3.2.2 代理的实现方式
      • 3.2.3 实例
    • 3.3 MyBatis参数详解
      • 3.3.1 parameterType
      • 3.3.2 dao接口方法参数一个简单类型的参数
      • 3.3.3 dao接口方法中有多个简单类型的参数
      • 3.3.4 dao接口方法使用一个对象作为参数
      • 3.3.5 dao接口中多个简单类型的参数,使用位置
      • 3.3.6 dao接口参数是一个Map
    • 3.4 MyBatis占位符的讲解
      • 3.4.1 占位符#{}
      • 3.4.2 占位符${}
      • 3.4.3 #{}和${}组合使用
    • 3.5 resultType
      • 3.5.1 java类型的全限定名称
      • 3.5.2 自定义别名
        • 3.5.2.1 typeAlias自定义别名
        • 3.5.2.2 package自定义别名
      • 3.5.3 resultType表示简单类型
      • 3.5.4 resultType
    • 3.6 resultMap
    • 3.7 列名和Java对象属性名称不一致解决方式
      • 3.7.1 使用resultMap:自定义列名和属性名称对应关系
      • 3.7.2 使用resultType
    • 3.8 MyBatis实现模糊查询
      • 3.8.1 第一种方式
      • 3.8.2 第二种方式
  • 4 MyBatis框架动态SQL
    • 4.1 动态SQL之if
    • 4.2 动态SQL之where
    • 4.3 动态SQL之foreach
      • 4.3.1 foreach简单类型的List
      • 4.3.2 foreach对象类型的List
    • 4.4 sql标签
  • 5 主配置文件
    • 5.1 settings部分
    • 5.2 typeAliases别名
    • 5.3 配置环境
    • 5.4 使用数据库属性配置文件
    • 5.5 mapper文件的两种指定方式
  • 6 PageHelper

1 MyBatis框架的概述 1.1 三层架构

mvc:web开发中,使用mvc架构模式。m:数据 v:视图 c:控制器

  • c:控制器:接收请求,调用service对象,显示请求的处理结果。当前使用servlet作为控制器
  • v:视图:显示请求的结果的结果,把m中数据显示出来。当前使用jsp,html,css,js等
  • m:数据:来自数据库mysql,来自文件,来自网络

mvc作用:

  • 实现解耦
  • 让mvc各司其职
  • 使得系统扩展更好

三层架构:

1.界面层(视图层):接收用户的请求,调用service,显示请求的处理结果。包含了jsp,html,servlet等对象。对应的包controller

2.业务逻辑层:处理业务逻辑,使用算法处理数据的。把数据返回给界面层。对应的是service包,和保重的很多XXXService类。例如:StudentService,OrderSerVice,ShopService

3.持久层(数据访问层):访问数据库,或者是读取文件,访问网络,获取数据。对应的包是dao。dao包中有很多的StudentDao,OrderDao,ShopDao等等

1.2 三层架构请求的处理流程

用户发起请求→界面层→业务逻辑层→持久层→数据库(mysql)

原理图如下:

1.3 为什么要使用三层

1.结构清晰、耦合度低。各层分工明确

2.可维护性高,可扩展性高

3.有利于保准化

4.开发人员可以只关注整个结构中的其中某一层的功能实现

5.有利于各层逻辑的复用

1.4 三层架构模式和框架

每一层对应着一个框架

  • 界面层—SpringMVC框架
  • 业务层—Spring框架
  • 持久层—Mybatis框架

MyBatis框架:

MyBatis是一个优秀的基于java的持久层框架,内部封装了jdbc,开发者只需要关注sql语句本身,而不需要处理加载驱动、创建连接、创建statement、关闭连接

Spring框架:
Spring框架为了解决软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前非常复杂的企业级开发。

SpringMVC框架:

SpringMVC属于SpringframeWork3.0版本假如的一个模块,为Spring框架提供了构建Web应用程序的能力。

1.5 框架

什么是框架?

    框架(framework)是整个或不分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种认为,框架是可被应用开发者定制的应用模板。

    简单的说,框架其实就是半成品软件,就是一组组件,供你使用完成你自己的系统。从另一个角度来说框架时一个舞台,你再舞台上做表演,在框架基础上假如你要完成的功能。

    框架时安全的,可复用的,不断升级的软件。

    框架是对某一个方面是有用的,不是全能的。
1.6 框架解决的问题

1.框架能实现技术的整合

2.提高开发的效率,降低难度

1.7 jdbc访问数据库的优缺点

优点:

1.直观,好理解

缺点:

  • 创建创建很多对象Connection,Statement,ResultSet
  • 注册驱动
  • 执行sql语句
  • 把ResultSet转为Student,List集合
  • 关闭资源
  • sql语句和业务逻辑代码混为一起
1.8 MyBatis框架

什么是MyBatis?

MyBatis是一个持久层框架,原名是ibatis,2013年改名为MyBatis.

MyBatis可以操作数据库,对数据执行增删改查,看做是高级的JDBC,解决JDBC的缺点

MyBatis可以做什么?

1.注册驱动

2.创建jdbc中使用的Connection,Statement,ResultSet

3.执行sql语句,得到ResultSet

4.处理ResultSet,把记录集中的数据转为java对象,同时还能把java对象放入到List集合

5.关闭资源

6.实现sql语句和java代码的解耦合

2 MyBatis框架快速入门 2.1 使用MyBatis准备

学习文档:

mybatis – MyBatis 3 | 入门

我们按照这个学习路线来学习

在学习此教程之前你需要会这些知识:Java基础,JDBC,Maven

2.2 搭建MyBatis项目八步 2.2.1 创建mysql数据库和表

数据库名:ssm;表名:student

插入一条数据:

2.2.2 在idea中创建一个空项目

然后输入项目名

创建完成之后,我们在里面添加Modules

创建一个Maven项目

输入名字:

一直点next直到创建完成项目,创建完成后我们来查看项目的结构

2.2.3 修改pom.xml文件

1)加入依赖:mybatis依赖,MySQL驱动,junit


    junit
    junit
    4.13.2
    test



    org.mybatis
    mybatis
    3.5.7



    mysql
    mysql-connector-java
    8.0.26

2)在加入资源插件


    
        src/main/java
        
            ***.xml
        
        false
    

2.2.4 创建一个实体类Student

首先创建一个实体包,创建一个Student实体类

定义属性,属性名和列名保持一致

package com.lu.entity;
 
public class Student {
    //属性名和列名保持一致
    private Integer id;
    private String name;
    private String email;
    private Integer age;
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getEmail() {
        return email;
    }
 
    public void setEmail(String email) {
        this.email = email;
    }
 
    public Integer getAge() {
        return age;
    }
 
    public void setAge(Integer age) {
        this.age = age;
    }
 
    @Override
    public String toString() {
        return "学生实体信息{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", email='" + email + ''' +
                ", age=" + age +
                '}';
    }
}
2.2.5 创建Dao接口,定义操作数据库的方法

创建dao包

代码如下:

package com.lu.dao;
 
import com.lu.entity.Student;
 
public interface StudentDao {
    
    //查询一个学生
    Student selectStudentById(Integer id);
}
2.2.6 创建xml文件(mapper文件),写sql语句

mybatis框架推荐是把sql语句和java代码分开

mapper文件:定义和dao接口在同一目录,一个表一个mapper文件



 

 
    
    
    select id,name,email,age from student where id = #{studentId}

这样我们就使用了占位符,#{}

占位符表示从Java程序中传入过来的数据

我们修改测试代码

Student student = session.selectOne(sqlId, 1001);

重新执行代码,得到一样的输出

2.4 MyBatis使用日志 2.4.1 日志的介绍

我们打开官方教程,看到可以一下几种日志供我们使用

我们来看这一段话

不少应用服务器(如 Tomcat 和 WebShpere)的类路径中已经包含 Commons Logging。注意,在这种配置环境下,MyBatis 会把 Commons Logging 作为日志工具。这就意味着在诸如 WebSphere 的环境中,由于提供了 Commons Logging 的私有实现,你的 Log4J 配置将被忽略。这个时候你就会感觉很郁闷:看起来 MyBatis 将你的 Log4J 配置忽略掉了(其实是因为在这种配置环境下,MyBatis 使用了 Commons Logging 作为日志实现)。如果你的应用部署在一个类路径已经包含 Commons Logging 的环境中,而你又想使用其它日志实现,你可以通过在 MyBatis 配置文件 mybatis-config.xml 里面添加一项 setting 来选择其它日志实现。

这段话的意思也就是或如果我们使用了类似于Tomcat,WebShpere之类的服务器,那么MyBatis会默认使用这些 服务器自带的Commons Logging作为日志工具。而如果我们还想使用其他日志来进行实现,我们必须在主配置文件中添加一项setting来选择其他日志实现。

格式如下:


  
    ...
    
    ...
  

name代表了我们日志的名称,而value的值是我们选择何种日志实现方式

可选的值有:SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING

我们一般使用的是LOG4J和STDOUT_LOGGING

结合我们昨天学习的东西,我们去mybatis的主配置文件添加以下代码:




    
    
        
    
 
    
        
            
            
            
                
                
                
                
                
                
                
                
            
        
    
 
    
    
        
        
    

我们重新来运行代码,执行查询操作

我们可以看到输出的信息比以前更详细了,但出现了几个新的概念。

什么是自动提交?

当你的sql语句执行完毕后,提交事务。数据库更新操作之间保存到数据

什么是手动提交事务?

在你需要提交事务的位置,执行方法,提交事务或者回滚事务

我们下面通过一个添加学生数据的例子,来更清楚的弄懂自动提交和手动提交事务的区别。

2.4.2 添加学生数据

既然我们要添加学生数据,我们首先需要在StudentDao结构中定义一个方法

代码如下:

package com.lu.dao;
 
import com.lu.entity.Student;
 
public interface StudentDao {
 
    //查询一个学生
    Student selectStudentById(Integer id);
 
    //添加学生
    //返回值int,表示本次操作影响的数据库的行数
    int insertStudent(Student student);
}

然后在StudentDao.xml文件中来写sql语句



 

 
    
    select id, name, email, age from student

然后编写测试代码:

@Test
public void testSelectStudents() {
    //1.获取SqlSession对象
    SqlSession session = MyBatisUtil.getSqlSession();
 
    //2.指定sqlId
    String sqlId = "com.lu.dao.StudentDao" + "." + "selectStudents";
 
    //3.执行方法
    List students = session.selectList(sqlId);
 
    for (Student stu :
            students) {
        System.out.println(stu);
    }
    //4.关闭SqlSession对象
    session.close();
}

执行测试类

成功将所有数据查询出来

3.1.3 使用传统的dao执行sql

为了更加精简测试类的代码量,我们使用传统的dao来执行sql,也就是说实现dao接口的实现类

我们来编写StudentDao接口的实现类StudentDaoImpl.java

package com.lu.dao;
 
import com.lu.entity.Student;
import com.lu.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
 
import java.util.List;
 
public class StudentDaoImpl implements StudentDao {
    @Override
    public Student selectStudentById(Integer id) {
        //1.获取SqlSession对象
        SqlSession session = MyBatisUtil.getSqlSession();
 
        //2.指定sqlId
        String sqlId = "com.lu.dao.StudentDao" + "." + "selectStudentById";
 
        //3.执行方法
        Student student = session.selectOne(sqlId, id);
 
        //4.关闭SqlSession对象
        session.close();
        return student;
    }
 
    @Override
    public List selectStudents() {
        //1.获取SqlSession对象
        SqlSession session = MyBatisUtil.getSqlSession();
 
        //2.指定sqlId
        String sqlId = "com.lu.dao.StudentDao" + "." + "selectStudents";
 
        //3.执行方法
        List students = session.selectList(sqlId);
 
        //4.关闭SqlSession对象
        session.close();
        return students;
    }
}

我们再来新建一个测试类MyTest2

package com.lu;
 
import com.lu.dao.StudentDao;
import com.lu.dao.StudentDaoImpl;
import com.lu.entity.Student;
import org.junit.Test;
 
import java.util.List;
 
public class MyTest2 {
 
    @Test
    public void testSelectOne() {
        //要使用dao的方法
        // 接口类型 变量 = new 接口的实现类();
        StudentDao dao = new StudentDaoImpl();
        Student student = dao.selectStudentById(1001);
        System.out.println("通过dao执行方法得到的对象 = " + student);
    }
 
    @Test
    public void testSelectStudents() {
        StudentDao dao = new StudentDaoImpl();
        List students = dao.selectStudents();
        for (Student stu :
                students) {
            System.out.println(stu);
        }
    }
}

分别执行

这样我们在测试类中的代码又精简了,但是我们发现一个问题,好像这样也没有少写代码,这只不过代码放到dao接口的实现类当中去了,所以我们必须谋求一种更精简的方式。

3.2 MyBatis使用动态代理 3.2.1 引出代理技术

今天我们继续学习前一天的内容,昨天我们使用了传统的dao来执行sql,我们来分析一下,来看下面这两行代码,就是dao接口我们写的实现类里面的两行代码,我们怎么样通过dao调用方法来得到这两行代码的信息呢?

String sqlId = "com.lu.dao.StudentDao.selectStudentById";
Student student = session.selectOne(sqlId, id);

测试方法中:调用dao的方法

Student student = dao.selectStudentById(1001);

我们来分析一下,首先分析后面的dao.selectStudentById()

1.dao:通过反射能够得到全限定类型名称

dao是StudentDao类型的,全限定名称:com.lu.dao.StudentDao,那么通过反射我们就可以得到sqlId前面的内容com.lu.dao.StudentDao"

2.selectStudentById:dao中的方法名称,方法名称就是mapper文件中标签的id

现在我们sqlId后面的内容"selectStudentById"也得到了,两个一拼接就得到了完整的sqlId

也就是说通过dao.selectStudentById()可以得到sqlId的信息

sqlId = "com.lu.dao.StudentDao.selectStudentById"

现在我们已经得到了sqlId的值,那么我们还需要得到第二行代码,也就是如何确定SqlSession调用的那个方法。

**3.确定调用SqlSession的哪个方法 **

1).根据dao接口的返回值,如果返回的是一个对象,例如Student,说明调用SqlSession.selectOne()

2).如果dao接口中的方法返回List,调用SqlSession的selectList();

3).根据mapper文件中的标签,如果标签是,调用SqlSession.insert()方法

现在我们根据Student student = dao.selectStudentById(1001);这一行代码可以得到上面两行代码的信息。同样,mybatis框架,发现使用dao的方法调用能确定执行sql语句的必要信息,那么mybatis就能简化dao对象的实现。

由mybatis框架在程序执行期间,根据你的Dao接口,创建一个内存中的接口的实现类对象

mybatis把这个技术叫做dao技术(动态代理,dao的动态代理)

**dao代理技术:**由mybatis创建StudentDao接口的实现类Proxy(StudentDaoImpl),使用框架创建的StudentDaoImpl代替你手工实现的StudentDaoImpl类的功能,开发人员不再需要写dao接口的实现类。

使用dao的代理要求:

1.mapper文件中的namespace:必须是dao接口的全限定名称

2.mapper文件中标签的id是dao接口中的方法名称(一模一样)

3.2.2 代理的实现方式

要想实现代理,其实很简单,我们来看官网的介绍

使用SqlSession对象的方法 getMapper(dao.class)

例如:现在有StudentDao接口

SqlSession session = MyBatisUtils.getSqlSession();
StudentDao dao = session.getMapper(StudentDao.class);
Student student = dao.selectStudentById(1001);

//上面代码中
StudentDao dao = session.getMapper(StudentDao.class);
//等同于
StudentDao dao = new StudentDaoImpl();

通过这三行代码,我们就可以实现数据库的查询,这样我们的代码又精简了,不用自己再写dao接口的实现类了。

3.2.3 实例

我们再来新建一个Maven项目,实现数据库的添加

项目目录结构为

其他的没有什么不同,但是我们没有dao接口的实现类了

同时MyTest的代码为

@Test
public void testselectStudentById() {
    SqlSession session = MyBatisUtil.getSqlSession();
    StudentDao dao = session.getMapper(StudentDao.class);
    Student student = dao.selectStudentById(1001);
    System.out.println(student);
    session.close();
}

控制台输出:

查询成功!

那么我们生成的dao对象到底是什么,我们来输出一下

可以看到dao对象是一个代理

**到现在我们又进一步精简化了代码,实现了mybatis的代理,dao接口实现类的代码mybatis也帮我们写了,是不是方便了很多,学到这里我们已经将mybatis的大概学会了,接下来我们会讲解mybatis的参数详细理解。 **

3.3 MyBatis参数详解

参数就是通过java程序把数据传入到mapper文件中的sql语句。参数主要是指dao接口方法的形参

3.3.1 parameterType

**parameterType:**表示参数的类型,指定dao方法的形参数据类型。这个形参的数据类型是给mybatis使用。mybatis是给sql语句的参数赋值时使用。

PreparedStatement.setXXX(位置, 值)

要想理解这里必须对JDBC中的PreparedStatement有足够的了解,推荐看我之前写的一篇文章

一文学会JDBC(两万字,适用于新手)_ypxcan的博客-CSDN博客

我们来看mapper文件中select查询语句


    select id, name, email, age from student where id = #{studentId}

我们在测试类中测试一下

发现是可以执行的

但是我们发现一个问题,好像parameterType不写也是可以的,没错,parameterType不是强制的,mybatis通过反射机制是可以得到参数类型的,绝大多数情况下我们不需要写这个参数。

3.3.2 dao接口方法参数一个简单类型的参数

如果dao接口中方法的形参是一个简单类型,那么mapper文件中,获取这个参数值,使用#{任意字符}

简单类型:八种基本类型 + String

我们来讲一个例子,首先在dao接口中定义一个方法

package com.lu.dao;
 
import com.lu.entity.Student;
 
public interface StudentDao {
 
    Student selectStudentByEmail(String email);
}

在mapper文件中来写查询代码



 

    
    
    
    select id, name, email, age from student where name = #{studentName} or age = #{studentAge}

在测试类中测试

@Test
public void testSelectByNameOrAge() {
    SqlSession session = MyBatisUtil.getSqlSession();
    StudentDao dao = session.getMapper(StudentDao.class);
    List students = dao.selectByNameOrAge("张三", 25);
    students.forEach(student -> System.out.println(student));
    session.close();
}

控制台输出:

报错了,mybatis不能识别多个参数,所以这时候我们就需要使用**@Param注解**

该注解的使用位置在dao接口中

List selectByNameOrAge(@Param("myname") String name, @Param("myage") Integer age);

当使用了@Param后,例如@Param(“myname”),在mapper文件中,使用#{命名的参数},

例如#{myname},那么mapper文件中就需要改成


    select id, name, email, age from student where name = #{name} or age = #{age}

这里我们只写了name和age,那么测试类中就可以这么写

@Test
public void testSelectByObject() {
    SqlSession session = MyBatisUtil.getSqlSession();
    StudentDao dao = session.getMapper(StudentDao.class);
 
    Student student = new Student();
    student.setName("张三");
    student.setAge(25);
    List students = dao.selectByObject(student);
    students.forEach(stu -> System.out.println(stu));
 
    session.close();
}

控制台输出:

可以看到可以正常输出

我们必须明白我们的参数不一定使我们定义的Student实体类,也可以是其他类,只要该类的属性有set和get方法即可

3.3.5 dao接口中多个简单类型的参数,使用位置

参数位置:dao接口中方法的形参列表,从左往右,参数位置是0,1,2…

语法格式:#{arg0},#{arg1}

下面来讲一个例子:

我们首先在接口中定义一个方法

List selectByPosition(String name, Integer age);

mapper文件中


    select id, name, email, age from student where name = #{myname} or age = #{myage}

测试类中:

@Test
public void testSelectByMap() {
    SqlSession session = MyBatisUtil.getSqlSession();
    StudentDao dao = session.getMapper(StudentDao.class);
 
    //使用Map传递参数
    Map data = new HashMap<>();
    data.put("myname", "张三");
    data.put("myage", 20);
    List students = dao.selectStudentByMap(data);
    students.forEach(student -> System.out.println(student));
 
    session.close();
}

控制台输出:

在mybatis中,占位符有两个,一个是#,一个是$,这两个有什么区别,我们分别来讲解一下

3.4 MyBatis占位符的讲解 3.4.1 占位符#{}

语法:#{字符}

#占位符告诉mybatis使用实际的参数值代替。并,#{…}代替sql语句的"?"。这样做更安全,更迅速,通常也是首选做法

mapper文件中


	select * from ${tableName} where name = #{myname} order by ${colName} desc

在测试类中

    @Test
    public void testQueryStudentOrderByColName() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        List students = dao.queryStudentOrderByColumn("张三", "id", "student");
        students.forEach(student -> System.out.println(student));

        session.close();
    }

控制台输出:

现在我们已经实现了#{}和${}的组合使用

封装输出结果:MyBatis执行sql语句,得到ResultSet,转为java对象

这里我们两个,分别为resultType和resultMap

3.5 resultType

resultType属性:在执行select时使用,作为标签的属性出现的。

resultType:执行sql得到ResultSet转换的类型,使用类型的完全限定名或别名。注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。

它的值有两种:

  1. java类型的全限定名称
  2. 使用别名
3.5.1 java类型的全限定名称

dao接口中定义方法

Student selectStudentById(Integer id);

mapper文件中


	select id, name, email, age from student where id = #{studentId}

3.测试类中测试

    @Test
    public void testselectStudentById() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        Student student = dao.selectStudentById(1002);
        System.out.println(student);
        session.close();
    }

控制台输出:

使用typeAlias有优点也有缺点

优点:别名可以自定义

缺点:每个类型必须单独定义

3.5.2.2 package自定义别名

主配置文件中:


mapper文件中:


	select count(*) from student

在测试类中测试

    @Test
    public void testCountStudent() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        long nums = dao.countStudent();
        System.out.println("nums = " + nums);

        session.close();
    }

控制台输出:

3.5.4 resultType

dao接口中定义方法:

Map selectMap(Integer id);

mapper文件中写sql语句:


        select id, name, email, age from student where id = #{studentid}
    

这样我们就可以使用resultMap来定义数据库列和属性的关系

我们在测试类中进行测试:

    @Test
    public void testSelectById2() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        CustomObject co = dao.selectById2(1001);
        System.out.println(co);
        session.close();
    }

控制台输出:

这样resultMap就成功解决了列名和属性名不一致的情况。

注意:resultType和resultMap不能同时使用。

3.7 列名和Java对象属性名称不一致解决方式 3.7.1 使用resultMap:自定义列名和属性名称对应关系

这个方法在上面讲解resultMap的时候就讲解了,可以直接看上面

3.7.2 使用resultType

使用列别名,让别名和Java对象属性名称一样

我们在dao接口中定义一个方法:

CustomObject selectById3(Integer id);

我们在mapper文件中写:


我们在测试类中进行测试

    @Test
    public void testSelectById3() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        CustomObject co = dao.selectById2(1003);
        System.out.println(co);
        session.close();
    }

控制台输出:

3.8 MyBatis实现模糊查询

今天我们来学习mybatis实现模糊查询

3.8.1 第一种方式

第一种方式:在java程序中,把like的内容组装好,把这个内容传入到sql语句

我们先在dao接口中定义一个方法

//like的第一种方式
List selectLikeOne(@Param("name") String name);

mapper文件中:


	select * from student where name like "%" #{name} "%"

在测试类中测试:

@Test
public void testLikeTne() {
	SqlSession session = MyBatisUtil.getSqlSession();
	StudentDao dao = session.getMapper(StudentDao.class);

	String name = "张";
	List students = dao.selectLikeTwo(name);
	session.close();

	students.forEach(student -> System.out.println(student));
}

控制台输出:

4 MyBatis框架动态SQL

什么是动态sql:同一个dao的方法,根据不同的条件可以表示不同的sql语句,主要是where部分有变化

通过使用mybatis提供的标签,实现动态sql的能力,主要将if,where,foreach,sql这四个标签

注意:

在使用动态sql的时候,dao方法的形参要使用java对象。

4.1 动态SQL之if

语法:


	sql代码



在mapper文件中

	select * from student where
	
		name = #{name}
	

	
	or age = #{age}
	

在测试类中

@Test
public  void testSelectIf() {
    SqlSession session = MyBatisUtil.getSqlSession();
    StudentDao dao = session.getMapper(StudentDao.class);

    Student student = new Student();
    student.setName("张三");
    student.setAge(22);

    List students = dao.selectIf(student);
    students.forEach(stu -> System.out.println(stu));

    session.close();
}

控制台输出:

查询成功。

现在我们来修改测试类中的代码,不给name赋值,或者赋空值

@Test
public  void testSelectIf() {
    SqlSession session = MyBatisUtil.getSqlSession();
    StudentDao dao = session.getMapper(StudentDao.class);

    Student student = new Student();
    student.setName("张三");
    student.setAge(22);

    List students = dao.selectIf(student);
    students.forEach(stu -> System.out.println(stu));

    session.close();
}

我们重新运行程序

程序运行出错,我们发现,如果给name赋空值的话,那么就不满足第一个条件,但是满足第二个条件,这样就成为了

select * from student where or age = ?

这种sql语法肯定是错误的,那么我们应该如何避免这种错误的?

我们修改mapper文件:


    select * from student where id = -1
    
        name = #{name}
    

    
        or age = #{age}
    

我们在where后面加上一个 id = -1,我们知道肯定是不满足条件的,这样我们如果没有给name赋值,那么我们的sql语法就变成了

select * from student where id = -1 or age > 0

这样就不会出现语法错误了,但是如果我们的name赋值了呢,那岂不是我们的语法不就变成了

select * from student where id = -1 name = "张三" or age > 0

这样我们的语法又错误了

我们再修改mapper文件:


    select * from student where id = -1
    
        or name = #{name}
    

    
        or age = #{age}
    

这样好像就可以了,哪怕我们的name赋值了,sql语法也变成了这样:

select * from student where id = -1 or name = "张三" or age > 0

所以在具体的案例中我们在where后面总是加上一个一直满足(比如where 1 = 1)或者一直不满足(比如1 = -1)这样的语句,具体的情况需要根据我们的需求来添加,而后面的判断条件是加 and 或者是 or都根据实际情况来写。

这里我们再来讲一个细节,如果我们要查询小于某个年龄的人群,我们在mapper文件中:


    select * from student where id = -1
    
        or name = #{name}
    

    
        or age < #{age}
    

我们在idea中看到直接报错了

标签名字有问题,这是因为idea会认为 < 小于号是闭合标签,我们需要使用小于号的实体,小于号的实体为 <


    select * from student
    
        
            or name = #{name}
        

        
            or age < #{age}
        
    

在测试类中进行测试:

@Test
public  void testSelectWhere() {
    SqlSession session = MyBatisUtil.getSqlSession();
    StudentDao dao = session.getMapper(StudentDao.class);

    Student student = new Student();
    student.setName("");
    student.setAge(25);

    List students = dao.selectWhere(student);
    students.forEach(stu -> System.out.println(stu));

    session.close();
}

控制台输出:

我们发现查询成功了,按理说我们测试类中给name赋了个空值,那么拼接后的sql的语句应该为:

select * from student where or age < 25

那么这样我们的语句又错了,但是我们查询结果却没有错,sql语句中也没有or,这就是标签的强大之处了,where标签会自动删除紧跟在其后的and或者or,那么这样语法就没有错误了。

4.3 动态SQL之foreach

在讲解foreach之前我们先来实现一个小案例

@Test
public void testFor() {
    List idlist = new ArrayList<>();
    idlist.add(1001);
    idlist.add(1002);
    idlist.add(1003);

    // 查询id在idlist中的student
    // select * from student where id = (1001,1002,1003)

    StringBuffer sql = new StringBuffer("");
    sql.append("select * from student where id in (");

    for (Integer i :
         idlist) {
        sql.append(i);
        sql.append(",");
    }

    sql.deleteCharAt(sql.length() - 1);
    sql.append(")");

    System.out.println(sql);
}

我们发现,要想实现这个小案例,需要写很多的代码,我们需要大量的代码来处理字符串。所以mybatis提供了foreach标签,供我们来实现循环查询

使用foreach可以循环数组,list集合,一般使用在in语法中

语法:


	#{item的值}


标签属性:
collection:表示循环的对象是数组,还是list集合。如果dao接口方法的形参是数组,collection="array",如果dao接口形参是	List,collection="list"

open:循环开始时的字符。			sql.append("(");
close:循环结束是的字符。			sql.append(")");
item:集合成员,自定义的变量。	  Integer item = idlist.get(i); //item是集合成员
separator:集合成员之间的分隔符。  sql.append(",");

#{item的值}:获取集合成员的值。
4.3.1 foreach简单类型的List

我们来举一个例子

dao接口中定义一个方法:

//foreach-1
List selectForeachOne(List idlist);

mapper文件


    select * from student
    
        where id in
        
            #{myid}
        
     

我们重新在测试类中进行测试

这样就不会出现错误了。

4.3.2 foreach对象类型的List

我们举一个例子

dao接口中定义一个方法:

//foreach-2
List selectForeachTwo(List studentList);

mapper文件中


这样我们就实现了代码的分复用

5 主配置文件

mybatis主配置文件,提供mybatis全局设置的,包含的内容日志,数据源,mapper文件位置

我们来放一个MyBatis主配置文件的模板




    
        
    

    
        
            
            
                
                
                
                
            
        
    

    
        
    

我们从上往下看

5.1 settings部分

settings是mybatis的全局设置,影响整个mybatis的运行。这个设置一般使用默认值就可以了。


一个配置完整的settings元素的示例如下:


  
  
  
  
  
  
  
  
  
  
  
  
  
  
  

5.2 typeAliases别名

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:


    
    

    
    

下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

5.3 配置环境
environments:环境标签,在它里面可以配置多个environment
		属性: default,必须是某个environment的id属性值。标识mybatis默认连接的数据库
environment:表示一个数据库的连接信息
		属性: id 自定义的环境的标识。唯一值。
transactionManager:失误管理器
		属性: type 表示失误管理器的类型
		属性值: 1. JDBC:使用Connection对象,由Mybatis自己完成事务的处理。
			   2. MANAGED:管理,表示把事务的处理交给容器实现(由其他软件完成失误的提交,回滚)
dataSource:数据源,创建的Connection对象,连接数据库
		属性: type 数据源的类型
		属性值: 1. POOLED,mybatis会在内存中创建PooledDataSource类,管理多个Connection连接对象,使用的连接池
			   2. UNPOOLED,不适用连接池,mybatis创建一个UnPooledDataSource这个类,每次执行sql语句先创建Connection对					  象,再执行sql语句,最后关闭Connection
			   3. JNDI:java的命名和目录服务。


    
        
        
        
            
            
            
            
            
            
            
            
        
    
    
    
        
        
        
            
            
            
            
            
            
            
            
        
    

5.4 使用数据库属性配置文件

需要把数据库的配置信息放到一个单独文件中,独立管理。这个文件扩展名是properties。

这个文件中,使用自定义的key=value的格式表示数据

使用步骤:

1.在resources目录汇总,创建jdbc.properties

2.在文件中,使用key=value的格式定义数据

​ 例如:jdbc.url=jdbc:mysql://localhost:3306/ssm

3.在mybatis主配置文件,使用标签引用外部的属性配置文件

4.在使用值的位置,使用${key}获取key对应的value

5.5 mapper文件的两种指定方式

第一种方式:resources="mapper文件的全限定路径名称"

例如:


    

优点:文件清晰。加载的文件时明确的,文件的位置比较灵活

缺点:文件比较多,代码量会比较大,管理难度大

第二种方式,使用

例如:


    

name:mapper文件所在的包名

特点:把这个包中的所有mapper文件,一次加载

使用要求:

  1. mapper文件和dao接口在同一目录
  2. mapper文件和dao接口名称完全一样
6 PageHelper

PageHelper做数据分页。在你的select语句后面加入分页的sql内容,如果你使用的mysql数据库,它就是在select * from student后面加上limit语句。

使用步骤:

1.加入依赖pageHelper依赖


    com.github.pagehelper
    pagehelper
    5.2.1

2.在mybatis主配置文件,加入plugin声明(在之前加入)


    

3.在select语句之前,调用PageHelper.startPage(页码,每页大小)

@Test
public  void testPageHelper() {
    SqlSession session = MyBatisUtil.getSqlSession();
    StudentDao dao = session.getMapper(StudentDao.class);

    //调用PageHelper
    PageHelper.startPage(1,3);

    List students = dao.selectAllStudents();
    students.forEach(student -> System.out.println(student));
    session.close();
}

控制台输出:

**到这里我们MyBatis就算入门了,恭喜你!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/445029.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号