SSM

MyBatis快速入门

Nick · 3月28日 · 2020年 · · · 本文9625字 · 阅读25分钟610

1、什么是框架?

它是我们软件开发中的一套解决方案,不同的框架解决的是不同的问题。
使用框架的好处:
    框架封装了很多的细节,使开发者可以使用极简的方式实现功能。大大提高开发效率。

2、三层架构

表现层:
    是用于展示数据的
业务层:
    是处理业务需求
持久层:
    是和数据库交互的

3、持久层技术解决方案

JDBC技术:
    Connection
    PreparedStatement
    ResultSet
Spring的JdbcTemplate:
    Spring中对jdbc的简单封装
Apache的DBUtils:
    它和Spring的JdbcTemplate很像,也是对Jdbc的简单封装

以上这些都不是框架
    JDBC是规范
    Spring的JdbcTemplate和Apache的DBUtils都只是工具类

4.MyBatis

mybatis的概述

mybatis是一个持久层框架,用java编写的。
它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等繁杂过程
它使用了ORM思想实现了结果集的封装。

mybatis的入门

mybatis的环境搭建

  • 第一步:创建maven工程并导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.qkongtao</groupId>
    <artifactId>MyBatis1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.35</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>
  • 创建实体类和dao的接口
package dao;
import domain.User;
import java.util.List;
/**
 *
 * 用户的持久层接口
 */
public interface IUserDao {
    /**
     * 查询所有操作
     * @return
     */
    List<User> findAll();
}
  • 创建Mybatis的主配置文件 SqlMapConifg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- mybatis的主配置文件 -->
<configuration>
    <!-- 配置环境 -->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <!-- 配置连接数据库的4个基本信息 -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/eesy"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
    <mappers>
        <mapper resource="dao/IUserDao.xml"/>
    </mappers>
     <!--起别名,可以不用谢写全限定类名-->
    <typeAliases>
        <typeAlias type="domain.User" alias="user"></typeAlias>
    </typeAliases>
</configuration>
  • 创建映射配置文件 IUserDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.IUserDao">
    <!--配置查询所有-->
    <select id="findAll" resultType="domain.User">
        select * from user
    </select>
</mapper>

环境搭建的注意事项:

  • 创建IUserDao.xml 和 IUserDao.java时名称是为了和我们之前的知识保持一致。在Mybatis中它把持久层的操作接口名称和映射文件也叫做:Mapper,所以:IUserDao 和 IUserMapper是一样的
  • 在idea中创建目录的时候,它和包是不一样的包在创建时:com.itheima.dao它是三级结构目录在创建时:com.itheima.dao是一级目录
  • mybatis的映射配置文件位置必须和dao接口的包结构相同
  • 映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名
  • 映射配置文件的操作配置(select),id属性的取值必须是dao接口的方法名

mybatis的入门案例

  1. 读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
  1. 创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
  1. 创建SqlSession
 SqlSession session = factory.openSession();
  1. 创建Dao接口的代理对象
 IUserDao userDao = session.getMapper(IUserDao.class);
  1. 执行dao中的方法
List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }
  1. 释放资源
session.close();
        in.close();

注意事项:
不要忘记在映射配置中告知mybatis要封装到哪个实体类中
配置的方式:指定实体类的全限定类名

mybatis基于注解的入门案例:

把IUserDao.xml移除,在dao接口的方法上使用@Select注解,并且指定SQL语句,同时需要在SqlMapConfig.xml中的mapper配置时,使用class属性指定dao接口的全限定类名。

package dao;

import domain.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
 *
 * 用户的持久层接口
 */
public interface IUserDao {

    /**
     * 查询所有操作
     * @return
     */
    @Select("select * from user")
    List<User> findAll();
}

明确:
我们在实际开发中,都是越简便越好,所以都是采用不写dao实现类的方式。不管使用XML还是注解配置。但是Mybatis它是支持写dao实现类的。

MyBatis连接池:

我们在实际开发中都会使用连接池。
因为它可以减少我们获取连接所消耗的时间。

mybatis中的连接池
mybatis连接池提供了3种方式的配置:
配置的位置:
主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。

 <!-- 配置数据源(连接池) -->
 <dataSource type="POOLED">
     <!-- 配置连接数据库的4个基本信息 -->
     <property name="driver" value="com.mysql.jdbc.Driver"/>
     <property name="url" value="jdbc:mysql://localhost:3306/eesy"/>
     <property name="username" value="root"/>
     <property name="password" value="root"/>
 </dataSource>

type属性的取值:
1. POOLED 采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现
2. UNPOOLED 采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。
3. JNDI 采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样。
注意:如果不是web或者maven的war工程,是不能使用的。我们使用的是tomcat服务器,采用连接池就是dbcp连接池。

MyBatis动态 SQL

  1. 动态 SQL 之标签我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。
<select id="findUserByCondition" resultMap="userMap" resultType="domain.User">
        select * from user where 1 =1
        <if test="name != null">
           and name = #{name}
        </if>
        <if test="sex != null">
            and sex = #{sex}
        </if>
</select>
  1. 动态 SQL 之标签
    为了简化上面 where 1=1 的条件拼装,我们可以采用标签来简化开发。
<select id="findUserByCondition" resultMap="userMap" resultType="domain.User">
        select * from user
        <where>
            <if test="name != null">
                and name = #{name}
            </if>
            <if test="sex != null">
                and sex = #{sex}
            </if>
        </where>
</select>
  1. 动态标签之标签
    传入多个 id 查询用户信息,用下边两个 sql 实现:
SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16)

这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。
* 在 QueryVo 中加入一个 List 集合用于封装参数

