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

Mybatis学习笔记 : )

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

Mybatis学习笔记 : )

Mybatis 概述

Mybatis是什么?有什么特点?

它是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL延迟加载和缓存等特性,但它的数据库无关性较低

  1. 什么是ORM?

    Object Relation Mapping,对象关系映射。对象指的是Java对象,关系指的是数据库中的关系模型,对象关系映射,指的就是在Java对象和数据库的关系模型之间建立一种对应关系,比如用一个Java的Student类,去对应数据库中的一张student表,类中的属性和表中的列一一对应。Student类就对应student表,一个Student对象就对应student表中的一行数据

  2. 为什么mybatis是半自动的orm框架

    由于mybatis需要手写SQL语句,所以它有较高的灵活性,可以根据需要,自由地对SQL进行定制,也因为要手写SQL,当要切换数据库时,SQL语句可能就要重写,因为不同的数据库有不同的方言(Dialect),所以mybatis的数据库无关性低。虽然mybatis需要手写SQL,但相比JDBC,它提供了输入映射和输出映射,可以很方便地进行SQL参数设置,以及结果集封装。并且还提供了关联查询和动态SQL等功能,极大地提升了开发的效率。

基本流程
  1. 编写全局配置文件
  2. 编写mapper映射文件
  3. 加载全局配置文件,生成SqlSessionFactory
  4. 创建SqlSession,调用mapper映射文件中的SQL语句来执行CRUD操作

事例:

数据库创建表

创建maven项目

在父工程中倒入依赖的jar包
 
   
    
        mysql
        mysql-connector-java
        8.0.26
    
   
    
        org.mybatis
        mybatis
        3.5.2
    
   
    
        junit
        junit
        4.12
        test
    
   
        
            org.projectlombok
            lombok
            1.18.12
            provided
        

    
创建一个pojo实体类
package com.kang.pojo;

import lombok.*;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class user {
    private int id;
    private String name;
    private String pwd;
    private Integer score;
    private Integer gender;

}

