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

MyBatis笔记

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

MyBatis笔记

MyBatis 笔记

MyBatis 是基于 Java 语言的开源的持久层框架,利用实体类和数据表之间产生了关联,通过映射文件中的 sql 语句对数据库进行操作

使用 maven 创建工程需要导入 mybatis 的依赖:


    org.mybatis
    mybatis
    3.5.5

简单实例演示

mybatis的持久层开发有两种方式,一种是原始的 dao 开发,比较繁琐,还有一种是基于接口的 JDK 动态代理开发,也是最普遍的一种开发模式

原始dao开发模式

使用原始 dao 开发模式,首先第一步: 创建 mybatis 的核心配置文件,一般取名为 mybatis-config.xml

在dataSource标签中配置数据库连接,在mapper标签中配置xml映射文件目录,然后去书写xml映射文件



    
        
            
            
                
                
                
                
            
        
    
    
        
    

第二步:在上面的映射文件目录对应的位置创建文件

mapper 标签的 namespace 属性自定义书写,select 标签的 id 不能与其他 id 重复,resultType 是和数据库表对应的实体类的全限定路径名,实体类仅仅只有和表中字段对应的属性及 get set toString 方法而已



    
        select * from test1
    

第三步:按照上面映射文件目录创建接口

这里和上面不同的是不需要太多繁琐的结构,只需要创建一个方法即可对应mapper中的增删改查,但是需要注意一点:==接口方法名必须和mapper的CRUD标签id一致,否则会报错==

public interface BeanDao {
    List findAll();
}

第四步:创建测试类,对写好的代码进行测试

public class TestDemo {
    private SqlSessionFactory factory = null;
    @Before
    public void before(){
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream("mybatis-config.xml");
        }catch (Exception e){
            System.out.println("加载核心配置文件失败");
            System.exit(0);
        }
        this.factory = new SqlSessionFactoryBuilder().build(is);
    }
    @Test
    public void test1(){
        SqlSession session = factory.openSession();
        BeanDao mapper = session.getMapper(BeanDao.class);
        List list = mapper.findAll();
        for (Bean bean : list)
            System.out.println(bean);
    }
}

注意:在 openSession 的时候是可以传入一个 boolean 参数的,如果不传参数默认为 false,如果要执行 DML 语句进行增删改的话,一定要传入 true 做为参数,否则他不会自动提交 ( 你可以手动提交 ),查询无需提交所以不需要设置

Mybatis 的核心配置文件

mybatis 的核心配置文件,一般都起名为 mybatis-config.xml 或者是 sqlMapConfig.xml ,在核心配置文件中可以通过某些标签对 mybatis 进行一些配置

==注意:mybatis 的核心配置文件内不可以书写中文注释 (英文或数字可以),否则报错==

mybatis 提供了很多标签进行配置,但是这些标签也有着先后顺序,如果标签不按顺序书写也是会报错的

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

上面来自 mybatis 官方文档,这里会挑常用的标签进行笔记

Environments 环境配置

1. 环境的选择

在 mybatis 配置文件中使用 environments 标签配置环境,在他下面可以有一个或多个 environment 子标签,每个都代表一个环境,然后在 environments 标签中使用 default 属性对环境进行选择

这里使用 default 对环境进行选择,目前选择的是MySQL的环境


    
        这是MySQL的环境
    
    
        这是oracle的环境
    

除开配置文件内的默认环境,也可以在打开打开会话工厂的时候传入指定环境的id进行选择环境

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is, "mysql");

注意: 尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

2. 事务管理器

在每个 environment 子标签环境中有 transactionManager 标签的 type 属性可以对 SQL 进行事务控制管理,管理事务的管理器有两种:【 JDBC 】【 MANAGED 】

事务管理器说明
JDBC直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
MANAGED什么都不做,让容器来管理事务的整个生命周期,不建议使用

建议使用 JDBC 来管理事务


    

3. 数据源

