六万字最全总结Java数据库编程MyBatis(建议收藏)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 六万字最全总结Java数据库编程MyBatis(建议收藏)

最新更新

相关代码已上传到Gitee,欢迎start!

https://gitee.com/the_efforts_paid_offf/java/tree/master/ssm_db1

前言

今天复习Java数据库编程,二话不说MyBatis手把手保姆级教程献上,再也不用担心学不会!

资料:

链接:https://pan.baidu.com/s/1FIDi_9QiTuhb4x7pksGOUQ

提取码:kevf

1. MyBatis入门

1.1 概述

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理注册驱动、创建Connection、创建Statement、手动设置参数、结果集检索及映射等繁杂的过程代码。

  • 历史进程

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对iBatis进行一些改进。

  • 多学一招

同层产品:commons-dbutils、spring-jdbc、Hibernate

1.2 下载

MyBaits的代码由github.com管理,地址:https://github.com/mybatis/mybatis-3/releases

  • 可以直接Copy老师的JAR包

1.3 与JDBC对比

  • JDBC编写DAO的步骤

  • MyBatis编写DAO的步骤

1.4 入门案例:搭建环境

1.4.1 构建项目

  • 1)创建新项目:Java --> Java EE --> Web Application

  • 2)创建项目名:mybatis-demo01

  • 3)添加jar包WEB-INF/lib目录下(目录不存在,需手动创建)

  • 4)添加jar

1.4.2 数据库和表:User

# 创建数据库
CREATE DATABASE ssm_db1;
# 使用数据库
USE ssm_db1;
# 1.1 创建用户表
CREATE TABLE `user` (
  `uid` VARCHAR(32) NOT NULL,
  `username` VARCHAR(20) DEFAULT NULL,  #用户名
  `password` VARCHAR(32) DEFAULT NULL,  #密码
  `name` VARCHAR(20) DEFAULT NULL,    #昵称
  `email` VARCHAR(30) DEFAULT NULL,   #电子邮箱
  `telephone` VARCHAR(20) DEFAULT NULL, #电话
  `birthday` DATE DEFAULT NULL,     #生日
  `sex` VARCHAR(10) DEFAULT NULL,   #性别
  `state` INT(11) DEFAULT 0,      #状态:0=未激活,1=已激活
  `code` VARCHAR(64) DEFAULT NULL,    #激活码
  PRIMARY KEY (`uid`)
) ;
# 1.2 初始化用户默认数据
INSERT INTO `user` VALUES ('u001','jack','1234','杰克','jack@czxy.com','13612345678','2015-11-04','男',0,NULL);
INSERT INTO `user` VALUES ('u002','rose','1234','肉丝','rose@czxy.com','13612345679','2015-11-05','女',0,NULL);
INSERT INTO `user` VALUES ('373eb242933b4f5ca3bd43503c34668b','ccc','ccc','aaa','bbb@store.com','15723689921','2015-11-04','男',0,'9782f3e837ff422b9aee8b6381ccf927bdd9d2ced10d48f4ba4b9f187edf7738'),('3ca76a75e4f64db2bacd0974acc7c897','bb','bb','张三','bbb@store.com','15723689921','1990-02-01','男',0,'1258e96181a9457987928954825189000bae305094a042d6bd9d2d35674684e6'),('62145f6e66ea4f5cbe7b6f6b954917d3','cc','cc','张三','bbb@store.com','15723689921','2015-11-03','男',0,'19f100aa81184c03951c4b840a725b6a98097aa1106a4a38ba1c29f1a496c231'),('c95b15a864334adab3d5bb6604c6e1fc','bbb','bbb','老王','bbb@store.com','15712344823','2000-02-01','男',0,'71a3a933353347a4bcacff699e6baa9c950a02f6b84e4f6fb8404ca06febfd6f'),('f55b7d3a352a4f0782c910b2c70f1ea4','aaa','aaa','小王','aaa@store.com','15712344823','2000-02-01','男',1,NULL);

1.5 入门案例:查询所有

1.5.1 JavaBean:User

package com.czxy.ssm.domain;
import java.util.Date;
/**
 *
 Create Table
 CREATE TABLE `user` (
 `uid` varchar(32) NOT NULL,
 `username` varchar(20) DEFAULT NULL,
 `password` varchar(20) DEFAULT NULL,
 `name` varchar(20) DEFAULT NULL,
 `email` varchar(30) DEFAULT NULL,
 `birthday` date DEFAULT NULL,
 `sex` varchar(10) DEFAULT NULL,
 `state` int(11) DEFAULT NULL,
 `code` varchar(64) DEFAULT NULL,
 PRIMARY KEY (`uid`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
 */
public class User {
  private String uid;
  private String username;
  private String password;
  private String name;
  private String email;
  private Date birthday;
  private String sex;
  private Integer state;
  private String code;
  @Override
  public String toString() {
    return "User{" +
        "uid='" + uid + '\'' +
        ", username='" + username + '\'' +
        ", password='" + password + '\'' +
        ", name='" + name + '\'' +
        ", email='" + email + '\'' +
        ", birthday=" + birthday +
        ", sex='" + sex + '\'' +
        ", state=" + state +
        ", code='" + code + '\'' +
        '}';
  }
  public String getUid() {
    return uid;
  }
  public void setUid(String uid) {
    this.uid = uid;
  }
  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 String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getEmail() {
    return email;
  }
  public void setEmail(String email) {
    this.email = email;
  }
  public Date getBirthday() {
    return birthday;
  }
  public void setBirthday(Date birthday) {
    this.birthday = birthday;
  }
  public String getSex() {
    return sex;
  }
  public void setSex(String sex) {
    this.sex = sex;
  }
  public Integer getState() {
    return state;
  }
  public void setState(Integer state) {
    this.state = state;
  }
  public String getCode() {
    return code;
  }
  public void setCode(String code) {
    this.code = code;
  }
  public User(String uid, String username, String password, String name, String email, Date birthday, String sex, Integer state, String code) {
    this.uid = uid;
    this.username = username;
    this.password = password;
    this.name = name;
    this.email = email;
    this.birthday = birthday;
    this.sex = sex;
    this.state = state;
    this.code = code;
  }
  public User() {
  }
}

1.5.2 编写Dao:UserMapper

之前的开发中我们编写的都是UserDao,在MyBatis将dao称为Mapper。

所以此后所有dao接口统一命名成Mapper。

  • 在MyBatis只需要编写接口即可,实现类由MyBatis自动生成,并在测试程序时自动执行。

package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public interface UserMapper {
    /**
     * 查询所有
     * @return
     */
    @Select("select * from user")
    public List<User> selectAll();
}

1.5.3 编写核心配置文件:SqlMapConfig.xml

  • 配置文件名称:SqlMapConfig.xml
  • 配置文件位置:src

  • 配置文件内容:
<?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>
  <!-- 环境: default的值引用什么id,就表示使用什么数据库了-->
  <environments default="db1">
    <!-- 配置数据库连接信息及事务 -->
    <environment id="db1">
      <!-- 表示使用事务:默认是自动开启事务 -->
      <transactionManager type="JDBC" />
      <!-- 使用连接池 -->
      <dataSource type="POOLED">
        <!-- 数据库连接基本信息 -->
        <property name="driver" value="com.mysql.cj.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/ssm_db1" />
        <property name="username" value="root" />
        <property name="password" value="1234" />
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <!-- 表示加载此包下的所有dao接口-->
    <package name="com.czxy.ssm.mapper"/>
  </mappers>
</configuration>

1.5.4 测试类