/**
    package domain;/*
 *Created by tao on 2020-03-26.
 */

import java.util.List;

public class QueryVo {
    private  User user;
    private List<Integer> ids;

    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}
  • 持久层 Dao 接口
/**
     根据QueryVo中的提供的Id集合查询用户信息
     *
     * @param vo
     * @return
     */
    List<User> findUserInIds(QueryVo vo);
  • 持久层 Dao 映射配置
<!--根据QueryVo中的Id集合查询用户列表-->
<select id="findUserInIds" resultMap="userMap" parameterType="domain.QueryVo">
   select * from user
   <where>
      <if test="ids != null and ids.size()>0">
          <foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
              #{uid}
          </foreach>
      </if>
   </where>
</select>

foreach SQL语句
* 标签用于遍历集合,它的属性:
* collection:代表要遍历的集合元素,注意编写时不要写#{}
* open:代表语句的开始部分
* close:代表结束部分
* item:代表遍历集合的每个元素,生成的变量名
* sperator:代表分隔符

MyBatis多表查询

IUserDao配置如下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="dao.IUserDao">
    <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->

    <!--一对一:定义 AccountUser 表的 accountMap-->
    <resultMap id="accountMap" type="domain.AccountUser">
        <id column="aid" property="id"/>
        <result column="uid" property="uid"/>
        <result column="money" property="money"/>
        <!-- 它是用于指定从表方的引用实体属性的 -->
        <association property="user" javaType="domain.User">
            <id column="id" property="id"/>
            <result column="name" property="name"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <result column="age" property="age"/>
        </association>
    </resultMap>

    <!--一对多:定义 user 表的 userMap-->
    <resultMap id="userMap" type="domain.User">
        <!-- 主键字段的对应 -->
        <id property="id" column="id"></id>
        <!--非主键字段的对应-->
        <result property="name" column="name"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="age" column="age"></result>
        <!-- collection 是用于建立一对多中集合属性的对应关系ofType 用于指定集合元素的数据类型-->
        <collection property="accounts" ofType="domain.Account">
            <id column="aid" property="id"/>
            <result column="uid" property="uid"/>
            <result column="money" property="money"/>
        </collection>
    </resultMap>

    <!--多对多:定义 role 表的 ResultMap-->
    <resultMap id="roleMap" type="domain.Role">
        <id property="roleId" column="rid"></id>
        <result property="roleName" column="role_name"></result>
        <result property="roleDesc" column="role_desc"></result>
        <collection property="users" ofType="domain.User">
            <id column="id" property="id"></id>
            <result column="username" property="name"></result>
            <result column="age" property="age"></result>
            <result column="sex" property="sex"></result>
            <result column="birthday" property="birthday"></result>
        </collection>
    </resultMap>


    <!-- 一对一查询所有 -->
    <select id="findAll" resultMap="accountMap">
        select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;
    </select>

    <!--一对多查询所有-->
    <select id="findAllDuo" resultMap="userMap">
      select u.*,a.id as aid ,a.uid,a.money from user u left outer join account
       a on u.id =a.uid
    </select>

    <!--一对多查询-->
    <select id="findAllDDD" resultMap="roleMap">
        select u.*,r.id as rid,r.role_name,r.role_desc from role r left outer join user_role ur on r.id = ur.rid
         left outer join user u on u.id = ur.uid;
    </select>

</mapper>
  • collection:
    部分定义了用户关联的账户信息。表示关联查询结果集
  • property="accList":
    关联查询的结果集存储在 User 对象的上哪个属性。
  • ofType="account":
    指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。

开启 Mybatis 的延迟加载策略

  • 什么是延迟加载
    在真正使用数据时才发起查询,不用的时候不查询。按需加载(懒加载)
  • 什么是立即加载
    不管用不用,只要一调用方法,马上发起查询。
  • 在对应的四种表关系中:一对多,多对一,一对一,多对多
    一对多,多对多:通常情况下我们都是采用延迟加载。
    多对一,一对一:通常情况下我们都是采用立即加载。

我们需要在 Mybatis 的配置文件 SqlMapConfig.xml 文件中添加延迟加载的配置。

<!-- 开启延迟加载的支持 -->
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>

Mybatis中的注解开发

要用注解都用注解,要用xml都用xml,不能同时存在,不然会报错

Mybatis 缓存

像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提
高性能。
Mybatis 中缓存分为一级缓存,二级缓存。
1. 什么是缓存
存在于内存中的临时数据。
2. 为什么使用缓存
减少和数据库的交互次数,提高执行效率。
什么样的数据能使用缓存,什么样的数据不能使用
3. 适用于缓存:
* 经常查询并且不经常改变的。
* 数据的正确与否对最终结果影响不大的。
4. 不适用于缓存:
* 经常改变的数据
* 数据的正确与否对最终结果影响很大的。
* 例如:商品的库存,银行的汇率,股市的牌价。

一级缓存

在不修改数据库的情况下,查询了两次,但最后只执行了一次数据库操作,这就是 Mybatis 提供给我们的一级缓存在起作用了。
**一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
**
* 手动清空一级缓存
sqlSession.clearCache();//此方法也可以清空缓存

二级缓存:

它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
二级缓存的使用步骤:

第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)

<!--配置二级缓存-->
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)

<!--开启二级缓存-->
    <cache/>

第三步:让当前的操作支持二级缓存(在select标签中配置)

 <!-- 一对一查询所有 -->
    <select id="findAll" resultMap="accountMap" useCache="true">
        select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;
    </select>
0 条回应
在线人数:1人 来访统计
隐藏