数据源是配置 mybatis 和数据库进行连接的相关配置,他由 environment 标签下的 dataSource 标签进行设置

通过 dataSource 标签的 type 属性可以选择数据源类型:

类型说明
UNPOOLED只是每次被请求时打开和关闭连接,反应较慢,适用于简单小型项目
POOLED相对于UNPOOLED相比使用了 数据库连接池 的感念
JNDI能在如 EJB 或应用服务器这类容器中使用

数据源最基本的四个属性:

  • 【driver】 数据库连接驱动类
  • 【url】 数据库链接地址
  • 【username】 用户名
  • 【password】 密码

最常见的 environments 标签配置


    
        
        
            
            
            
            
        
    

Mappers 映射标签

书写的 mapper 文件需要被映射到核心配置文件中,映射的标签就是 mappers ,他下面有两个子标签,分别是 mapper 和 package 映射方法如下:

1. 映射的文件在resources目录下


    
    >
    
    

2. 映射的文件在dao包下

当 mapper 文件在 dao 包下的时,mapper 和接口必须是同名的,或者在 resources 目录下有着同级的目录


    
    
    
    

3. 接口注解开发


    

注意!当mapper文件在dao包下的时候,需要在maven的pom文件中添加如下代码,否则xml文件可能不会被打包发布


    
        
            src/main/resources
            
                ***.xml
            
            true
        
        
            src/main/java
            
                ***.xml
            
            true
        
    

Properties 属性

我们在使用传统 JDBC 的时候都会把 driver,url 等等放在一个 propertis 后缀的文件中,这样可以降低代码的耦合性,方便环境切换,mybatis 中也支持这种做法,使用 properties 标签就可以实现

1. 手写 properties 配置文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1/库名
username=root
password=*****

2. 使用 properties 标签将配置文件引入进来



TypeAliases 别名

在我们的 mapper 映射文件中,CRUD 标签中的参数,返回结果 resultType 通常都是全限定名,例如:

这个时候我们就可以使用 typeAliases 标签下的 typeAlias 子标签==配置类别名==,可以简化全限定名书写格式

abc就是这个类的类别名,就可以在映射文件中使用了


    


typeAlias 标签中的 alias 属性也可以忽略不写,默认已类名作为别名 (别名首字母小写即可)


    


但如果是个较大的项目,表和实体类比较多,如果逐个实体类配置的话会很麻烦,这时可以使用 package 子标签

将指定包下的所有类全部配置别名,别名为类本身名字 (首字母小写)


    


Settings 全局设置

在 mybatis 中可以对全局进行一些设置,设置需要用 settings 下的 setting 子标签实现,格式体现为:


  

常用的设置有:

设置名作用描述参数
cacheEnabled设置全局缓存的开启和关闭boolean
defaultStatementTimeout设置超时时间,它决定驱动等待数据库响应的秒数。任意正整数
mapUnderscoreToCamelCase是否开启驼峰命名规则boolean
logImpl配置日志信息,个人推荐使用 STDOUT_LOGGING 日志@官方文档

Mapper 映射文件

mapper 映射文件,用来负责和数据库交互的 sql 代码,主要是增删改查四个标签为主:

增删改标签

增删改标签是用来书写插入 sql 的标签,比较常用的几个属性如下:

属性作用
id用来作为标签的标识符,使用id可以直接找到当前标签调用
parameterType接受的参数的类型,如果参数类型是集合,那么就填集合内元素的类型
flushCache增删改标签默认设置为true,只要语句被调用,就会清空本地和二级缓存
timeout抛出异常之前,驱动程序等待响应的时间,默认为空值

查询标签

select 标签是用来专门书写查询语句的标签,比较常用的几个属性如下:


SELECT FROM t_user

${ } 和 #{ } 的区别

${ }和#{ }他们都是用来接收传入参数的,只不过有些细节需要留意,假设现在有一行SQL语句:

select * from t_user where userid = 1;

