欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

MyBatis学习笔记

时间:2023-07-30

一 Mybatis简介

1、Mybatis简介

项目地址https://github.com/mybatis/mybatis-3/

MyBatis 是支持定制化 SQL、存储过程以及高级 映射的优秀的持久层框架。• MyBatis 避免了几乎所有的 JDBC 代码和手动设 置参数以及获取结果集• MyBatis可以使用简单的XML或注解用于配置和原 始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记 录、

2、MyBatis历史 原是Apache的一个开源项目iBatis, 2010年6月这 个项目由Apache Software Foundation 迁移到了 Google Code,随着开发团队转投Google Code 旗下, iBatis3.x正式更名为MyBatis ,代码于 2013年11月迁移到GithubiBatis一词来源于“internet”和“abatis”的组合,是 一个基于Java的持久层框架。 iBatis提供的持久 层框架包括SQL Maps和Data Access Objects (DAO)

3.为什么要使用MyBatis? MyBatis是一个半自动化的持久化层框架。JDBC – SQL夹在Java代码块里,耦合度高导致硬编码内伤 – 维护不易且实际开发需求中sql是有变化,频繁修改的情况多见 Hibernate和JPA

– 长难复杂SQL,对于Hibernate而言处理也不容易– 内部自动生产的SQL,不容易做特殊优化。– 基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难。 导致数据库性能下降。对开发人员而言,核心sql还是需要自己优化sql和java编码分开,功能边界清晰,一个专注业务、 一个专注数据



二 Mybatis hello world案例

1.HelloWorld简单版 

创建一张测试表创建对应的javaBean创建mybatis配置文件,sql映射文件 – 测试

2.Mybatis操作数据库

2.1 创建MyBatis全局配置文件 

MyBatis 的全局配置文件包含了影响 MyBatis 行为甚深 的设置(settings)和属性(properties)信息、如数据 库连接池信息等。指导着MyBatis进行工作。我们可以 参照官方文件的配置示例。

2.2 创建SQL映射文件

映射文件的作用就相当于是定义Dao接口的实现类如何 工作。这也是我们使用MyBatis时编写的最多的文件。

mysql数据库中创建表employee和相应字段创建employee java类用来封装表里面的数据,类中字段和sql表中字段名称和类型统一。创建(全局配置文件)mybatis.config.xml文件配置相应的数据库连接信息

<?xml version="1.0" encoding="UTF-8" ?>驱动地址用户名密码


编写测试类

sqlsession

public SqlSessionFactory getSqlSessionFactory() throws IOException {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);return new SqlSessionFactoryBuilder().build(inputStream);}

 测试类

@Testpublic void test() throws IOException {// 2、获取sqlSession实例,能直接执行已经映射的sql语句// sql的唯一标识:statement Unique identifier matching the statement to use.// 执行sql要用的参数:parameter A parameter object to pass to the statement.SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();SqlSession openSession = sqlSessionFactory.openSession();try {Employee employee = openSession.selectOne("com.atguigu.mybatis.EmployeeMapper.selectEmp", 1);System.out.println(employee);} finally {openSession.close();}}

创建sql 的xml 映射文件

<?xml version="1.0" encoding="UTF-8" ?> sql映射文件中加上数据库标识select EMPLOYEE_ID id,LAST_NAMElastName,EMAIL email from employees where EMPLOYEE_ID=#{id}


DB_VENDOR

会通过 DatabasemetaData#getDatabaseProductName() 返回的字符 串进行设置。由于通常情况下这个字符串都非常长而且相同产品的不 同版本会返回不同的值,所以最好通过设置属性别名来使其变短


MyBatis匹配规则如下

如果没有配置databaseIdProvider标签,那么databaseId=null如果配置了databaseIdProvider标签,使用标签配置的name去匹 配数据库信息,匹配上设置databaseId=配置指定的值,否则依旧为 null如果databaseId不为null,他只会找到配置databaseId的sql语句MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃 


8.mapper映射

mapper逐个注册SQL映射文件,将sql映射注册到全局配置中

将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中

mapper:注册一个sql映射
                注册配置文件
                resource:引用类路径下的sql映射文件
                    mybatis/mapper/EmployeeMapper.xml
                url:引用网路路径或者磁盘路径下的sql映射文件
                    file:///var/mappers/AuthorMapper.xml

或者使用批量注册:

这种方式要求SQL映射文件名必须和接口名相同并且在同一目录 


       注册接口
                class:引用(注册)接口,
                    1、有sql映射文件,映射文件名必须和接口同名,并且放在与接口同一目录下;
                    2、没有sql映射文件,所有的sql都是利用注解写在接口上;

@Select("select * from tbl_employee where id=#{id}")public Employee getEmpById(Integer id);


                    推荐:
                        比较重要的,复杂的Dao接口我们来写sql映射文件
                        不重要,简单的Dao接口为了开发快速可以使用注解;


 本章小结  每个标签都有先后顺序 标签有提示

四 MyBatis-映射文件

1.映射文件sql语句xml

映射文件(sql的xml文件)指导着MyBatis如何进行数据库增删改查(所有sql语句都在xml文件里面编写), 有着非常重要的意义

cache –命名空间的二级缓存配置cache-ref – 其他命名空间缓存配置的引用。resultMap – 自定义结果集映射parameterMap – 已废弃!老式风格的参数映射sql –抽取可重用语句块。insert – 映射插入语句update – 映射更新语句delete – 映射删除语句select – 映射查询语句


public Long addEmp(Employee employee);public boolean updateEmp(Employee employee);public void deleteEmpById(Integer id);

insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})update tbl_employee set last_name=#{lastName},email=#{email},gender=#{gender}where id=#{id}delete from tbl_employee where id=#{id}