package com.czxy.ssm.test;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test01_SelectAll {
    public static void main(String[] args) throws IOException {
        //1 加载配置文件
        // 1.1 获得资源流
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 1.2 获得工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //2 获得会话(连接)
        SqlSession session = factory.openSession();
        //3获得功能接口
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //4 调用功能
        List<User> userList = userMapper.selectAll();
        //5 打印查询结果
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

1.6 总结

  • 到这里MyBatis的入门案例已经完成。我们总结一下:
  • 编写SqlMapConfig.xml,用于配置数据源和需要加载的Mapper
  • 编写UserMapper.java接口,用于执行方法与SQL语句的绑定
  • 基本API使用,流程是:加载资源、获得工厂、获得会话、获得Mapper。

2. 基本操作:增删改查

2.1 模糊查询

  • 功能接口中的方法
  • 如果参数简单类型,sql语句需要使用value [不推荐]
@Select("select * from user where name like #{value}")
public List<User> selectByName(String name);
  • 如果使用@Param,可以进行相应的命名 【推荐】
@Select("select * from user where name like #{name}")
public List<User> selectByName(@Param("name") String name);
  • 测试类
package com.czxy.ssm.test;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test02_Like {
    public static void main(String[] args) throws IOException {
        //1 加载配置文件
        // 1.1 获得资源流
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 1.2 获得工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //2 获得会话(连接)
        SqlSession session = factory.openSession();
        //3获得功能接口
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //4 调用功能
        List<User> userList = userMapper.selectByName("%王%");
        //5 打印查询结果
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

2.2 插入数据

  • 功能接口中的方法
/**
     * 插入数据
     * @param user
     */
    @Insert("insert into user(uid, username, password, name, email, birthday, sex, state) values(#{uid},#{username},#{password},#{name},#{email},#{birthday},#{sex},#{state})")
    public Integer insert(User user);
  • 测试类(注意:需要提交事务)
package com.czxy.ssm.test;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test03_Insert {
    public static void main(String[] args) throws IOException {
        //1 加载配置文件
        // 1.1 获得资源流
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 1.2 获得工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //2 获得会话(连接)
        SqlSession session = factory.openSession();
        //3获得功能接口
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //4 调用功能
        User user = new User();
        user.setUid("1");
        user.setUsername("jack");
        user.setPassword("1234");
        user.setName("杰克");
        user.setEmail("itcast_lt@163.com");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setSex("0");
        Integer result = userMapper.insert(user);
        System.out.println(result);
        //5 提交资源
        session.commit();
        //6 释放资源
        session.close();
    }
}

2.3 更新数据

  • 功能接口中的方法
/**
     * 插入数据
     * @param user
     */
    @Insert("update user set username=#{username}, password=#{password}, name=#{name}, email=#{email},birthday=#{birthday},sex=#{sex}, state=#{state} where uid=#{uid}")
    public Integer update(User user);
  • 测试类
package com.czxy.ssm.test;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test04_Update {
    public static void main(String[] args) throws IOException {
        //1 加载配置文件
        // 1.1 获得资源流
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 1.2 获得工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //2 获得会话(连接)
        SqlSession session = factory.openSession();
        //3获得功能接口
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //4 调用功能
        User user = new User();
        user.setUid("1");
        user.setUsername("jack1");
        user.setPassword("12341");
        user.setName("杰克");
        user.setEmail("itcast_lt@163.com");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setSex("0");
        Integer result = userMapper.update(user);
        System.out.println(result);
        //5 提交资源
        session.commit();
        //6 释放资源
        session.close();
    }
}

2.4 删除数据

  • 功能接口中的方法
/**
     * 通过id删除
     * @param uid
     */
    @Delete("delete from user where uid = #{uid}")
    public Integer deleteByPrimaryKey(@Param("uid") Integer uid);
  • 测试类
package com.czxy.ssm.test;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test05_Delete {
    public static void main(String[] args) throws IOException {
        //1 加载配置文件
        // 1.1 获得资源流
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 1.2 获得工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //2 获得会话(连接)
        SqlSession session = factory.openSession();
        //3获得功能接口
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //4 调用功能
        Integer result = userMapper.deleteByPrimaryKey(1);
        System.out.println(result);
        //5 提交资源
        session.commit();
        //6 释放资源
        session.close();
    }
}

3.日志与工具类

3.1 日志

3.1.1 什么是日志

  • 记录程序运行的过程细节。例如:我们在控制台可以看到SQL语句

3.1.2 整合日志

  • 1)添加jar包 (已添加)

  • 2)添加配置文件

# 2. 输出格式
## log4j.appender.stdout=输出位置(固定值,由log4j提供)
## log4j.appender.stdout.Target=方式
## log4j.appender.stdout.layout=布局(固定值)
## log4j.appender.stdout.layout.ConversionPattern=格式
# 2.1 将日志输出到控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c:%L - %m%n
# 2.2 将日志输出到文件
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=d:/file.log
log4j.appender.file.Append=false
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c:%L - %m%n
#1.log4j.rootLogger=日志级别, 输出方式1, 输出方式2, ...
## 日志级别:debug、info、warn、error
log4j.rootLogger=debug, stdout, file
# 3 自定义日志级别
## log4j.logger.包=日志级别
#log4j.logger.com.ibatis = debug    
#log4j.logger.com.ibatis.common.jdbc.SimpleDataSource = debug    
#log4j.logger.com.ibatis.common.jdbc.ScriptRunner = debug    
#log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate = debug    
#log4j.logger.java.sql.Connection = debug    
#log4j.logger.java.sql.Statement = debug    
#log4j.logger.java.sql.PreparedStatement = debug    
#log4j.logger.java.sql.ResultSet =debug
log4j.logger.org.apache.ibatis.transaction = info
log4j.logger.org.apache.ibatis.io = info
log4j.logger.org.apache.ibatis.datasource = info
log4j.logger.org.apache.ibatis.logging = info

3.2 工具类

3.2.1 拷贝工具类

  • 完成增删改查的时候,我们发现有一些代码大量重复,我们将提供工具类,对重复代码进行简化。

package com.czxy.ssm.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
/**
 * @author  manor的大数据之路
 *  
 */
public class MyBatisUtils {
    // 会话工厂
    private static SqlSessionFactory factory;
    static{
        try {
            // 1.1 加载核心配置文件
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            // 1.2 获得工厂
            factory = new SqlSessionFactoryBuilder().build(is);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    private static ThreadLocal<SqlSession> local = new ThreadLocal<>();
    /**
     * 获得新会话
     * @return
     */
    private static SqlSession openSession(){
        SqlSession sqlSession = local.get();
        if(sqlSession == null){
            sqlSession = factory.openSession();
            local.set(sqlSession);
        }
        return sqlSession;
    }
    /**
     * 获得mapper
     * @param clazz
     * @return
     */
    public static <T> T getMapper(Class<T> clazz){
        return openSession().getMapper(clazz);
    }
    /**
     * 释放资源
     */
    public static void close() {
        SqlSession sqlSession = openSession();
        if(sqlSession != null){
            sqlSession.close();
        }
    }
    /**
     * 提交并释放资源
     */
    public static void commitAndclose() {
        SqlSession sqlSession = openSession();
        if(sqlSession != null){
            sqlSession.commit();
            close();
        }
    }
    /**
     * 回滚并释放资源
     */
    public static void rollbackAndclose() {
        SqlSession sqlSession = openSession();
        if(sqlSession != null){
            sqlSession.rollback();
            close();
        }
    }
}

3.2.2 工具类原理分析

  • 工具类实现原理分析

3.2.3 测试类

package com.czxy.ssm.test;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.UserMapper;
import com.czxy.ssm.utils.MyBatisUtils;
import java.util.Date;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test06_Utils {
    public static void main(String[] args) {
        UserMapper userMapper = MyBatisUtils.getMapper(UserMapper.class);
        User user = new User();
        user.setUid("1");
        user.setUsername("jack");
        user.setPassword("1234");
        user.setName("杰克");
        user.setEmail("itcast_lt@163.com");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setSex("0");
        Integer result = userMapper.insert(user);
        System.out.println(result);
        MyBatisUtils.commitAndclose();
    }
}

4.API详解

4.1 核心配置文件详解

在实际开发中,开发者会事先准备好配置文件模板,然后把模板Copy到项目中,再去修改重要的配置参数即可。这样开发者就无需把配置文件的结构背下来。但是开发者还是需要能够读懂配置文件的。下面我们来学习MyBatis核心配置文件。

4.1.1 根标签:

  • 配置子标签时,多个标签之间有先后顺序,使用时一定要注意。
  • 如下就是常用4个标签的使用顺序:
<?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>
  <properties></properties>
  <typeAliases></typeAliases>
  <environments></environments>
  <mappers></mappers>
</configuration>
  • 常见子标签介绍
标签名称 描述
properties 属性配置,也可引入外部properties文件
settings 系统参数配置,所有参数都有默认值,通常不用配置
typeAliases 类型别名,简化开发,仅减少类完全限定名的冗余。用于xml开发。
plugins 插件,用于添加扩展功能。
environments 环境配置,提供给factory配置信息
mappers 映射器,确定SQL语句的位置

4.1.2 属性:

将易于修改的配置内容抽取到properties中,方便统一管理。mybatis提供两种方式来维护properties:property标签和properties配置文件。

方式1:property标签
  • 1)配置:将需要的内容配置在
<properties>
  <property name="jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
  <property name="jdbc.url" value="jdbc:mysql://localhost:3306/ssm_db1"/>
  <property name="jdbc.username" value="root"/>
  <property name="jdbc.password" value="1234"/>
</properties>
  • 2)使用:在配置文件的其他位置,通过 ${标识} 方式获得内容
<!-- 使用连接池 -->
<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>
  • 整体示意图

方式2:properties配置文件

在实际开发中,我们常见数据库的配置信息存放到properties文件,mybatis也提供了对配置文件的支持。

  • 1)添加 db.properties配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_db1
jdbc.username=root
jdbc.password=1234
  • 2)加载properties文件,修改核心配置文件
<properties resource="db.properties" />
  • 整体示意图

注意事项
  • properties配置文件加载的内容,将覆盖标签配置的内容。
  • 先加载标签配置的内容
  • 再加载 resource指定的properties配置文件配置的内容,也就是后者覆盖了前者。
