MyBatis(4)学习内容

一、MyBatis分页插件

1.1 分页插件的介绍

分页是一种将所有数据分段展示给用户的技术.用户每次看到的不是全部数据,而是其中的一部分,如果在其中没有找到自己想要的内容,用户可以通过制定页码或是翻页的方式转换可见内容,直到找到自己想要的内容为止。

分页的的好处:

1.提高性能,一次查20个,比一次查20000个性能肯定更好;另外如果数据量很大,一次性将内容都查询出来,查询出来的结果是放在内存里面的,会增加cpu的开销造成内存的浪费,效率极低。

2.展现层面的考虑:如果一次展现太多的数据,不管是排版,还是美观上都不好。

1.2 分页插件的引入和配置

(1).在pom.xml中引入插件依赖

(2).在mybatis核心配置文件中进行配置

1.3 定义UserMapper接口方法

1.4 配置UserMapper.xml映射文件

1.5 测试分页插件作用

二、MyBatis的注解开发

2.1 注解开发的背景介绍

注解提供了一种简单的方式来实现简单映射语句,而不会引入大量的开销。能够读懂别人写的代码,特别是框架相关的代码。本来可能需要很多配置文件,需要很多逻辑才能实现的内容,就可以使用一个或者多个注解来替代,这样就使得编程更加简洁,代码更加清晰。

2.2 常用注解介绍

这几年来注解开发越来越流行,Mybatis 也可以使用注解开发方式,这样我们就可以减少编写 Mapper 映射文件了。

本次我们先围绕一些基本的 CRUD 来学习,再学习复杂映射关系及延迟加载。

@Insert: 实现新增

@Update: 实现更新

@Delete: 实现删除

@Select: 实现查询

@Result: 实现结果集封装

@Results: 这个注解用于定义结果集映射,它包含了一个或多个 @Result 注解,每个 @Result 注解指定了一个数据库字段到 Java 对象属性的映射

@ResultMap: 实现引用 @Results 定义的封装

@One: 实现一对一结果集封装

@Many: 实现一对多结果集封装

@CacheNamespace: 在类名上加入注解,实现注解二级缓存的使用

三、项目环境搭建

3.1 构建maven工程,导入依赖

3.2 加入配置文件

加入mybatis核心配置文件,log4j.properties配置文件、db.properties配置文件、MybatisUtil.java工具类,加入到项目中

四、使用 Mybatis 注解实现基本 CRUD

4.1 编写实体类

package com.sy.pojo;

import java.io.Serializable;
import java.util.List;

public class User implements Serializable {
    private int id; //编号id
    private String username; //用户名
    private String password; //密码
    private int age; //年龄
    private String sex; //性别
    private String email; //邮箱

    private List<Order> orderList;

    public List<Order> getOrderList() {
        return orderList;
    }

    public void setOrderList(List<Order> orderList) {
        this.orderList = orderList;
    }

    public User() {
    }

    public User(String username, String password, int age, String sex, String email) {
        this.username = username;
        this.password = password;
        this.age = age;
        this.sex = sex;
        this.email = email;
    }

    public User(int id, String username, String password, int age, String sex, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
        this.sex = sex;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", email='" + email + '\'' +
                ", orderList=" + orderList +
                '}';
    }

}

package com.sy.pojo;

public class Order {
    // 订单id
    private Integer id;
    // 用户id,该属性名和数据库的字段名不一致
    private Integer userId;
    // 订单号
    private String number;
    // 订单创建时间
    private String createTime;
    // 备注
    private String note;
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Order() {
    }

    public Order(Integer userId, String number, String createTime, String note) {
        this.userId = userId;
        this.number = number;
        this.createTime = createTime;
        this.note = note;
    }

    public Order(Integer id, Integer userId, String number, String createTime, String note) {
        this.id = id;
        this.userId = userId;
        this.number = number;
        this.createTime = createTime;
        this.note = note;
    }



    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getCreateTime() {
        return createTime;
    }

    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    @Override
    public String toString() {
        return "Order{" +
                "id=" + id +
                ", userId=" + userId +
                ", number='" + number + '\'' +
                ", createTime='" + createTime + '\'' +
                ", note='" + note + '\'' +
                ", user=" + user +
                '}';
    }
}

4.2 编写 SqlMapConfig 配置文件