编写mapper映射文件(编写SQL)




    
    
    select * from USER
  
    
        insert into user (name,score,gender,id,pwd)value (#{name}.#{score},#{gender},#{id},#{pwd});
    
    
        delete from user where id = #{id};
    

编写properties文件
db.url = jdbc:mysql://localhost:3306/myBatis
db.user = root
db.pwd = 12345678
db.driver = com.mysql.cj.jdbc.Driver
编写全局配置文件

        

    
    
        
            
            

                
                
                
                
            
        
    
    
    
        
    
     
编写dao类
package com.kang.dao;

import com.kang.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 java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class StudentDao {

	private SqlSessionFactory sqlSessionFactory;

	public StudentDao(String configPath) throws IOException {
		InputStream inputStream = Resources.getResourceAsStream(configPath);
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	}

	public List findAll() {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		List studentList = sqlSession.selectList("findAll");
		sqlSession.close();
		return studentList;
	}

	public int addStudent(user user) {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		int rowsAffected = sqlSession.insert("insert", user);
		sqlSession.commit();
		sqlSession.close();
		return rowsAffected;
	}

	public int deleteStudent(int id) {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		int rowsAffected = sqlSession.delete("delete",id);
		sqlSession.commit();
		sqlSession.close();
		return rowsAffected;
	}
}
测试
package com.kang.dao;

import com.kang.pojo.user;
import org.junit.Before;
import org.junit.Test;

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

public class SimpleTest {

	private StudentDao studentDao;

	@Before
	public void init() throws IOException {
		studentDao = new StudentDao("mybatis-config.xml");
	}

	@Test
	public void insertTest() {
		user user = new user();
		user.setName("yogurt");
		user.setId(4);
		user.setGender(1);
		user.setScore(100);
		user.setPwd("77777777");
		studentDao.addStudent(user);
	}

	@Test
	public void findAllTest() {
		List all = studentDao.findAll();
		for (user user : all) {
			System.out.println(user.toString());
		}
	}
}

结果展示


总结事件
  1. 在编写mapper映射文件时,select和insert中resultType和parameterType区别:

    1. 使用resultType :主要针对于从数据库中提取相应的数据出来

    2. 使用parameterType :主要针对于将信息存入到数据库中

    3. resultType:

      • 基本数据类型
      • pojo类类型。mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。如果对有多条数据,则分别映射,并把对象放到list容器中。所以即使返回时list数组,resultType也是pojo类型
    4. parameterType:

      • 基本数据类型
      • 复杂数据类型(如类和Map)
  2. 关于注解开发,在测试类中没有识别到Lombok的@Getter和@Setter

    • 处于idea的问题,问题汇报并不影响程序的执行,他没有识别到而已并不代表我们没有
    • 可以配置idea让他对于这个问题不报错(不推荐)
  3. 关于静态资源过滤问题:

    在平常我们编写的时候可能会遇到在target中找不到对应的文件,我们有两种方式来解决

    1. 在子项目的pom.xml中加入静态资源过滤

      
                  
                      src/main/java
                      
                          ***.xml
                      
                      false
                  
      
                  
                      src/main/resources
                      
                          ***.xml
                      
                      false
                  
      
      
              
      
    2. 在resource目录下添加相同路径的包,然后将映射文件放到这个包的路径之下

XML配置 全局配置文件标签顺序

	

为了方便理解,将测试流程中的全局配置文件拿来

这个之中只有简单的三个,,,其实还有好多,但是目前还没有接触到,我们要严格遵守他定义的顺序,那么接下来解析一下每个标签的作用

自标签的说明 properties

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。(注意,这里的代码个人理解的意思为自定义properties里的内容,他的优先级要高于在文件中的初始定义,在使用时自动覆盖掉源文件中的对应信息)


  
  

设置好的属性可以在整个配置文件中用来替换需要动态配置的属性值。




  
  
  	
  	
  	
  	
  
 

我们一般将数据源的信息单独放在一个properties文件中,然后用这个标签引入后,在下面的environment标签中,就可以用${}占位符快速获取数据源信息

mybatis家在配置的顺序

首先读取在properties元素体中的指定的属性

然后根据properties元素中的resource属性读取类路径下的属性文件,或根据url属性指定的路径读取属性文件,并覆盖掉之前读取的同名属性

最后读取作为方法参数传递的属性,并覆盖掉之前的同名属性

settings

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。用来开启或关闭mybatis的一些特性,比如可以用来开启延迟加载,可以用来开启二级缓存

大致浏览:

展示一下配置完整的settings元素的示例


  
  
  
  
  
  
  
  
  
  
  
  
  
  
  

typeAliases

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


  
  
  
  
  
  

这样做的目的是为了简化我们使用全名称地址,在任何我们需要用到全名称地址的时候我们可以使用他的alias别名

每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。见下面的例子:

@Alias("author")
public class Author {
    ...
}
typeHandlers

用于处理Java类型和Jdbc类型之间的转换,mybatis有许多内置的TypeHandler,比如StringTypeHandler,会处理Java类型String和Jdbc类型CHAR和VARCHAR。这个标签用的不多

objectFactory

mybatis会根据resultType或resultMap的属性来将查询得到的结果封装成对应的Java类,它有一个默认的DefaultObjectFactory,用于创建对象实例,这个标签用的也不多

plugins

可以用来配置mybatis的插件,比如在开发中经常需要对查询结果进行分页,就需要用到pageHelper分页插件,这些插件就是通过这个标签进行配置的。在mybatis底层,运用了责任链模式+动态代理去实现插件的功能

MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看 MyBatis 发行包中的源代码。 如果你想做的不仅仅是监控方法的调用,那么你最好相当了解要重写的方法的行为。 因为在试图修改或重写已有方法的行为时,很可能会破坏 MyBatis 的核心模块。 这些都是更底层的类和方法,所以使用插件的时候要特别当心。

通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。

// ExamplePlugin.java
@Intercepts({@Signature(type= Executor.class,method = "update",args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
  private Properties properties = new Properties();
  public Object intercept(Invocation invocation) throws Throwable {
    // implement pre processing if need
    Object returnObject = invocation.proceed();
    // implement post processing if need
    return returnObject;
  }
  public void setProperties(Properties properties) {
    this.properties = properties;
  }
}

  
    
  

上面的插件将会拦截在 Executor 实例中所有的 “update” 方法调用, 这里的 Executor 是负责执行底层映射语句的内部对象。

提示 覆盖配置类

除了用插件来修改 MyBatis 核心行为以外,还可以通过完全覆盖配置类来达到目的。只需继承配置类后覆盖其中的某个方法,再把它传递到 SqlSessionFactoryBuilder.build(myConfig) 方法即可。再次重申,这可能会极大影响 MyBatis 的行为,务请慎之又慎。

environments

用来配置数据源,MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景,==尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。==所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个SqlSessionFactory。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单

  • 每个数据库对应一个 SqlSessionFactory 实例

为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);

如果忽略了环境参数,那么将会加载默认环境,如下所示:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);

注意一些关键点:

  • 默认使用的环境 ID(比如:default=“development”)。
  • 每个 environment 元素定义的环境 ID(比如:id=“development”)。
  • 事务管理器的配置(比如:type=“JDBC”)。
  • 数据源的配置(比如:type=“POOLED”)。

默认环境和环境 ID 顾名思义。 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。

mapper

用来配置mapper.xml映射文件,这些xml文件里都是SQL语句,举个简单的例子,在笔记的开头我们的示例中

mapper就是注册这个文件然后进行使用的

对于简单类型(8种java原始类型再加一个String)的入参,${}中参数的名字必须是value,例子如下


        SELECT * FROM student;
    

    
        INSERT INTO student (name,age) VALUES (#{name},#{age});
    

    
        DELETE FROM student WHERe id = #{id};
    

    
  SELECT * FROM BLOG WHERe state = ‘ACTIVE’
  
    
      AND title like #{title}
    
    
      AND author_name like #{author.name}
    
    
      AND featured = 1
    
  

有一些像java的switch

where

        SELECT * FROM student WHERe id in
        
          #{item}
        

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!

提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

至此,我们已经完成了与 XML 配置及映射文件相关的讨论。下一章将详细探讨 Java API,以便你能充分利用已经创建的映射配置。


	SELECT * FROM user
	



     
         
         	AND username like '%${user.name}%'
         
     

bind

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


  select id, username, hashedPassword
  from some_table
  where id = #{id}

在这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 JavaBean 的属性上。如果列名和属性名不能匹配上,可以在 SELECT 语句中设置列别名(这是一个基本的 SQL 特性)来完成匹配。比如:


  select user_id, user_name, hashed_password
  from some_table
  where id = #{id}

下面介绍一些常见的resultMap外部配置的标签

他的属性:

id和result

这些元素是结果映射的基础。idresult 元素都将一个列的值映射到一个简单数据类型(String, int, double, Date 等)的属性或字段。

这两者之间的唯一不同是,id 元素对应的属性会被标记为对象的标识符,在比较对象实例时使用。 这样可以提高整体的性能,尤其是进行缓存和嵌套结果映射(也就是连接映射)的时候。

两个元素都有一些属性:

关联(多对一)

  
  

关联(association)元素处理“有一个”类型的关系。 比如,在我们的示例中,一个博客有一个用户。关联结果映射和其它类型的映射工作方式差不多。 你需要指定目标属性名以及属性的javaType(很多时候 MyBatis 可以自己推断出来),在必要的情况下你还可以设置 JDBC 类型,如果你想覆盖获取结果值的过程,还可以设置类型处理器。

关联的不同之处是,你需要告诉 MyBatis 如何加载关联。MyBatis 有两种不同的方式加载关联:

  • 嵌套 Select 查询:通过执行另外一个 SQL 映射语句来加载期望的复杂类型。
  • 嵌套结果映射:使用嵌套的结果映射来处理连接结果的重复子集。

首先,先让我们来看看这个元素的属性。你将会发现,和普通的结果映射相比,它只在 select 和 resultMap 属性上有所不同。

关联的嵌套 Select 查询

不推荐,因为在大型数据集或大型数据表上表现不佳。这个问题被称为“N+1 查询问题”。 概括地讲,N+1 查询问题是这样子的:

  • 你执行了一个单独的 SQL 语句来获取结果的一个列表(就是“+1”)。
  • 对列表返回的每条记录,你执行一个 select 查询语句来为每条记录加载详细信息(就是“N”)。

这个问题会导致成百上千的 SQL 语句被执行。有时候,我们不希望产生这样的后果。

关联查询的结果集映射

现在我们可以映射这个结果:


  
  
  



  
  
  
  
  

在上面的例子中,你可以看到,博客(Blog)作者(author)的关联元素委托名为 “authorResult” 的结果映射来加载作者对象的实例。

非常重要: id 元素在嵌套结果映射中扮演着非常重要的角色。你应该总是指定一个或多个可以唯一标识结果的属性。 虽然,即使不指定这个属性,MyBatis 仍然可以工作,但是会产生严重的性能问题。 只需要指定可以唯一标识结果的最少属性。显然,你可以选择主键(复合主键也可以)。

现在,上面的示例使用了外部的结果映射元素来映射关联。这使得 Author 的结果映射可以被重用。 然而,如果你不打算重用它,或者你更喜欢将你所有的结果映射放在一个具有描述性的结果映射元素中。 你可以直接将结果映射作为子元素嵌套在内。这里给出使用这种方式的等效例子:


  
  
  
    
    
    
    
    
  

集合(一对多)

  
  
  

集合元素和关联元素几乎是一样的,它们相似的程度之高,以致于没有必要再介绍集合元素的相似部分。 所以让我们来关注它们的不同之处吧。

我们来继续上面的示例,一个博客(Blog)只有一个作者(Author)。但一个博客有很多文章(Post)。 在博客类中,这可以用下面的写法来表示

private List posts;

要像上面这样,映射嵌套结果集合到一个 List 中,可以使用集合元素。 和关联元素一样,我们可以使用嵌套 Select 查询,或基于连接的嵌套结果映射集合。

集合的嵌套 Select 查询

首先,让我们看看如何使用嵌套 Select 查询来为博客加载文章。


  



  SELECT * FROM POST WHERe BLOG_ID = #{id}

你可能会立刻注意到几个不同,但大部分都和我们上面学习过的关联元素非常相似。 首先,你会注意到我们使用的是集合元素。 接下来你会注意到有一个新的 “ofType” 属性。这个属性非常重要,它用来将 JavaBean(或字段)属性的类型和集合存储的类型区分开来。 所以你可以按照下面这样来阅读映射:


读作: “posts 是一个存储 Post 的 ArrayList 集合”

在一般情况下,MyBatis 可以推断 javaType 属性,因此并不需要填写。所以很多时候你可以简略成:


集合的嵌套结果映射

现在你可能已经猜到了集合的嵌套结果映射是怎样工作的——除了新增的 “ofType” 属性,它和关联的完全相同。

首先, 让我们看看对应的 SQL 语句:


我们再次连接了博客表和文章表,并且为每一列都赋予了一个有意义的别名,以便映射保持简单。 要映射博客里面的文章集合,就这么简单:


  
  
  
    
    
    
  

再提醒一次,要记得上面 id 元素的重要性,如果你不记得了,请阅读关联部分的相关部分。

以上内容大部分来自官方文档还有个人学习笔记,主要涉及到的点是我们作为新手会经常遇到的问题还有需要掌握的知识点 (个人认为)。一点也不辛苦主要是为了日后重新回顾用的哈哈哈希望大家不要点赞,如果有兴趣交流的小伙伴可以私信我的微信:H-20200406

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

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

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