其中作为查询条件的 1 是需要接收传入参数的,那么获取到传入参数有两种方法:

  • ${ },拼接SQL字符串
  • #{ },作为SQL占位符

如果使用 ${} 的话,通过日志可以看到,它以拼接字符串的方式执行,这样的话就很容易收到SQL注入的攻击

select * from t_user where userid = 1;

但是如果使用 #{} 的话,他是将 SQL 代码预处理之后在执行之前进行参数替换,传入的参数都将作为普通参数对待,通过执行日志就可以看到:

select * from t_user where userid = ? ;

这是二者最明显的差距,通过占位符可以有效防止SQL注入攻击,推荐使用#{ }

ResultMap 标签

一般使用 resultType 返回对象的时候,是数据库自动检测实体类中和字段匹配的属性进行封装,但是如果实体类中的属性和表中的字段截然不同的话,就需要手动配置他们之间的映射关系了


    
    
    
    
    
     property="tel" javaType="club.hanzhe.pojo.Tel">
        
    
    
    
        
    

动态 SQL

通过传入的参数对 sql 进行灵活化使用,类似 Java 一样,通过 判断循环 来控制 SQL 的最终执行

if 判断标签

如果接收的username参数不为空的话,就追加当前标签内的sql语句


    select * from t_user
    
        
            and userid = #{userid }
        
        
            and username like #{username }
        
        
            and usersex = #{usersex }
        
        
            and usertel = #{usertel }
        
    

choose 标签

choose 标签有着和 switch 类似的功能,他要求当前判断至少成立一个才可以结束,如果没有成立的会执行otherwise


    
    
    

set 标签

使用 set 标签之后,如果 set 内有符合 if 条件的会自动添加 set 关键字,如果没有符合的就不添加,需要注意一点的是,==set → if 内的 sql 结尾一定要带上逗号==,系统会自动省略但不会自动追加。


    update t_user
    
        
            username = #{username },
        
        
            usersex = #{usersex },
        
        
            usertel = #{usertel },
        
    
    where userid = #{userid }

foreach 标签

foreach 标签用来遍历传进来的集合或数组容器,多用于批量删除操作,里面的属性解释如下:


    delete from bean where id in
    
        #{ i }
    
  • collection:传进来被遍历的那个容器的名字,可以是数组或集合
  • open:循环开始前需要添加的前缀
  • close:循环结束后需要添加的后置
  • separator:每循环一次时需要在中间添加的分隔符
  • item:被循环出来的每个字段,在标签内直接使用即可

cache 缓存标签

一级缓存

在 mybatis 中一级缓存是默认开启的,在进行 openSession 的时候就自动打开了一级缓存,且对于一级缓存的操作,只能清空,不能禁用,一级缓存的作用范围是当前的 SqlSession 实例

在同一个 SqlSession 实例中,两次同样的查询返回的结果是一致的,但是如果是两个SqlSession那么进行相同的查询结果就会不同,这里就不写了

public void test4(){
    SqlSession session = this.factory.openSession(true);
    BeanDao mapper = session.getMapper(BeanDao.class);
    Bean bean1 = mapper.findById(7844);
    Bean bean2 = mapper.findById(7844);
    System.out.println(bean1 == bean2);
}

二级缓存

二级缓存的范围是基于当前的 mapper.xml 配置文件的 mapper 标签,也就是当前的 namespace 下,一个二级缓存可以横跨多个一级缓存,而二级缓存默认是关闭的,开启二级缓存的方法就是==使用 cache标签==

没错,只要在 mapper 下面加上这么一句代码,二级缓存就开启完成了,简单粗暴

在开启二级缓存后还不能立刻使用,会报错,==需要让该 mapper 相关的所有 bean 实现 Serializable 序列化接口==

Mybatis 注解开发

CRUD 注解

在 mybatis 中也可以不使用 mapper 映射文件,改为使用注解开发,分别相对着增删改查四个注解

@Insert("insert into t_user values(null,#{name},#{sex},#{address})")
public int saveUser(User user);