<?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">
<configuration>

    <!--
        SqlMapConfig.xml 中配置的内容和顺序如下:
            1. properties(属性)
            2. settings(全局配置参数)
            3. typeAliases(类型别名)
            4. plugins(插件)
            5. environments(环境集合属性对象)
               ==environment(环境子属性对象)
               ====transactionManager(事务管理)
               ======dataSource(数据源)
            6. mappers(映射器)
    -->

    <!--引入数据源 db.properties文件   用resource属性加载外部配置文件 -->
    <properties resource="db.properties"></properties>

    <!--配置使用的日志-->
    <settings>
        <!--
            配置使用的日志:
                value="STDOUT_LOGGING":mybatis自带的日志输出
                value="log4j": 当然也可以设置为log4j
        -->
        <setting name="logImpl" value="log4j"/>

        <!--依赖包的问题:空指针异常-->
        <!-- 全局开启延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 当启用时,有会话时,会执行延迟加载 -->
        <setting name="aggressiveLazyLoading" value="false"/>

        <!-- 开启二级缓存的支持 -->
        <setting name="cacheEnabled" value="true"/>

    </settings>

    <!--设置别名  typeAliases类型别名-->
    <typeAliases>
        <!--别名定义:针对单个别名定义 type:类型的路径; alias:别名-->
        <!--可以为多个实体类配置别名    别名的大小写没有影响-->
        <!--<typeAlias type="com.sy.pojo.User" alias="user"/>-->

        <!--
            批量别名的定义: (常用)
            package:指定包名,mybatis会自动扫描包中的pojo类,
                    自动定义别名,别名就是类名(首字母大写或小写都可以)
        -->
        <!--扫描包 的方式-->
        <package name="com.sy.pojo"/>
    </typeAliases>

    <!--分页插件-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

    <!--
        environments:设置多个连接数据库的环境
        属性:
            default:设置默认使用的环境的id(development代表开发环境下)
    -->
    <environments default="development">
        <!--
            environment:设置具体的连接数据库的环境信息
            属性:
                id:设置环境的唯一标识,可通过environments标签中的
                default设置某一个环境的id,表示默认使用的环境
        -->
        <environment id="development">
            <!--
                transactionManager:设置事务管理方式
                属性:
                    type:设置事务管理方式,type="JDBC|MANAGED"
                    type="JDBC":说明当前mybatis事务管理使用的是connection的机制,connection.commit().connection.rollback()等
                    type="MANAGED":mybatis不管理事务了,交给其他外部第三方框架管理,比如和Spring整合之后交给Spring管理
            -->
            <transactionManager type="JDBC"/>
            <!--
                dataSource:设置数据源
                属性:
                    type:设置数据源的类型,type="POOLED|UNPOOLED|JNDI"
                    type="POOLED":使用POOLED连接池,这种数据源的实现利用“池”的概念将 JDBC
                    连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。
                    type="UNPOOLED":不使用数据库连接池,即每次使用连接都需要重新创建
                    type="JNDI":调用上下文中的数据源
            -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>

        <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=UTC&amp;useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
        <!--在xml文件中用&amp;  在properties文件中用&-->
    </environments>

    <!--加载映射文件-->
    <mappers>
        <!--包扫描  要求:mapper接口名称和mapper映射文件名称相同-->
        <package name="com.sy.mapper"/>
    </mappers>

</configuration>

4.3 使用注解方式开发持久层接口

package com.sy.mapper;

import com.sy.pojo.Order;
import com.sy.pojo.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;
//开启二级缓存的支持
@CacheNamespace
public interface OrderMapper {

    /**
     * 查询所有订单
     */
    @Results(id = "orderResult",value = {
            @Result(id = true,column = "id",property = "id"),
            @Result(column = "user_id",property = "userId"),
            @Result(column = "number",property = "number"),
            @Result(column = "create_time",property = "createTime"),
            @Result(column = "note",property = "note"),
    })
    @Select("select * from orders")
    List<Order> queryOrderList();

    /**
     * 根据用户id查询订单
     */
    @ResultMap(value = "orderResult")
    @Select("select * from orders where user_id = #{uid}")
    List<Order> queryOrderByUid(Integer uid);

    /**
     * 添加订单信息
     @SelectKey注解: 则用于定义一个查询,这个查询通常是用来获取最后插入的记录的ID
      *      属性:
      *          statement属性: 用于指定查询最后生成的主键值的SQL语句
      *          keyProperty属性: 用于指定将获取到的主键值赋值给哪个属性
      *          keyColumn属性: 表示将查询结果赋值给数据表中的哪一列
      *          before属性: 用于指定在插入数据之前还是之后执行这个查询
      *          resultType属性: 用于指定查询返回的结果类型
      *     LAST_INSERT_ID()是MySQL特有的函数,用于获取最后一次插入生成的自增ID
      */
    @Insert("insert into orders ( user_id, number, create_time, note)" +
            "values (#{userId},#{number},#{createTime},#{note})")
    @SelectKey(statement = "SELECT LAST_INSERT_ID()", before = false,
            keyColumn = "id", keyProperty = "id", resultType = Integer.class)
    Integer addOrder(Order order);