@Testpublic void test03() throws IOException{SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();//1、获取到的SqlSession不会自动提交数据SqlSession openSession = sqlSessionFactory.openSession();try{EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);//测试添加Employee employee = new Employee(null, "jerry4",null, "1");mapper.addEmp(employee);System.out.println(employee.getId());//测试修改//Employee employee = new Employee(1, "Tom", "jerry", "0");//boolean updateEmp = mapper.updateEmp(employee);//System.out.println(updateEmp);//测试删除//mapper.deleteEmpById(2);//2、手动提交数据openSession.commit();}finally{openSession.close();}}


mybatis允许增删改直接定义以下类型返回值

Integer、Long、Boolean、void

我们需要手动提交数据

sqlSessionFactory.openSession();===》手动提交sqlSessionFactory.openSession(true);===》自动提交



 2.主键生成方式

2.1支持自增主键的数据库

若数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),则可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上。

获取自增主键的值:
        mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys();
        useGeneratedKeys="true";使用自增主键获取主键值策略
        keyProperty;指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性


2.2 不支持自增主键的数据库

对于不支持自增型主键的数据库(例如 Oracle),则可以使用 selectKey 子元素:

selectKey 元素将会首先运行,id 会被设置,然 后插入语句会被调用

获取非自增主键的值:
        Oracle不支持自增;Oracle使用序列来模拟自增;
        每次插入的数据的主键是从序列中拿到的值;如何获取到这个值

keyProperty:查出的主键值封装给javaBean的哪个属性
        order="BEFORE":当前sql在插入sql之前运行
               AFTER:当前sql在插入sql之后运行
        resultType:查出的数据的返回值类型
        
        BEFORE运行顺序:
            先运行selectKey查询id的sql;查出id值封装给javaBean的id属性
            在运行插入的sql;就可以取出id属性对应的值
        AFTER运行顺序:
            先运行插入的sql(从序列中取出新值作为id);
            再运行selectKey查询id的sql;

运行多条sql时获取是最后一条主键值


