一、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&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<!--在xml文件中用& 在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 添加一对多测试方法


589

被折叠的 条评论
为什么被折叠?