    /**
     * 修改订单信息
     *
     */
    @Update("update orders set number = #{number},note = #{note} where id = #{id}")
    Integer updateOrderById(Order order);

    /**
     * 删除订单信息
     */
    @Delete("delete from orders where id = #{id}")
    Integer deleteOrderById(Integer id);

    //需求:查询每个订单对应的用户信息(嵌套查询)
    @Results(value = {
            //订单信息
            @Result(id = true,column = "id",property = "id"),
            @Result(column = "user_id",property = "userId"),
            @Result(column = "number",property = "number"),
            @Result(column = "create_time",property = "createTime"),
            @Result(column = "note",property = "note"),
            //用户信息
            @Result(property = "user",javaType = User.class,column = "user_id",
                one=@One(select = "com.sy.mapper.UserMapper.queryById",fetchType = FetchType.LAZY)
            )
    })
    @Select("select * from orders")
    List<Order> queryOrderUser();

}

4.4 编写测试方法

package com.sy.test;

import com.sy.mapper.OrderMapper;
import com.sy.pojo.Order;
import com.sy.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class OrderMapperTest {
    //查询所有订单
    @Test
    public void queryOrderListTest(){

        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        List<Order> orders = mapper.queryOrderList();
        for (Order order : orders) {
            System.out.println(order);
        }
        MyBatisUtils.close(sqlSession);

    }

    //根据用户id查询订单
    @Test
    public void queryOrderByUidTest(){

        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        List<Order> orders = mapper.queryOrderByUid(1);
        for (Order order : orders) {
            System.out.println(order);
        }
        MyBatisUtils.close(sqlSession);

    }

    //添加订单信息
    @Test
    public void addOrderTest(){

        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        Order order = new Order(3, "1000014", "2015-02-12 16:13:25", "新增订单");
        int i = mapper.addOrder(order);
        if (i > 0){
            System.out.println("更新了: " + i + " 条数据");
        }
        System.out.println(order);

        MyBatisUtils.close(sqlSession);

    }

    // 修改订单信息
    @Test
    public void updateOrderByIdTest(){

        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        Order order = new Order();
        order.setId(6);
        order.setNumber("1000015");
        order.setNote("修改订单");
        int i = mapper.updateOrderById(order);
        if (i > 0){
            System.out.println("修改成功");
        }

        MyBatisUtils.close(sqlSession);

    }

    //删除订单信息
    @Test
    public void deleteOrderByIdTest(){

        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        Integer i = mapper.deleteOrderById(4);
        if (i > 0){
            System.out.println("删除成功");
        }
        MyBatisUtils.close(sqlSession);

    }

    //需求:查询每个订单对应的用户信息(嵌套查询)
    @Test
    public void queryOrderUserTest(){

        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        List<Order> orders = mapper.queryOrderUser();
        for (Order order : orders) {
            System.out.println(order);
        }
        MyBatisUtils.close(sqlSession);

    }

}

五、使用注解实现复杂关系映射开发

5.1 复杂关系映射的注解介绍

1. @Results 注解:

代替的是标签<resultMap>

该注解中可以使用单个@Result 注解,也可以使用@Result 集合

@Results({@Result(),@Result()})或@Results(@Result())

2. @Resutl 注解:

代替了 <id> 标签和<result> 标签

@Result 中 属性介绍:

id 是否是主键字段

column 数据库的列名

property 需要装配的属性名

one 需要使用的@One 注解(@Result(one=@One)()))

many 需要使用的@Many 注解(@Result(many=@many)()))

3. @One 注解(一对一)

代替了<assocation> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对

象。

@One 注解属性介绍:

select 指定用的 来多表查询的 sqlmapper

fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。

使用格式:

@Result(column=" ",property="",one=@One(select=""))

4. @Many 注解(一对多)

代替了<Collection> 标签, 是是多表查询的关键,在注解中用来指定子查询返回对象集合。

注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType

(一般为 ArrayList)但是注解中可以不定义;

使用格式:

@Result(property="",column="",many=@Many(select=""))

5.2 使用注解实现一对一复杂关系映射及延迟加载

需求:查询每个订单对应的用户信息

5.2.1 实体类

5.2.2 添加UserMapper的持久层接口并使用注解配置

5.2.3 添加OrderMapper持久层接口并使用注解配置

5.2.4 添加一对一测试方法

5.3 使用注解实现一对多复杂关系映射

5.3.1 实体类

5.3.2 添加OrderMapper持久层接口并使用注解配置

5.3.3 添加UserMapper持久层接口并使用注解配置

5.3.4 添加一对多测试方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值