<!--最后url的值为 db.properties配置的内容 -->
<properties resource="db.properties" >
  <property name="jdbc.url" value="jdbc:mysql://localhost:3306/ssm_db2"/>
</properties>
<!-- 【开发中不建议混搭使用】 -->

4.1.3 设置:

  • mybatis框架系统配置settings,用于改变 MyBatis 的运行时行为。
  • mybatis提供可多种设置,用于系统的优化。
设置参数 描述 有效值 默认值
mapUnderscoreToCamelCase 是否开启自动驼峰命名规则映射, 即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 true | false false
autoMappingBehavior 指定 MyBatis 是否以及如何自动映射指定的列到字段或属性。 NONE 表示取消自动映射; PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集 NONE, PARTIAL, FULL PARTIAL
useGeneratedKeys 允许 JDBC 支持自动生成主键,需要驱动兼容。 true | false false
useColumnLabel 使用列标签代替列名。 true | false true
cacheEnabled 该配置影响的所有映射器中配置的缓存的全局开关。 true | false true
lazyLoadingEnabled 延迟加载的全局开关。 true | false false
  • 驼峰命名设置
<settings>
    <!-- java对象属性驼峰,对应数据的下划线 -->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
  </settings>

4.1.4 环境:

  • MyBatis通过环境environments来配置数据库的连接和事务管理。
  • 确定使用哪个配置
<!--
  default用于确定当前环境使用哪个配置
  <environment id=””>用于提供一套配置方案,id的值提供给default使用。
-->
<environments default="配置2">
  <environment id="配置1">
  </environment>
  <environment id="配置2">
  </environment>
</environments>
  • 配置内容
<!--
  <transactionManager> 用于配置事务管理方案
    type:用于确定管理事务具体方案,取值:JDBC、MANAGED
      JDBC,jdbc底层事务管理,commit提交,rollback回顾。
      MANAGED,交予其他框架管理,自己不做事务操作,仅关闭连接。
  <dataSource>用于配置连接池(多个连接的池子)
    type:用于确定管理连接的方案,取值:POOLED、UNPOOLED、JNDI
      POOLED:通过连接池,管理连接创建和销毁。
      UNPOOLED:不使用连接池,每一次都创建和销毁连接。
      JNDI:将连接池存放到JNDI中。
-->
<environment id="development">
  <!-- 使用jdbc管理事务 -->
  <transactionManager type="JDBC"></transactionManager>
  <!-- 配置数据源(配置连接) -->
  <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>
  • 扩展(查看源码,可以确定 type 配置内容)
  1. 事务的配置项

  2. 连接池的配置项

  3. MANAGED 不管事务,只关闭连接

4.1.5 映射器:

  • 加载指定包package所有的接口。
<!-- 映射文件 -->
<mappers>
  <package name="com.czxy.ssm.mapper"/>
</mappers>

4.2 输入:vo 条件查询

在开发中,一个对象的查询条件,比对象中封装的属性更多。例如:user有birthday,我们需要查询2010-2020年的数据,时间段beginTime、endTime在User对象中就没有提供属性,实际开发中,一般提供一个自定义对象,例如:UserVo。

  • 1)编写vo
package com.czxy.ssm.vo;
/**
 * @author  manor的大数据之路
 *  
 */
public class UserVo {
    private String beginTime;       // 开始时间
    private String endTime;         // 结束时间
    public UserVo() {
    }
    public UserVo(String beginTime, String endTime) {
        this.beginTime = beginTime;
        this.endTime = endTime;
    }
    public String getBeginTime() {
        return beginTime;
    }
    public void setBeginTime(String beginTime) {
        this.beginTime = beginTime;
    }
    public String getEndTime() {
        return endTime;
    }
    public void setEndTime(String endTime) {
        this.endTime = endTime;
    }
}
  • 2)修改Mapper,添加 condition 方法
/**
     * 条件查询
     * @param userVo
     * @return
     */
    @Select("select * from user where birthday >= #{beginTime} and birthday <= #{endTime}")
    public List<User> condition(UserVo userVo);
  • 3)测试类
package com.czxy.ssm.test;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.UserMapper;
import com.czxy.ssm.utils.MyBatisUtils;
import com.czxy.ssm.vo.UserVo;
import java.util.Date;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test07_Condition {
    public static void main(String[] args) {
        UserMapper userMapper = MyBatisUtils.getMapper(UserMapper.class);
        List<User> list = userMapper.condition(new UserVo("2010-01-01", "2021-01-01"));
        // 打印
        list.forEach(user -> {
            System.out.println(user);
        });
        MyBatisUtils.commitAndclose();
    }
}

4.3 输出:结果集映射Result

实际开发中,如果数据库字段和Java对象字段不能对应,就需要我们编写对应关系。

注解 描述
@Results 对象和表的映射关系。
@Result 一个对象属性和一个表的字段的映射关系。
@ResultMap 映射关系,使用@Results声明的映射关系。

4.3.1 基本使用

  • 语法
/** 
  @Results(value = 一组Result )
*/    
@Results(value = {
     @Result(property = "属性名", column = "字段名", id = true),
     @Result(property = "属性名2", column = "字段名2"),
     @Result(property = "属性名3", column = "字段名3")
})
  • 基本使用
/**
     * 查询所有
     * @return
     */
    @Select("select * from user")
    @Results({
            @Result(property = "uid", column = "uid", id = true),
            @Result(property = "username", column = "username"),
            @Result(property = "password", column = "password")
    })
    public List<User> selectAll();

4.3.2 重复使用

  • 语法
@Select(...)
@Results(id = "标识", value = {...})
public 返回值 方法名();
@Select(...)
@ResultMap("标识")
public 返回值 方法名2();
  • 使用
/**
     * 查询所有
     * @return
     */
    @Select("select * from user")
    @Results(id = "userResult", value = {
            @Result(property = "uid", column = "uid", id = true),
            @Result(property = "username", column = "username"),
            @Result(property = "password", column = "password")
    })
    public List<User> selectAll();
    /**
     * 通过id查询详情
     * @param uid
     * @return
     */
    @Select("select * from user where uid = #{uid}")
    @ResultMap("userResult")
    public User selectById(@Param("uid") String uid);

4.4 已有注解总结

注解名称 描述
@Insert 添加sql
@Update 更新sql
@Delete 删除sql
@Select 查询sql
@Param 形参命名
@Results 对象和表的映射关系。
@Result 一个对象属性和一个表的字段的映射关系。

5. 关联查询:一对多

5.1 用户和订单数据模型

5.1.1 表关系