@Delete(“DELETE FROM t_user WHERe u_id = #{abc}”)
public int removeUser(Integer id);

@Update(“update t_user set u_address=#{address} where u_name = #{name}”)
public int updateUser(User user);

@Select(“select * from t_user where u_id = #{abc}”)
public User findUserById( Integer id );

注意!使用 mapper 文件的时候需要扫描 mapper 文件所在位置,然后才可以使用,使用注解开发也需要扫描:

将所有带有注解的接口都扫描


    

Result 注解

使用 xml 开发时,会遇到字段与实体类属性名不匹配造成封装失败的情况,起别名解决是一种方法,但是一般都使用 resultMap 结果映射,将字段与属性匹配,注解开发也可以使用 resultMap,对应的注解是 @Results

使用注解的方式匹配字段与属性查询

@Results(
    id = "r1",  // id:给当前results起名字,像resultMap一样继承使用
    value = {   // value:配置多个映射
        
        @Result( column = "u_id" , property = "id" ),
        @Result( column = "u_name" , property = "name" ),
        @Result( column = "u_sex" , property = "sex" ),
        @Result( column = "u_address" , property = "address" )
    }
)
public User findUserById( Integer id );

如果有另一个查询与他的规则相同,那么可以引用之前写的Results的id属性

@Select("select * from t_user where u_name = #{abc}")
@ResultMap("r1")
public User findUserByName( String name );

扩展功能

Mybatis 逆向工程

逆向工程是根据数据库中表的信息进行自动创建实体类,接口,映射文件的技术

1. 环境配置

使用逆向工程必须引入他的依赖或jar包


    org.mybatis.generator
    mybatis-generator-core
    1.3.5

2. 逆向工程配置文件

你可以在任意位置 ( 包括项目外 ) 创建逆向工程所需要的配置文件,需要手动配置的地方有以下几点:

  • properties 标签中的配置文件需要自己书写,也可以书写该标签及文件
  • jdbcConnection 标签需要修改,修改需参考上面的 properties 配置文件
  • javaModelGenerator 标签需要修改,他是实体类生成的目标包路径
  • sqlMapGenerator 标签需要修改,他是 mapper 映射文件生成的目标路径
  • javaClientGenerator 标签需要修改,他是接口生成的目标包路径
  • table 标签的 tableName 属性需要修改,他是逆向工程所参考的数据表
    • 如有多个表被参考就书写多个 table 标签,可以直接复制修改 tableName 属性



    
    
        
            
            
        
        
        
        
        
            
        
        
        
            
            
            
            
        
        
        
            
        
        
        
            
        
        
        

3. 使用逆向工程

在环境配置完成后使用下面这段模板代码,运行后就会将实体类,接口,mapper文件自动生成

需要在改代码中手动设置配置文件的文件名及位置

import org.junit.Test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Generator {
@Test
public void create(){
try {
List warnings = new ArrayList();
boolean overWriter = true;
// 这里加载刚刚创建的逆向工程配置文件
File configFile = new File(“文件位于磁盘的绝对路径”);
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overWriter);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}catch (Exception e){
System.out.println(“操作失败!”);
System.out.println(“==================================================”);
System.out.println(e);
e.printStackTrace();
}
}
}

PageHelper 分页插件

pageHelper 插件是针对 mybatis 设计的一款分页插件,通过拦截器对 sql 进行操作,使其拥有分页的能力

1. 环境配置

使用 pageHelper 分页插件需要导入他的 maven 依赖或者导入他的 jar 包


    com.github.pagehelper
    pagehelper
    
    5.0.0

在 maven 依赖添加完成后,还需要在 mybatis 的核心配置文件中使用 plugins 标签注册 pageHelper 插件


    

2. 使用PageHelper

PageHelper 依赖引入后,在程序中就有了 PageHelper 类,调用它的 startPage 静态方法,后紧跟的第一条查询语句就是分页查询

startPage 的静态方法需要两个参数,第一个是查询的页码,第二个是每页的查询数量

public void test1(){
    // 查询第二页,每页5条记录
    PageHelper.startPage(2, 5);
    List list = mapper.findAll();
    for (Bean bean : list)
        System.out.println(bean);
    System.out.println(list);
}

分页除了 PageHelper 类,还有一个 PageInfo 可以使用,将查询的结果封装到 PageInfo 中,可以查询一些和分页相关的信息

public void test1(){
    SqlSession session = factory.openSession();
    BeanDao mapper = session.getMapper(BeanDao.class);
    PageHelper.startPage(2, 5, true);
    PageInfo info = new PageInfo(mapper.findAll());
    System.out.println("总页码:" + info.getPages());
    System.out.println("总记录数:" + info.getTotal());
    System.out.println("结果集:");
    List list = info.getList();
    for (Bean bean : list)
        System.out.println(bean);
}

3. PageInfo常用参数

在将结果集封装到 PageInfo 中的时候,可以可选性的传入一个导航页码的参数,可以获取到和当前页相邻的页码

public void test1(){
    SqlSession session = factory.openSession();
    BeanDao mapper = session.getMapper(BeanDao.class);
    PageHelper.startPage(201, 5, true);
    // 在创建info对象的时候可以跟随一个int类型,这个值是当前页附近的页码的数量
    PageInfo info = new PageInfo(mapper.findAll(), 7);
    System.out.println("当前页:" + info.getPageNum());
    System.out.println("每页显示数量:" + info.getPageSize());
    System.out.println("当前页信息:");
    for (Object obj : info.getList())
        System.out.println(obj);
    System.out.println("总页码:" + info.getPages());
    System.out.println("总记录数:" + info.getTotal());
    System.out.println("上一页:" + info.getPrePage());
    System.out.println("下一页:" + info.getNextPage());
    System.out.println("是否首页:" + info.isIsFirstPage());
    System.out.println("是否尾页:" + info.isIsLastPage());
    System.out.println("导航条页码:");
    for (int page : info.getNavigatepageNums() )
        System.out.print( page + "  " );
    System.out.println("n导航条中首页" + info.getNavigateFirstPage());
    System.out.println("导航条中尾页" + info.getNavigateLastPage());
}
  • 这里需要注意!==每页显示数量是指分页是设置的数量==,例如设置每页只显示5条,获取到的就是5,而不是最后一页只显示三条就返回三,这是错误的

合理化查询

在网页中往往有些人会钻空子乱改数据,例如只有20页数据,他修改了参数请求到了第50页,这种情况经常会发生,所以在注册 pageHelper 的时候可以添加一个参数使数据变得合理化


    

Lombok 插件

在我们进行查询的时候,需要将查询的结果封装到指定的实体类中,而对应的实例类需要书写响应的 get set 方法,构造方法及 toString 方法,这样比较麻烦,这是可以使用 lombok 插件进行自动生成功能

1. 环境配置

使用 lombok 需要引入他的 maven 依赖


    org.projectlombok
    lombok
    1.18.8

在依赖引入后还需要在编辑器中安装 lombok 的插件 ( IDEA 编辑器为例 ) File → settings → plugins → install JetBrains plugin... 在里面搜索 lombok 下载安装,而后在 file → settings → build,Exe.. → Compiler → Annotation Pro... 里面选中当前项目,在右面的 Enable annotation processing 选项打勾

2. 使用 Lombok 插件

在目标实体类上,只需要书写好属性即可,无需书写其他多余方法,使用 lombok 提供的注解用来一键生成:

注解作用
@Getter一键生成所有 get 方法
@Setter一键生成所有 set 方法
@ToString一键生成 toString 方法
@Data一键生成 get set toString 等方法
@NoArgsConstructor生成无参构造方法
@AllArgsConstructor生成有参构造方法

 

更多学习资料请微信搜万神小栈

 

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

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

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