select EMPLOYEES_SEQ.nextval from dual insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) values(#{id},#{lastName},#{email})


3、参数(Parameters)传递

3.1 mybatis参数处理

单个参数

可以接受基本类型,对象类型,集合类型的值。这种情况 MyBatis可直接使用这个参数,不需要经过任何处理

多个参数

任意多个参数,都会被MyBatis重新包装成一个Map传入。 Map的key是param1,param2,0,1…,值就是参数的值。

命名参数

为参数使用@Param起一个名字,MyBatis就会将这些参数封 装进map中,key就是我们自己指定的名字

POJO

当这些参数属于我们业务POJO时,我们直接传递POJO

Map

我们也可以封装多个参数为map,直接传递


单个参数:mybatis不会做特殊处理,
    #{参数名/任意名}:取出参数值

public Employee getEmpById(Integer id);

select * from tbl_employee where id = #{id} and last_name=#{lastName}


POJO:
如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo;
    #{属性名}:取出传入的pojo的属性

public Employee getEmp(Integer id,@Param("e")Employee emp);取值:id==>#{param1} lastName===>#{param2.lastName/e.lastName}

Map:
如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map
    #{key}:取出map中对应的值

public Employee getEmpByMap(Map map);

select * from tbl_employee where id = #{id} and last_name=#{lastName}

List like = mapper.getEmpsByLastNameLike("%e%");for (Employee employee : like) {System.out.println(employee);}


select 返回map集合

返回一条记录的map;Map key就是列名(对象中的属性值),值就是对应的值

//返回一条记录的map;key就是列名,值就是对应的值public Map getEmpByIdReturnMap(Integer id);

 resultType 是map中object mybatis中起了别名 可以写map类型

select * from tbl_employee where last_name like #{lastName}

若是像让map的key为返回数据的主键,需要在接口上加上注解

//@MapKey:告诉mybatis封装这个map的时候使用哪个属性作为map的key@MapKey("id") //MapKey("lastName") 其他属性也可以public Map getEmpByLastNameLikeReturnMap(String lastName);


3.5 自动映射(自动封装) resultMap

全局setting设置 

autoMappingBehavior默认是PARTIAL,开启自动映射 的功能。唯一的要求是列名和javaBean属性名一致 如果autoMappingBehavior设置为null则会取消自动映射 数据库字段命名规范,POJO属性符合驼峰命名法,如 A_COLUMN -> aColumn,我们可以开启自动驼峰命名规 则映射功能,mapUnderscoreToCamelCase=true。自定义resultMap,实现高级结果集映射。


resultMap 内标签

constructor - 类在实例化时, 用来注入结果到构造方法中

        idArg - ID 参数; 标记结果作为 ID 可以帮助提高整体效能 

        arg - 注入到构造方法的一个普通结果

id – 一个 ID 结果; 标记结果作为 ID 可以帮助提高整体效能result – 注入到字段或 JavaBean 属性的普通结果association – 一个复杂的类型关联;许多结果将包成这种类型 

                嵌入结果映射 – 结果映射自身的关联,或者参考一个 

collection – 复杂类型的集 

                嵌入结果映射 – 结果映射自身的集,或者参考一个

discriminator – 使用结果值来决定使用哪个结果映射 

        case – 基于某些值的结果映射

                嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相同的元 素,或者它可以参照一个外部的结果映射。 id & resul 


public Employee getEmpById(Integer id);

 resultMap 和resultTYPE只能二选一

SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept dWHERe e.d_id=d.id AND e.id=#{id}

方式一  结果集映射


方式二 association


association 分步查询

 使用association进行分步查询:
        1、先按照员工id查询员工信息
        2、根据查询员工信息中的d_id值去部门表查出部门信息
        3、部门设置到员工中;

public Employee getEmpByIdStep(Integer id);

public interface DepartmentMapper {public Department getDeptById(Integer id);}

select id,dept_name departmentName from tbl_dept where id=#{id}


 association 懒加载(延迟加载)

可以使用延迟加载(懒加载);(按需加载)
         Employee==>Dept:
             我们每次查询Employee对象的时候,都将一起查询出来。
             部门信息在我们使用的时候再去查询;
             分段查询的基础之上加上两个配置

lazyLoadingEnabled 懒加载 使用时加载

aggressiveLazyLoading 侵入加载 需要时全部加载 禁用按需加载

使用时就会查询出来 不使用时不查询

System.out.println(employee);//System.out.println(employee.getDept());System.out.println(employee.getDept());

 3.7 Collection

一个部门对应多个员工

查询部门的时候将部门对应的所有员工信息也查询出来:注释在DepartmentMapper.xml中

部门类有员工集合 一对多

public class Department {private Integer id;private String departmentName;private List emps;

public Department getDeptByIdPlus(Integer id);

 部门sql xml 中

select id,dept_name from tbl_dept where id=#{id}

public interface EmployeeMapperPlus {public List getEmpsByDeptId(Integer deptId);}

扩展:多列的值传递过去:
            将多列的值封装map传递;
            column="{key1=column1,key2=column2}"
        fetchType="lazy":表示使用延迟加载;
                - lazy:延迟
                - eager:立即


3.8 鉴别器


        鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为
        封装Employee:
            如果查出的是女生:就把部门信息查询出来,否则不查询;
            如果是男生,把last_name这一列的值赋值给email;

五 MyBatis-动态SQL

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。