CREATE TABLE `orders` (
  `oid` VARCHAR(32) PRIMARY KEY NOT NULL,
  `ordertime` DATETIME DEFAULT NULL,    #下单时间
  `total_price` DOUBLE DEFAULT NULL,    #总价
  `state` INT(11) DEFAULT NULL,     #订单状态:1=未付款;2=已付款,未发货;3=已发货,没收货;4=收货,订单结束
  `address` VARCHAR(30) DEFAULT NULL,   #收获地址
  `name` VARCHAR(20) DEFAULT NULL,    #收获人
  `telephone` VARCHAR(20) DEFAULT NULL,   #收货人电话
  `uid` VARCHAR(32) DEFAULT NULL,
  CONSTRAINT `order_fk_0001` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`)
) ;
INSERT INTO `orders` VALUES ('x001','2010-10-10',10,1,'江苏','张三','12345','u001');
INSERT INTO `orders` VALUES ('x002','2010-11-11',20,2,'河北','李四','67890','u001');
INSERT INTO `orders` VALUES ('x003','2011-10-10',30,3,'山西','王五','66666','u002')

5.1.2 JavaBean

  • 默认情况下,两个JavaBean没有关系

package com.czxy.ssm.domain;
import java.util.Date;
/**
 *
 Create Table
 CREATE TABLE `orders` (
 `oid` varchar(32) NOT NULL,
 `ordertime` datetime DEFAULT NULL,
 `total` double DEFAULT NULL,
 `state` int(11) DEFAULT NULL,
 `address` varchar(30) DEFAULT NULL,
 `name` varchar(20) DEFAULT NULL,
 `telephone` varchar(20) DEFAULT NULL,
 `uid` varchar(32) DEFAULT NULL,
 PRIMARY KEY (`oid`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
 */
public class Order {
  private String oid;     // 订单编号
  private Date ordertime;   // 下单时间
  private Double total;     // 订单总金额
  private Integer state;    // 订单状态 0 未支付 1 已支付 2已发货 3已收货
  private String address;   // 收货人地址
  private String name;    // 收货人姓名
  private String telephone; // 收货人电话
  private String uid;
  @Override
  public String toString() {
    return "Order{" +
        "oid='" + oid + '\'' +
        ", ordertime=" + ordertime +
        ", total=" + total +
        ", state=" + state +
        ", address='" + address + '\'' +
        ", name='" + name + '\'' +
        ", telephone='" + telephone + '\'' +
        ", uid='" + uid + '\'' +
        '}';
  }
  public String getOid() {
    return oid;
  }
  public void setOid(String oid) {
    this.oid = oid;
  }
  public Date getOrdertime() {
    return ordertime;
  }
  public void setOrdertime(Date ordertime) {
    this.ordertime = ordertime;
  }
  public Double getTotal() {
    return total;
  }
  public void setTotal(Double total) {
    this.total = total;
  }
  public Integer getState() {
    return state;
  }
  public void setState(Integer state) {
    this.state = state;
  }
  public String getAddress() {
    return address;
  }
  public void setAddress(String address) {
    this.address = address;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getTelephone() {
    return telephone;
  }
  public void setTelephone(String telephone) {
    this.telephone = telephone;
  }
  public String getUid() {
    return uid;
  }
  public void setUid(String uid) {
    this.uid = uid;
  }
  public Order(String oid, Date ordertime, Double total, Integer state, String address, String name, String telephone, String uid) {
    this.oid = oid;
    this.ordertime = ordertime;
    this.total = total;
    this.state = state;
    this.address = address;
    this.name = name;
    this.telephone = telephone;
    this.uid = uid;
  }
  public Order() {
  }
}

5.1.3 JavaBean关系

  • 以对象的方法,描述两个JavaBean之间的关系

  • JavaBean:User
public class User {
  private String uid;
  private String username;
  private String password;
  private String name;
  private String email;
  private Date birthday;
  private String sex;
  private Integer state;
  private String code;
  // 一对多:一个用户 拥有【多个用户】
  private List<Order> orderList = new ArrayList<>();
    // ...
}
  • JavaBean:Order
public class Order {
  private String oid;     // 订单编号
  private Date ordertime;   // 下单时间
  private Double total;     // 订单总金额
  private Integer state;    // 订单状态 0 未支付 1 已支付 2已发货 3已收货
  private String address;   // 收货人地址
  private String name;    // 收货人姓名
  private String telephone; // 收货人电话
  private String uid;
  // 多对一, 多个订单 属于 【一个用户】
  private User user;
    // ...
}

5.2 一对多

5.2.1 语法

在Mybatis注解开发中,需要通过@Result进行关联关系的描述。

  • 一对多:需要使用many属性和@Many注解。
@Result(
    property = "1表JavaBean属性名", 
    column = "1表字段名",
    many = @Many(select = "多表Mapper的方法签名")
)

5.2.2 需求&分析

  • 需求:查询用户的同时,查询每个用户对应的订单
  • 分析:
  • 修改OrderMapper,完成通过uid查询所有的订单
  • 修改UserMapper,完成查询用户信息时,查询对应的订单

5.2.3 订单功能:通过uid查询所有的订单

package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.Order;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
 * @author  manor的大数据之路
 *  
 */
public interface OrderMapper {
    /**
     * 通过id查询详情
     * @param uid
     * @return
     */
    @Select("select * from orders where uid = #{uid}")
    public Order findOrdersByUserId(@Param("uid") String uid) ;
}

5.2.4 用户功能:关联查询

public interface UserMapper {
    /**
     * 查询所有
     * @return
     */
    @Select("select * from user")
    @Results(id = "userResult", value = {
            @Result(property = "uid", column = "uid", id = true),
            @Result(property = "username", column = "username"),
            @Result(property = "password", column = "password"),
            @Result(property="orderList" , many=@Many(select="com.czxy.ssm.mapper.OrderMapper.findOrdersByUserId"), column="uid")
    })
    public List<User> selectAll();
}

5.3 多对一

5.3.1 语法

在Mybatis注解开发中,需要通过@Result进行关联关系的描述。

  • 多对一:需要使用one属性和@One注解
@Result(
    property = "多表JavaBean属性名", 
    column = "多表字段名",
    one = @One(select ="1表Mapper的方法签名")
)

5.3.2 需求&分析

  • 需求:查询订单时,查询关联的用户信息
  • 分析:
    1)通过user_id查询用户详情
    2)通过id查询订单详情

5.4.3 用户功能:通过id查询用户详情(已有)

/**
     * 通过id查询详情
     * @param uid
     * @return
     */
    @Select("select * from user where uid = #{uid}")
    @ResultMap("userResult")
    public User selectById(@Param("uid") String uid);

5.4.4 订单功能:通过id查询订单详情

/**
     *
     * @param id
     * @return
     */
    @Select("select * from orders where oid = #{oid}")
    @Results({
            @Result(property="oid" , column="oid"),
            @Result(property="ordertime" , column="ordertime"),
            @Result(property="total" , column="total"),
            @Result(property="state" , column="state"),
            @Result(property="address" , column="address"),
            @Result(property="name" , column="name"),
            @Result(property="telephone" , column="telephone"),
            @Result(property="uid" , column="uid"),
            @Result(property="user" , one=@One(select="com.czxy.ssm.mapper.UserMapper.selectById") , column="uid"),
    })
    public Order selectById(@Param("oid") String id);

6.关联查询:多对多

6.1 学生和老师数据模型

6.1.1 表间关系

#老师表
CREATE TABLE teacher(
 tid INT PRIMARY KEY,
 NAME VARCHAR(50)
); 
#学生表
CREATE TABLE student(
 sid INT PRIMARY KEY,
 NAME VARCHAR(50)
);
#中间表
CREATE TABLE teacher_student(
 teacher_id INT ,
 student_id INT,
 CONSTRAINT ts_t_fk FOREIGN KEY (teacher_id) REFERENCES teacher(tid),
 CONSTRAINT ts_s_fk FOREIGN KEY (student_id) REFERENCES student(sid)
);
INSERT INTO teacher VALUES (1,'肖老师'); 
INSERT INTO teacher VALUES (2,'马老师'); 
INSERT INTO student VALUES (1,'张三');
INSERT INTO student VALUES (2,'李四');
INSERT INTO student VALUES (3,'王五');
INSERT INTO teacher_student VALUES (1,1);
INSERT INTO teacher_student VALUES (1,2);
INSERT INTO teacher_student VALUES (1,3);
INSERT INTO teacher_student VALUES (2,1);
INSERT INTO teacher_student VALUES (2,2);

6.1.2 JavaBean及其关系

  • JavaBean:Student
package com.czxy.ssm.domain;
import java.util.ArrayList;
import java.util.List;
/**
 * #学生表
 * CREATE TABLE student(
 *  sid INT PRIMARY KEY,
 *  NAME VARCHAR(50)
 * );
 * @author  manor的大数据之路
 *  
 */
public class Student {
    private Integer sid;
    private String name;
    private List<Teacher> teacherList = new ArrayList<>();
    public Integer getSid() {
        return sid;
    }
    public void setSid(Integer sid) {
        this.sid = sid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Teacher> getTeacherList() {
        return teacherList;
    }
    public void setTeacherList(List<Teacher> teacherList) {
        this.teacherList = teacherList;
    }
    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", name='" + name + '\'' +
                ", teacherList=" + teacherList +
                '}';
    }
}
  • JavaBean:Teacher
package com.czxy.ssm.domain;
import java.util.ArrayList;
import java.util.List;
/**
 * #老师表
 * CREATE TABLE teacher(
 *  tid INT PRIMARY KEY,
 *  NAME VARCHAR(50)
 * );
 * @author  manor的大数据之路
 *  
 */
public class Teacher {
    private Integer tid;
    private String name;
    private List<Student> studentList = new ArrayList<>();
    public Integer getTid() {
        return tid;
    }
    public void setTid(Integer tid) {
        this.tid = tid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Student> getStudentList() {
        return studentList;
    }
    public void setStudentList(List<Student> studentList) {
        this.studentList = studentList;
    }
    @Override
    public String toString() {
        return "Teacher{" +
                "tid=" + tid +
                ", name='" + name + '\'' +
                ", studentList=" + studentList +
                '}';
    }
}

6.2 多对多:老师–>学生

  • 需要根据老师tid查询中间表中,对应的所有学生id

6.2.1 student 映射

package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.Student;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
 * @author  manor的大数据之路
 *  
 */
public interface StudentMapper {
    /**
     * 通过tid查询对应的学生
     * @param tid
     * @return
     * @throws Exception
     */
    @Select("select * from student s where s.sid in (select student_id from teacher_student where teacher_id = #{tid} )")
    public Student findStudentByTeacherId(@Param("tid") Integer tid) throws Exception;
}

6.2.2 teacher 映射

package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.Teacher;
import org.apache.ibatis.annotations.*;
/**
 * @author  manor的大数据之路
 *  
 */
public interface TeacherMapper {
    @Select("select * from teacher t where  t.tid = #{tid}")
    @Results({
            @Result(property="tid" , column="tid"),
            @Result(property="name" , column="name"),
            @Result(property="studentList" , many=@Many(select="com.czxy.ssm.mapper.StudentMapper.findStudentByTeacherId") , column="tid"),
    })
    public Teacher selectById(@Param("tid") Integer tid);
}

6.2.3 测试

package com.czxy.ssm.test;
import com.czxy.ssm.domain.Order;
import com.czxy.ssm.domain.Teacher;
import com.czxy.ssm.mapper.OrderMapper;
import com.czxy.ssm.mapper.TeacherMapper;
import com.czxy.ssm.utils.MyBatisUtils;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test09_SelectTeacher {
    public static void main(String[] args) {
        TeacherMapper teacherMapper = MyBatisUtils.getMapper(TeacherMapper.class);
        Teacher teacher = teacherMapper.selectById(1);
        // 打印
        System.out.println(teacher);
        MyBatisUtils.commitAndclose();
    }
}

6.2.4 巩固练习

  • 查询所有的老师,并查询老师对应的学生。
package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.Teacher;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public interface TeacherMapper {
    /**
     * 通过id查询详情
     * @param tid
     * @return
     */
    @Select("select * from teacher t where  t.tid = #{tid}")
    @Results(id = "teacherResult" , value = {
            @Result(property="tid" , column="tid"),
            @Result(property="name" , column="name"),
            @Result(property="studentList" , many=@Many(select="com.czxy.ssm.mapper.StudentMapper.findStudentByTeacherId") , column="tid"),
    })
    public Teacher selectById(@Param("tid") Integer tid);
    /**
     * 查询所有
     * @return
     */
    @Select("select * from teacher")
    @ResultMap("teacherResult")
    public List<Teacher> selectList();
}
  • 测试类
package com.czxy.ssm.test;
import com.czxy.ssm.domain.Teacher;
import com.czxy.ssm.mapper.TeacherMapper;
import com.czxy.ssm.utils.MyBatisUtils;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test10_SelectAllTeacher {
    public static void main(String[] args) {
        TeacherMapper teacherMapper = MyBatisUtils.getMapper(TeacherMapper.class);
        List<Teacher> teacherList = teacherMapper.selectList();
        // 打印
        teacherList.forEach(teacher -> {
            System.out.println(teacher);
        });
        MyBatisUtils.commitAndclose();
    }
}

7.分页查询

MyBatis没有提供分页支持,需要自己编写limit语句。

开发中我们采用PageHelper插件。

7.1 搭建环境

7.1.1 导入jar包

7.1.2 添加插件

<!-- 插件 -->
  <plugins>
    <plugin interceptor="com.github.pagehelper.PageHelper">
      <!-- 方言 -->
      <property name="dialect" value="mysql"/>
      <!-- 设置为true时,使用RowBounds分页会进行count查询 -->
      <property name="rowBoundsWithCount" value="true"/>
    </plugin>
  </plugins>

7.2 语法

1) 设置分页数据
PageHelper.startPage(int pageNum, int pageSize)
  参数1:pageNum 第几页
  参数2:pageSize 页面显示个数
2) 封装分页结果 PageInfo
  new PageInfo(查询结果)    //创建分页对象
  pageInfo.getTotal(),  //自动查询总条数
  pageInfo.getPages(),  //总分页数

7.3 使用

package com.czxy.ssm.test;
import com.czxy.ssm.domain.Teacher;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.TeacherMapper;
import com.czxy.ssm.mapper.UserMapper;
import com.czxy.ssm.utils.MyBatisUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test11_Page {
    public static void main(String[] args) {
        UserMapper userMapper = MyBatisUtils.getMapper(UserMapper.class);
        // 设置分页 **
        PageHelper.startPage(1,2);
        // 查询
        List<User> users = userMapper.selectAll();
        // 获得封装对象 ** 
        PageInfo<User> pageInfo = new PageInfo<>(users);
        // 打印分页信息
        long total = pageInfo.getTotal();
        List<User> list = pageInfo.getList();
        System.out.println("总条数:" + total);
        System.out.println("分页数据:");
        list.forEach(user -> {
            System.out.println(user);
        });
        MyBatisUtils.commitAndclose();
    }
}

8. 通用Mapper

8.1 概述

  • 通用Mapper对MyBatis进行简化的第三方工具包。
  • 通用Mapper提供了一个名为Mapper的接口,用于自动完成单表的增删改查操作。
public interface UserMapper extends Mapper<User> {
}
  • 如果通用Mapper中的方法不足以满足你的需求,直接添加自定义方法即可。

8.2 搭建环境

8.2.1 导入jar

8.2.2 修改工具类

  • 添加内容从官方文档中拷贝
package com.czxy.ssm.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
import tk.mybatis.mapper.entity.Config;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import java.io.InputStream;
/**
 * @author  manor的大数据之路
 *  
 */
public class MyBatisUtils {
    // 会话工厂
    private static SqlSessionFactory factory;
    static{
        try {
            // 1.1 加载核心配置文件
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            // 1.2 获得工厂
            factory = new SqlSessionFactoryBuilder().build(is);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    private static ThreadLocal<SqlSession> local = new ThreadLocal<>();
    /**
     * 获得新会话
     * @return
     */
    private static SqlSession openSession(){
        SqlSession sqlSession = local.get();
        if(sqlSession == null){
            sqlSession = factory.openSession();
            //创建一个MapperHelper
            MapperHelper mapperHelper = new MapperHelper();
            //特殊配置
            Config config = new Config();
            // 设置UUID生成策略
            // 配置UUID生成策略需要使用OGNL表达式
            // 默认值32位长度:@java.util.UUID@randomUUID().toString().replace("-", "")
            //config.setUUID("");
            // 主键自增回写方法,默认值MYSQL,详细说明请看文档
//          config.setIDENTITY("HSQLDB");
            // 支持方法上的注解
            // 3.3.1版本增加
            config.setEnableMethodAnnotation(true);
            config.setNotEmpty(true);
            // 序列的获取规则,使用{num}格式化参数,默认值为{0}.nextval,针对Oracle
            // 可选参数一共3个,对应0,1,2,分别为SequenceName,ColumnName, PropertyName
            //config.setSeqFormat("NEXT VALUE FOR {0}");
            // 设置全局的catalog,默认为空,如果设置了值,操作表时的sql会是catalog.tablename
            //config.setCatalog("");
            // 设置全局的schema,默认为空,如果设置了值,操作表时的sql会是schema.tablename
            // 如果同时设置了catalog,优先使用catalog.tablename
            //config.setSchema("");
            // 主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER)
            //config.setOrder("AFTER");
            //设置配置
            mapperHelper.setConfig(config);
            // 注册通用tk.mybatis.mapper.common.Mapper接口 - 可以自动注册继承的接口
            mapperHelper.registerMapper(Mapper.class);
            mapperHelper.registerMapper(MySqlMapper.class);
//          mapperHelper.registerMapper(SqlServerMapper.class);
//          mapperHelper.registerMapper(IdsMapper.class);
            //配置完成后,执行下面的操作
            mapperHelper.processConfiguration(sqlSession.getConfiguration());
            local.set(sqlSession);
        }
        return sqlSession;
    }
    /**
     * 获得mapper
     * @param clazz
     * @return
     */
    public static <T> T getMapper(Class<T> clazz){
        return openSession().getMapper(clazz);
    }
    /**
     * 释放资源
     */
    public static void close() {
        SqlSession sqlSession = openSession();
        if(sqlSession != null){
            sqlSession.close();
        }
    }
    /**
     * 提交并释放资源
     */
    public static void commitAndclose() {
        SqlSession sqlSession = openSession();
        if(sqlSession != null){
            sqlSession.commit();
            close();
        }
    }
    /**
     * 回滚并释放资源
     */
    public static void rollbackAndclose() {
        SqlSession sqlSession = openSession();
        if(sqlSession != null){
            sqlSession.rollback();
            close();
        }
    }
}

8.3 编写Mapper

  • 编写接口,继承tk.mybatis.mapper.common.Mapper接口即可
  • 注意:Mapper接口以tk开头
package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.User;
import tk.mybatis.mapper.common.Mapper;
/**
 * @author  manor的大数据之路
 *  
 */
public interface UserMapper2 extends Mapper<User> {
}

8.4 通用API

  • 查询方法
方法名 描述
T selectOne(T t) 根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号
List select(T t) 根据实体中的属性值进行查询,查询条件使用等号
List selectAll() 查询全部结果
int selectCount(T t) 根据实体中的属性查询总数,查询条件,使用等号
T selectByPrimaryKey(Object key) 根据主键字段进行查询
boolean existsWhithPrimaryKey(Object key) 根据主键字段查询记录是否存在
List selectByExample(Object example) 根据Example条件进行查询
T selectOneByExample(Object example) 根据Example条件进行查询,只能有一个返回值
int selectCountByExample(Object example) 根据Example条件进行查询记录数

  • 插入方法
方法名 描述
int insert(T t) 保存一个实体,null的属性也会保存,不会使用数据库默认值
int intsertSelective(T t) 保存一个实体,null的属性不会保存,使用数据库默认值

  • 更新方法
方法名 描述
int updateByPrimaryKey(T t) 根据主键更新实体全部字段,null值会被更新
int updateByPrimaryKeySelective(T t) 根据主键更新实体中不为null值的字段

  • 删除方法
方法名 描述
int delete(T t) 根据实体属性作为条件进行删除,查询条件使用等号
int deletePrimaryKey(Object key) 根据主键字段进行删除
int deleteByExample(Object example) 根据Example条件删除数据

8.4.1 通过主键查询

  • 1)确定主键,否则所有字段都是主键

  • 2)测试
package com.czxy.ssm.test;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.UserMapper;
import com.czxy.ssm.mapper.UserMapper2;
import com.czxy.ssm.utils.MyBatisUtils;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public class Test13_Mapper {
    @Test
    public void testSelectByPrimaryKey() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);
        User user = userMapper2.selectByPrimaryKey("1");
        System.out.println(user);
        MyBatisUtils.commitAndclose();
    }
}

8.4.2 查询所有

@Test
    public void testSelectAll() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);
        List<User> list = userMapper2.selectAll();
        // 打印
        list.forEach(System.out::println);
        MyBatisUtils.commitAndclose();
    }

8.4.3 添加

@Test
    public void testInsert() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);
        User user = new User();
        user.setUid("2");
        user.setUsername("jack");
        user.setPassword("1234");
        user.setName("杰克");
        user.setEmail("itcast_lt@163.com");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setSex("0");
        int result = userMapper2.insert(user);
        // 打印
        System.out.println(result);
        MyBatisUtils.commitAndclose();
    }

8.4.4 修改

@Test
    public void testUpdate() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);
        User user = new User();
        user.setUid("2");
        user.setUsername("jack");
        user.setPassword("1234");
        user.setName("杰克");
        user.setEmail("itcast_lt@163.com");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setSex("0");
        int result = userMapper2.updateByPrimaryKey(user);
        // 打印
        System.out.println(result);
        MyBatisUtils.commitAndclose();
    }

8.4.5 删除

@Test
    public void testDelete() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);
        int result = userMapper2.deleteByPrimaryKey("2");
        // 打印
        System.out.println(result);
        MyBatisUtils.commitAndclose();
    }

8.4.6 多条件查询

  • 语法:
// 获得多条件对象
Example example = new Example(对象.class);
Example.Criteria criteria = example.createCriteria();
// 常见条件方法
andLike()         //模糊查询
andEqualTo()        //等值查询
andLessThanOrEqualTo()    //<=查询
andGreaterThanOrEqualTo() //>=查询
andBetween()        //区间查询
@Test
    public void testCondition() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andLike("name", "%王%");
        criteria.andEqualTo("sex", "男");
        List<User> list = userMapper2.selectByExample(example);
        for (User user : list) {
            System.out.println(user);
        }
        MyBatisUtils.commitAndclose();
    }

9. 基于XML

9.1 搭建环境

9.1.1 创建项目

  • 1)选择Web 应用

  • 2)创建项目mybatis-demo02

9.1.2 添加jar包

9.1.3 拷贝配置类

9.1.4 拷贝工具类

9.1.5 拷贝JavaBean

9.2 入门案例:查询所有

9.2.1 编写流程

  • 步骤1:编写Dao接口,用于确定方法名称
  • 步骤2:编写Mapper.xml文件,用于编写SQL语句
  • 步骤3:编写SqlMapConfig.xml 核心配置文件,并添加mapper xml文件
  • 步骤4:测试

9.2.2 编写Mapper接口

package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.User;
/**
 * @author  manor的大数据之路
 *  
 */
public interface UserMapper {
    /**
     * 通过id查询详情
     * @param uid
     * @return
     */
    public User selectById(String uid);
}

9.2.3 编写Mapper 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="com.czxy.ssm.mapper.UserMapper">
    <select id="selectById" parameterType="string" resultType="com.czxy.ssm.domain.User">
    select * from user where uid = #{id}
  </select>
</mapper>

9.2.4 修改核心配置文件

  • 核心配置文件  用于确定mapper配置文件的位置

<mappers>
    <!-- 表示加载此包下的所有dao接口-->
    <mapper resource="mapper/UserMapper.xml"/>
  </mappers>

9.2.5 测试类

package com.czxy.ssm.test;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.UserMapper;
import com.czxy.ssm.utils.MyBatisUtils;
import org.junit.Test;
/**
 * @author  manor的大数据之路
 *  
 */
public class TestUserMapper {
    @Test
    public void testSelectById() {
        UserMapper userMapper = MyBatisUtils.getMapper(UserMapper.class);
        User user = userMapper.selectById("1");
        System.out.println(user);
        MyBatisUtils.commitAndclose();
    }
}

9.3 配置文件详解

9.3.1 Mapper基本结构

<?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="Mapper类">
  <!-- 查询 -->
    <select id="方法名">SQL语句</select>
  <!-- 添加 -->
  <insert id="方法名">SQL语句</insert>
    <!-- 更新 -->
  <update id="方法名">SQL语句</update>
    <!-- 删除 -->
  <delete id="方法名">SQL语句</delete>
</mapper>

9.3.2 Mapper 参数类型:parameterType

  • 在映射文件mapper中,我们使用parameterType设置请求参数的类型
<?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="mapper类">
    <select id="方法名" parameterType="参数类型">SQL语句</select>
</mapper>
  • 简单类型:
<!-- 通过id查询 -->
<select id="findUserById" parameterType="int" resultType="com.czxy.domain.User">
  select * from user where uid = #{id}
</select>
  • POJO类型:
<!-- 添加用户 -->
<insert id="insertUser" parameterType="com.czxy.domain.User">
  insert into user(uid, username, password, name, email, birthday, sex, state) values(#{uid},#{username},#{password},#{name},#{email},#{birthday},#{sex},#{state})
</insert>

9.3.3 Mapper 结果类型:resultType

  • 在映射文件mapper中,我们使用resultType设置查询结果类型
<?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="mapper类">
    <select id="方法名" resultType="结果类型">SQL语句</select>
</mapper>
  • 简单类型
<!-- 总记录数 -->
<select id="findUserCount"  resultType="int">
  select count(*) from user
</select>
  • POJO类型
<!-- 通过id查询 -->
<select id="findUserById" parameterType="int" resultType="com.czxy.domain.User">
  select * from user where uid = #{id}
</select>

9.3.4 Mapper 映射关系:ResultMap

  • resultType可以指定pojo将查询结果封装到该pojo中,但需要pojo的属性名和sql查询的列名保持一致。
  • 如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系。
  • 语法:
<!--声明映射-->
<resultMap type="JavaBean类型" id="resultMap名称">
  <id column="表列名" property="JavaBean属性名"/>   <!--用于配置主键的映射-->
  <result column="表列名" property="JavaBean属性名"/> <!--用于配置普通结果集映射-->
</resultMap>
<!--使用映射-->
<select resultMap="resultMap名称">
</select>
  • 实例:
<resultMap type="com.czxy.ssm.domain.User" id="userResultMap">
    <id column="uid" property="uid"/>
    <result column="username" property="username"/>
  </resultMap>
    <select id="selectById" parameterType="string" resultMap="userResultMap">
    select * from user where uid = #{id}
  </select>

9.3.5 默认别名

别名 映射类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
map Map

9.3.6 自定义别名

  • 声明别名,在 SqlMapConfig.xml 配置文件中声明
  • 方式1:一次定义一个类
<typeAliases>
  <typeAlias type="类型" alias="别名"/>
</typeAliases>
  • 方式2:一次定义一个包下的所有类
<typeAliases>
  <package name="包名"/>
</typeAliases>

  • 使用别名,在mapper中直接使用
<!--使用别名-->
<select id="selectById" parameterType="string" resultType="user">
  select * from user where uid = #{id}
</select>

9.3.7 加载Mapper文件

  • 在SqlMapConfig.xml文件中,通过加载映射文件
  • 方式1:加载指定文件
<mappers>
    <!-- 表示加载此包下的所有dao接口-->
    <mapper resource="mapper/UserMapper.xml"/>
  </mappers>
  • 方式2:加载指定包下的所有映射文件
  • 要求:要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中
<mappers>
    <package name="com.czxy.ssm.mapper"/>
  </mappers>

9.4 增删改查

9.4.1 核心配置文件

9.4.2 mapper接口

package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.vo.UserVo;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public interface UserMapper {
    /**
     * 通过id查询详情
     * @param uid
     * @return
     */
    public User selectById(String uid);
    /**
     * 查询所有
     * @return
     */
    public List<User> selectAll();
    /**
     * 模糊查询
     * @param name
     * @return
     */
    public List<User> selectByName(@Param("name") String name);
    /**
     * 插入数据
     * @param user
     */
    public Integer insert(User user);
    /**
     * 插入数据
     * @param user
     */
    public Integer updateByPrimaryKey(User user);
    /**
     * 通过id删除
     * @param uid
     */
    public Integer deleteByPrimaryKey(@Param("uid") String uid);
    /**
     * 条件查询
     * @param userVo
     * @return
     */
    public List<User> condition(UserVo userVo);
}

9.4.3 Mapper 映射文件

<?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="com.czxy.ssm.mapper.UserMapper">
  <resultMap type="com.czxy.ssm.domain.User" id="userResultMap">
    <id column="uid" property="uid"/>
    <result column="username" property="username"/>
  </resultMap>
    <select id="selectById" parameterType="string" resultMap="userResultMap">
    select * from user where uid = #{id}
  </select>
  <select id="selectAll" parameterType="string" resultMap="userResultMap">
    select * from user
  </select>
  <select id="selectByName" parameterType="string" resultMap="userResultMap">
    select * from user where name like #{name}
  </select>
  <insert id="insert" parameterType="user">
    insert into user(uid, username, password, name, email, birthday, sex, state) values(#{uid},#{username},#{password},#{name},#{email},#{birthday},#{sex},#{state})
  </insert>
  <update id="updateByPrimaryKey" parameterType="user">
    update user set username=#{username}, password=#{password}, name=#{name}, email=#{email},birthday=#{birthday},sex=#{sex}, state=#{state} where uid=#{uid}
  </update>
  <delete id="deleteByPrimaryKey" >
    delete from user where uid = #{uid}
  </delete>
</mapper>

9.4.4 测试

package com.czxy.ssm.test;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.UserMapper;
import com.czxy.ssm.utils.MyBatisUtils;
import org.junit.Test;
import java.util.Date;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public class TestUserMapper {
    @Test
    public void testSelectById() {
        UserMapper userMapper = MyBatisUtils.getMapper(UserMapper.class);
        User user = userMapper.selectById("1");
        System.out.println(user);
        MyBatisUtils.commitAndclose();
    }
    @Test
    public void testSelectAll() {
        UserMapper UserMapper = MyBatisUtils.getMapper(UserMapper.class);
        List<User> list = UserMapper.selectAll();
        // 打印
        list.forEach(System.out::println);
        MyBatisUtils.commitAndclose();
    }
    @Test
    public void testSelectByName() {
        UserMapper UserMapper = MyBatisUtils.getMapper(UserMapper.class);
        List<User> list = UserMapper.selectByName("%张%");
        // 打印
        list.forEach(System.out::println);
        MyBatisUtils.commitAndclose();
    }
    @Test
    public void testInsert() {
        UserMapper UserMapper = MyBatisUtils.getMapper(UserMapper.class);
        User user = new User();
        user.setUid("2");
        user.setUsername("jack");
        user.setPassword("1234");
        user.setName("杰克");
        user.setEmail("itcast_lt@163.com");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setSex("0");
        int result = UserMapper.insert(user);
        // 打印
        System.out.println(result);
        MyBatisUtils.commitAndclose();
    }
    @Test
    public void testUpdate() {
        UserMapper UserMapper = MyBatisUtils.getMapper(UserMapper.class);
        User user = new User();
        user.setUid("2");
        user.setUsername("jack");
        user.setPassword("1234");
        user.setName("杰克");
        user.setEmail("itcast_lt@163.com");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setSex("0");
        int result = UserMapper.updateByPrimaryKey(user);
        // 打印
        System.out.println(result);
        MyBatisUtils.commitAndclose();
    }
    @Test
    public void testDelete() {
        UserMapper UserMapper = MyBatisUtils.getMapper(UserMapper.class);
        int result = UserMapper.deleteByPrimaryKey("2");
        // 打印
        System.out.println(result);
        MyBatisUtils.commitAndclose();
    }
}

9.5 动态SQL

9.5.1 什么是动态SQL

动态SQL就是Mybatis允许在映射文件中通过标签控制SQL语句最后的拼凑结果。

9.5.2 标签

  • 语法:在mapper映射文件中,标签就相当于Java中if语句,如果条件成立,标签体内的SQL语句有效。
<select>
  <if test="条件">
    //有效的SQL语句片段
  </if>
<select>
  • 封装对象:UserVo
public class UserVo {
    private String name;            // 模糊查询
    private String beginTime;       // 开始时间
    private String endTime;         // 结束时间
    // ...
}
  • 多条件查询,拼凑恒等条件 where 1=1
<select id="condition" parameterType="userVo" resultType="user" >
    select * from user where 1=1
    <if test="name != null and name != ''">
      and name like '%${name}%'
    </if>
  </select>
  • 测试
@Test
    public void testCondtion() {
        UserMapper UserMapper = MyBatisUtils.getMapper(UserMapper.class);
        UserVo userVo = new UserVo();
        userVo.setName("张");
        List<User> list = UserMapper.condition(userVo);
        // 打印
        list.forEach(System.out::println);
        MyBatisUtils.commitAndclose();
    }

9.5.3 标签

  • 多条件查询时,我们使用了一个小技巧“where 1=1”,mybatis提供了一个进行取代。
  • 修改映射文件
<select id="condition" parameterType="userVo" resultType="user" >
    select * from user
    <where>
      <if test="name != null and name != ''">
        and name like '%${name}%'
      </if>
    </where>
  </select>

9.5.4 >标签

  • 语法:
<!--
<foreach> 就是遍历一组数据,根据指定的内容拼凑成SQL语句片段
    collection ,需要遍历的数据,如果实际参数就是数组本身,此处需要使用array
    item ,每一次循环时存放数据的变量,在标签体中可以通过 ${item值}获得遍历数据
    open ,SQL语句片段的开发位置
    separator,分隔符号
    close ,SQL语句片段的结束位置
-->
<!-- 例如:uid in (1,2,4,6) 片段的拼凑
  开始 (变量 分隔符)*4 结束
-->
<foreach collection="数组" open="uid in (" item="变量" separator=","  close=")">
</foreach>
  • 封装对象
public class UserVo {
    private List<String> ids = new ArrayList<>();
    private String name;            // 模糊查询
    private String beginTime;       // 开始时间
    private String endTime;         // 结束时间
    // ... 
}
  • 多条件查询
<select id="condition" parameterType="userVo" resultType="user" >
    select * from user
    <where>
      <!-- uid in (1,2,4,6) -->
      <foreach collection="ids" open="uid in (" item="id" separator="," close=")">
        '${id}'
      </foreach>
    </where>
  </select>
  • 测试
@Test
    public void testCondtion() {
        UserMapper UserMapper = MyBatisUtils.getMapper(UserMapper.class);
        UserVo userVo = new UserVo();
        userVo.setIds(Arrays.asList("u001","u002"));
        List<User> list = UserMapper.condition(userVo);
        // 打印
        list.forEach(System.out::println);
        MyBatisUtils.commitAndclose();
    }

9.5.5 标签:多条件

  • 语法
<select id="">
    <choose>
      <when test=""></when>
      <when test=""></when>
      <otherwise></otherwise>
    </choose>
  </select>

9.5.6 标签

  • MyBatis为我们提供了代码片段,使用定义公共SQL语句,使用将需要的SQL片段拼凑到指定的位置。
<!-- 所有字段名称SQL片段 -->
<sql id="user_all_column">uid, username, password, name, email, birthday, sex, state</sql>
<select id="selectAll" parameterType="string" resultMap="userResultMap">
  select <include refid="user_all_column" /> from user
</select>

9.6 关系映射:一对多

9.6.1 mapper接口

  • UserMapper,已有
public interface UserMapper {
    /**
     * 通过id查询详情
     * @param uid
     * @return
     */
    public User selectById(String uid);
}
  • OrderMapper
package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.Order;
import org.apache.ibatis.annotations.Param;
/**
 * @author  manor的大数据之路
 *  
 */
public interface OrderMapper {
    /**
     * 查询指定用户的所有的订单
     * @param uid
     * @return
     */
    public Order findOrdersByUserId(@Param("uid") Integer uid) ;
}

9.6.2 Mapper 映射文件

  • OrdersMapper.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="com.czxy.ssm.mapper.OrderMapper">
    <select id="findOrdersByUserId" parameterType="string" resultType="order" >
    select * from orders where uid = #{uid}
  </select>
</mapper>
  • UserMapper.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="com.czxy.ssm.mapper.UserMapper">
  <resultMap type="com.czxy.ssm.domain.User" id="userResultMap">
    <id column="uid" property="uid"/>
    <result column="username" property="username"/>
    <collection property="orderList" column="uid" select="com.czxy.ssm.mapper.OrderMapper.findOrdersByUserId" />
  </resultMap>
    <select id="selectById" parameterType="string" resultMap="userResultMap">
    select * from user where uid = #{id}
  </select>
</mapper>

9.6.3 核心配置文件

9.6.4 测试

public class TestUserMapper {
    @Test
    public void testSelectById() {
        UserMapper userMapper = MyBatisUtils.getMapper(UserMapper.class);
        User user = userMapper.selectById("u001");
        System.out.println(user);
        MyBatisUtils.commitAndclose();
    }
}

9.7 关系映射:多对一

9.7.1 mapper接口

package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.Order;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public interface OrderMapper {
    /**
     *
     * @param oid
     * @return
     */
    public Order selectById(@Param("oid") String oid);
}

9.7.2 映射文件:OrdersMapper.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="com.czxy.ssm.mapper.OrderMapper">
  <resultMap id="ordersResultMap" type="order">
    <id property="oid" column="oid"></id>
    <result property="ordertime" column="ordertime" ></result>
    <result property="total" column="total" ></result>
    <result property="state" column="state" ></result>
    <result property="address" column="address" ></result>
    <result property="name" column="name" ></result>
    <result property="telephone" column="telephone" ></result>
    <result property="uid" column="uid" ></result>
    <association property="user" select="com.czxy.ssm.mapper.UserMapper.selectById" column="uid" />
  </resultMap>
  <select id="selectById" resultMap="ordersResultMap">
    select * from orders where oid = #{oid}
  </select>
</mapper>

9.7.3 测试类

package com.czxy.ssm.test;
import com.czxy.ssm.domain.Order;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.OrderMapper;
import com.czxy.ssm.mapper.UserMapper;
import com.czxy.ssm.utils.MyBatisUtils;
import com.czxy.ssm.vo.UserVo;
import org.junit.Test;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public class TestOrderMapper {
    @Test
    public void testSelectById() {
        OrderMapper orderMapper = MyBatisUtils.getMapper(OrderMapper.class);
        Order order = orderMapper.selectById("x001");
        System.out.println(order);
        MyBatisUtils.commitAndclose();
    }
}
tis.org/dtd/mybatis-3-mapper.dtd">
  <mapper namespace="com.czxy.ssm.mapper.OrderMapper">
      <select id="findOrdersByUserId" parameterType="string" resultType="order" >
      select * from orders where uid = #{uid}
    </select>
  </mapper>
  • UserMapper.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="com.czxy.ssm.mapper.UserMapper">
  <resultMap type="com.czxy.ssm.domain.User" id="userResultMap">
    <id column="uid" property="uid"/>
    <result column="username" property="username"/>
    <collection property="orderList" column="uid" select="com.czxy.ssm.mapper.OrderMapper.findOrdersByUserId" />
  </resultMap>
    <select id="selectById" parameterType="string" resultMap="userResultMap">
    select * from user where uid = #{id}
  </select>
</mapper>

9.6.3 核心配置文件

[外链图片转存中…(img-emp3n0Qt-1632570480007)]

9.6.4 测试

public class TestUserMapper {
    @Test
    public void testSelectById() {
        UserMapper userMapper = MyBatisUtils.getMapper(UserMapper.class);
        User user = userMapper.selectById("u001");
        System.out.println(user);
        MyBatisUtils.commitAndclose();
    }
}

9.7 关系映射:多对一

9.7.1 mapper接口

package com.czxy.ssm.mapper;
import com.czxy.ssm.domain.Order;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public interface OrderMapper {
    /**
     *
     * @param oid
     * @return
     */
    public Order selectById(@Param("oid") String oid);
}

9.7.2 映射文件:OrdersMapper.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="com.czxy.ssm.mapper.OrderMapper">
  <resultMap id="ordersResultMap" type="order">
    <id property="oid" column="oid"></id>
    <result property="ordertime" column="ordertime" ></result>
    <result property="total" column="total" ></result>
    <result property="state" column="state" ></result>
    <result property="address" column="address" ></result>
    <result property="name" column="name" ></result>
    <result property="telephone" column="telephone" ></result>
    <result property="uid" column="uid" ></result>
    <association property="user" select="com.czxy.ssm.mapper.UserMapper.selectById" column="uid" />
  </resultMap>
  <select id="selectById" resultMap="ordersResultMap">
    select * from orders where oid = #{oid}
  </select>
</mapper>

9.7.3 测试类

package com.czxy.ssm.test;
import com.czxy.ssm.domain.Order;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.OrderMapper;
import com.czxy.ssm.mapper.UserMapper;
import com.czxy.ssm.utils.MyBatisUtils;
import com.czxy.ssm.vo.UserVo;
import org.junit.Test;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
 * @author  manor的大数据之路
 *  
 */
public class TestOrderMapper {
    @Test
    public void testSelectById() {
        OrderMapper orderMapper = MyBatisUtils.getMapper(OrderMapper.class);
        Order order = orderMapper.selectById("x001");
        System.out.println(order);
        MyBatisUtils.commitAndclose();
    }
}


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7天前
|
安全 Java 开发者
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第9天】本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化。我们将详细解析Java中的同步机制,包括synchronized关键字、Lock接口以及并发集合等,并探讨它们如何影响程序的性能。此外,我们还将讨论Java内存模型,以及它如何影响并发程序的行为。最后,我们将提供一些实用的并发编程技巧和最佳实践,帮助开发者编写出既线程安全又高效的Java程序。
20 3
|
10天前
|
Java 调度
Java并发编程:深入理解线程池的原理与实践
【4月更文挑战第6天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将从线程池的基本原理入手,逐步解析其工作过程,以及如何在实际开发中合理使用线程池以提高程序性能。同时,我们还将关注线程池的一些高级特性,如自定义线程工厂、拒绝策略等,以帮助读者更好地掌握线程池的使用技巧。
|
14天前
|
存储 NoSQL Java
Java数据库编程指南:实现高效数据存储与访问
【4月更文挑战第2天】Java开发者必须掌握数据库编程,尤其是JDBC,它是连接数据库的标准接口。使用Spring JDBC或JPA能简化操作。选择合适的JDBC驱动,如MySQL Connector/J,对性能至关重要。最佳实践包括事务管理、防SQL注入、优化索引和数据库设计。NoSQL数据库如MongoDB也日益重要,Java有对应的驱动支持。理解这些概念和技术是构建高效数据库应用的基础。
Java数据库编程指南:实现高效数据存储与访问
|
10天前
|
设计模式 安全 Java
Java并发编程实战:使用synchronized关键字实现线程安全
【4月更文挑战第6天】Java中的`synchronized`关键字用于处理多线程并发,确保共享资源的线程安全。它可以修饰方法或代码块,实现互斥访问。当用于方法时,锁定对象实例或类对象;用于代码块时,锁定指定对象。过度使用可能导致性能问题,应注意避免锁持有时间过长、死锁,并考虑使用`java.util.concurrent`包中的高级工具。正确理解和使用`synchronized`是编写线程安全程序的关键。
|
13天前
|
Java
深入理解Java并发编程:线程池的应用与优化
【4月更文挑战第3天】 在Java并发编程中,线程池是一种重要的资源管理工具,它能有效地控制和管理线程的数量,提高系统性能。本文将深入探讨Java线程池的工作原理、应用场景以及优化策略,帮助读者更好地理解和应用线程池。
|
8天前
|
Java
Java 并发编程:深入理解线程池
【4月更文挑战第8天】本文将深入探讨 Java 中的线程池技术,包括其工作原理、优势以及如何使用。线程池是 Java 并发编程的重要工具,它可以有效地管理和控制线程的执行,提高系统性能。通过本文的学习,读者将对线程池有更深入的理解,并能在实际开发中灵活运用。
|
4天前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第11天】 在Java中,高效的并发编程是提升应用性能和响应能力的关键。本文将探讨Java并发的核心概念,包括线程安全、锁机制、线程池以及并发集合等,同时提供实用的编程技巧和最佳实践,帮助开发者在保证线程安全的前提下,优化程序性能。我们将通过分析常见的并发问题,如竞态条件、死锁,以及如何利用现代Java并发工具来避免这些问题,从而构建更加健壮和高效的多线程应用程序。
|
9天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第7天】在现代软件开发中,多线程编程已经成为一种不可或缺的技术。为了提高程序性能和资源利用率,Java提供了线程池这一强大工具。本文将深入探讨Java线程池的原理、使用方法以及如何根据实际需求定制线程池,帮助读者更好地理解和应用线程池技术。
15 0
|
10天前
|
缓存 安全 Java
Java并发编程进阶:深入理解Java内存模型
【4月更文挑战第6天】Java内存模型(JMM)是多线程编程的关键,定义了线程间共享变量读写的规则,确保数据一致性和可见性。主要包括原子性、可见性和有序性三大特性。Happens-Before原则规定操作顺序,内存屏障和锁则保障这些原则的实施。理解JMM和相关机制对于编写线程安全、高性能的Java并发程序至关重要。
|
22小时前
|
设计模式 运维 安全
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第15天】在Java开发中,多线程编程是提升应用程序性能和响应能力的关键手段。然而,它伴随着诸多挑战,尤其是在保证线程安全的同时如何避免性能瓶颈。本文将探讨Java并发编程的核心概念,包括同步机制、锁优化、线程池使用以及并发集合等,旨在为开发者提供实用的线程安全策略和性能优化技巧。通过实例分析和最佳实践的分享,我们的目标是帮助读者构建既高效又可靠的多线程应用。