MyBatis初探

0. 重点

  1. 配置MyBatis环境
  2. CRUD操作
    1.使用xml配置文件
    2.使用注解
  3. 利用Lombok插件简化对象实例的基本操作,e.g.,getter/setter/…
  4. 查询结果处理:一对多、多对一
  5. 动态SQL:类似多态,可以根据输入的不同条件,生成对应的SQL语句

1. 简介

1.1什么是MyBatis?

  1. MyBatis 是一款优秀的持久层框架
  2. 它支持自定义 SQL、存储过程以及高级映射
  3. MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
  4. MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录

1.2怎么获取MyBatis?

Maven获取

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

Github
中文文档:https://mybatis.org/mybatis-3/zh/index.html

1.3什么是持久层?

数据持久化
持久化就是将程序的数据在持久状态和瞬时状态转化的过程
内存:断电即失
数据库(jdbc) / IO文件持久化

为什么需要持久化?
断电即失:有一些对象不能丢失

1.4持久层

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

1.5为什么需要MyBatis?

辅助程序员将数据存入数据库
传统的JDBC代码太复杂。简化,框架,自动化。

2. 第一个MyBatis程序

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

2.1 搭建环境

搭建数据库

2.2 搭建Maven项目

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

2.3 MyBatis配置

https://mybatis.org/mybatis-3/zh/getting-started.html

3.CRUD

基本步骤:

  1. 创建接口
  2. 实现接口
    a) 利用xml配置文件
    b) 利用注解
  3. 测试

3.1 查找

UserMapper.java
// 根據ID查詢用戶 定义接口
User getUserByID(int id);
UserMapper.xml

// 实现接口
<select id="getUserByID" parameterType="int" resultType="com.kuang.pojo.User">
    select * from mybatis.user where id = #{id}
</select>

UserDaoTest.java

@Test
public void getUserByID(){
    /***
     * 使用try創建sqlSession實例,避免了關閉操作
     */
    try(SqlSession sqlSession = MybatisUtils.getSqlSession()){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserByID(1);
        System.out.println(user);
    }
}

3.2 插入

// 增删改需要提交事务
@Test
public void addUser(){
    try (SqlSession sqlSession = MybatisUtils.getSqlSession()){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int res = userMapper.addUser(new User(4,"李四","123456"));
        if (res > 0){
            System.out.println("插入成功!");
        }
        // 提交事务
        // 没有这行,不能提交数据库
        sqlSession.commit();
    }
}

3.3修改

3.4删除

注:增删改需要提交事务!!!!

3.5 Map

如果数据库的表中字段太多,可以考虑用map处理。因为,每次new一个新的对象,需要对每个字段赋值,而使用map,根据key-value与数据库对应字段对应起来。

3.6 模糊查询

  1. Java代码执行的时候,传递通配符:%

  2. 在Sql拼接中使用通配符。(推荐)

<select id="likeUser" resultType="com.kuang.pojo.User">
    select * from mybatis.user where name like "%"#{value}"%"
</select>

4. 配置解析

4.1 核心配置文件

• properties(属性)
• settings(设置)
• typeAliases(类型别名)
• typeHandlers(类型处理器)
• objectFactory(对象工厂)
• plugins(插件)
• environments(环境配置)

environment(环境变量)

  1. transactionManager(事务管理器)
  2. dataSource(数据源)

• databaseIdProvider(数据库厂商标识)
• mappers(映射器)

4.2 环境配置(environments)

尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
• JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
• MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。
默认:JDBC
数据源(dataSource)
有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):
默认:POOLED
4.3属性(properties)
1.编写配置文件

<!-- <property name="driver" value="com.mysql.cj.jdbc.Driver"/>-->
<!-- <property name="url" value="jdbc:mysql://192.168.56.10:3306/mybatis?userSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>-->
<!-- <property name="username" value="root"/>-->
<!-- <property name="password" value="root"/>-->

2.在核心配置文件引入

   <properties resource="db.properties">
<!--    外部配置优先级更高    /-->
  <property name="password" value="root"/>

3.直接引入外部文件

# db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://192.168.56.10:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=root

如果字段相同,外部文件优先级更高!!!

4.4 类型别名(typeAliases)

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

Way1:

<!--给实体类起别名-->
<typeAliases>
	<typeAlias type="com.kuang.pojo.User" alias="User"/>
</typeAliases>

Way2:

<!--指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean-->
<!--在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。不区分大小写-->
    <typeAliases>
        <package name="com.kuang.pojo"/>
    </typeAliases>

 对于方法2,加注解时,类名失效;
 注2.方法一,适用于方法类少的情况;方法二,适用于方法类多的情况。

4.5映射器(mappers)

注册绑定编写的Mapper文件
四种方法:官网
方法1:

<!-- 使用相对于类路径的资源引用 -->
<!--每一个Mapper.XML都需要在此注册-->
<mappers>
    <mapper resource="com/kuang/dao/UserMapper.xml"/>
</mappers>

方法2:

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
    <mapper class="com.kuang.dao.StudentMapper"/>
    <mapper class="com.kuang.dao.TeacherMapper"/>
</mappers>

方法3:

<!-- 将包内的映射器接口实现全部注册为映射器 -->

对于方法2和方法3:
注意点:

  1. 接口与他的Mapper配置文件必须同名
  2. 接口与他的Mapper配置文件必须在同一个包下。

4.6 作用域(Scope)和生命周期

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

SqlSessionFactoryBuilder
一旦创建了 SqlSessionFactory,就不再需要它了。

SqlSessionFactory
一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
类似数据库连接池。类比线程池

SqlSession
每个线程都应该有它自己的 SqlSession 实例。类比线程
用完之后需要及时关闭,避免资源浪费

5. 属性名与字段名不一致

Eg 属性名password 字段名:pwd

利用resultMap建立属性名与字段名的对应关系。

<resultMap id="userMap" type="User">
    <result column="id" property="id"></result>
    <result column="name" property="name"/>
    <result column="pwd" property="password"/>
</resultMap>
<select id="getUserByID" parameterType="int" resultMap="userMap">
    select * from mybatis.user where id = #{id}
</select>

5.1 resultMap

是MyBatis 中最重要最强大的元素

参考:官网

6. 日志

官网
mybatis-config.xml

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

结果:

6.1日志工厂:

<configuration>
  <settings>
    ...
    <setting name="logImpl" value="LOG4J"/>
    ...
  </settings>
</configuration>

利用日志信息,调试、排错。

7. 分页

7.1 利用数据库提供的Limit实现分页查询

两个参数:startIndex和pageSize

7.2 利用Java中RowBounds实现分页(早期,不推荐)

注:前者是物理分页,后者是逻辑分页!!!
逻辑分页:先查出所有数据,然后显示指定的范围。

8. 使用注解开发

8.1 面向接口编程

8.2 使用注解开发

注解在接口上实现:

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

注册:

<mappers>
    <mapper class="com.kuang.dao.UserMapper"/>
</mappers>

测试:

    @Test
    public void getUserByID(){
        /***
         * 使用try創建sqlSession實例,避免了關閉操作
         */
//        SqlSession sqlSession1 = MybatisUtils.getSqlSession();    alt+enter 代码补全
        try(SqlSession sqlSession = MybatisUtils.getSqlSession()){
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            List<User> users = userMapper.getUsers();
//            System.out.println(users);
            for (User user : users) {
                System.out.println(user);
            }
        }

    }

结果:
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心。MyBatis建议使用xml文件配置,而非注解。

注解:
本质:反射
底层:动态代理

8.3 CRUD

// 查找所有用户
@Select("select * from user")
List<User> getUsers();

// 按id查找用户
@Select("select * from user where id = #{id}")
User getUserByID(@Param("id") int id);

// 增删改,与此类似。

// 在创建工具类的时候自动提交事务!!!
sqlSessionFactory.openSession(true);

// 不设置autoCommit,默认为false
public SqlSession openSession() {
    return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
}

public SqlSession openSession(boolean autoCommit) {
    return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, autoCommit);
}

9.Lombok

9.1.安装插件:

9.2.导入Jar包:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>

9.3.在实体类上加注解:

import lombok.Data;

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

}

9.4.原始与Lombok比较

插件,避免了重复性工作,比如,为每个属性构造getter setter方法。
原始操作:

Lombok注解:

Lombok常用的注解:
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @NoArgsConstructor
@Data
可以自定义与Lombok同时使用。并非对立。

10.查询

10.1多对一情况

问题:多个学生对应一个老师,查询每个学生信息,及其对应的老师。
普通SQL语句:

利用Mybatis
首先给出直接复制SQL语句,得到的结果:

并没有查到对应老师的信息。
原因:resultType=”Student”

返回值与此类型不匹配。
为了匹配SQL返回值类型与自定义类型,MyBatis提供两种方法:
方法1:嵌套查询

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

<resultMap id="StuTea" type="Student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>

<select id="getTeacher" resultType="Teacher">
    select * from teacher where id = #{id}
</select>

利用resultMap保存返回的结果。
方法2:联表查询

<select id="getAllStudent" resultMap="StuTea">
    select s.id as sid,s.name as sname,t.name as tname from student s, teacher t where s.tid = t.id
</select>
<resultMap id="StuTea" type="Student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>

需要指出,这两种方法的结果是一样的。
方法一是查询了teacher的所有信息(id和name),方法二只查询了teacher表的name。

10.2一对多情况

一对多的情况下,一个老师+多个学生(List),即,返回值是一个集合。此时,如何把返回值与实体类进行映射?

返回值映射到对象:

<association property="teacher" javaType="Teacher">
    <result property="name" column="tid"/>
</association>

返回值映射到集合:

<collection property="student" ofType="Student">
    <result property="name" column="sname"/>
</collection>

也是两种方法。

11. 动态SQL

官网

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。
• if
• choose (when, otherwise)
• trim (where, set)
• foreach

12. 缓存

官网

12.0 基础知识

12.0.1 什么是缓存?

存在内存中的数据

12.0.2 为什么要缓存?

查询重复数据时,不必再查询数据库,直接读取缓存即可。即:减少和数据库的交互次数,减少系统开销,提高系统效率。

12.0.3 什么样的数据使用缓存?

经常查询且不经常改变的数据

12.1一级缓存

默认开启,只在sqlSession中有效,实际相当于局部变量。

12.2二级缓存

默认开启。
开启之后,同一个Mapper里面,每一次查询的结果都可以存在缓存中(引用有最大值)。
所有的数据都先放在一级缓存中,当sqlSession关闭时,才会提交到二级缓存中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值