MyBatis学习(二)SqlMapConfig.xml配置

8 篇文章 0 订阅
8 篇文章 0 订阅

MyBatis学习(二)SqlMapConfig.xml配置

示例工程:mybatis-demo2

本文档记录的是学习过程,主要描述了MyBatis中关于SqlMapConfig.xml的配置,版权所有

1、搭建MyBatis的开发环境

1.1、创建Maven项目

1)在IDEA中直接新建一个普通的maven项目

2)新建src/main/java目录、src/main/resources目录

3)新建src/test/java目录

4)新建对应的包路径com.iambest.study

  • 对应的目录结构如下所示:
├── pom.xml
├── README.md
├── src
│   ├── main
│   │   ├── java
│   │   └── resources
│   └── test
│       ├── java
│       └── resources
└── target

1.2、引入jar包依赖

在pom.xml中引入我们需要的jar包,包括:

1)mysql的数据库驱动

2)mybatis的jar依赖包

3)dbcp的数据库连接策略

  • pom.xml的依赖部分如下所示:
  <dependencies>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>

    <!-- 引入mysql的数据库驱动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.30</version>
    </dependency>

    <!-- 引入MyBatis的maven jar包 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>

    <!-- 数据库连接池策略 -->
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.2.2</version>
    </dependency>

    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.1</version>
    </dependency>
  </dependencies>

2、使用SqlMapConfig.xml配置MyBatis

2.1、配置SqlMapConfig.xml文件

1)在MyBatis中,通过SqlMapConfig.xml配置文件,进行配置MyBatis的基本信息

2)通过SqlSessionFactoryBuilder构建SqlSessionFactory工厂对象

3)然后通过SqlSessionFactory获取SqlSession

4)我们的核心操作都依赖SqlSession来完成,三大核心对象如下:

  • SqlSessionFactoryBuilder
  • SqlSessionFactory
  • SqlSession

1)首先,我们来配置我们的SqlMapConfig-sqlSession.xml文件

2)在resources/config目录下新建该文件,内容如下

  • SqlMapConfig-sqlSession.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"
        "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
<configuration>
    <environments default="environment">
        <environment id="environment">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/david"></property>
                <property name="username" value="root"></property>
                <property name="password" value="123456"></property>
            </dataSource>
        </environment>
    </environments>
</configuration>

2.2、单元测试验证

2.2.1、编写单元测试代码

1)我们通过编写单元测试的方式,验证我们的配置是否生效

2)如下是我们编写的单元测试用例代码

  • TestSqlSession
package com.iambest.study;

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 org.junit.Test;

import java.io.IOException;
import java.io.Reader;

/**
 * 测试SQLSession类
 */
public class TestSqlSession {
    @Test
    public void testSqlSession() throws IOException {
        String config = "config/SqlMapConfig-sqlSession.xml";
        Reader reader = Resources.getResourceAsReader(config);
        // 创建Builder对象
        SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
        // 创建Factory对象
        SqlSessionFactory factory = sfb.build(reader);
        // 通过factory对象生成session对象
        SqlSession session = factory.openSession();
        System.out.println(session);
        session.close();
    }
}
2.2.2、执行单元测试

运行我们的单元测试用例,如下图所示,表示我们的配置没有问题:

在这里插入图片描述

3、使用SqlMapConfig.xml结合mapper.xml实现数据库CRUD

本示例中使用到数据库表的建表语句如下:

-- mysql的建表脚本
create table t_student_info(
    id varchar(20) not null comment '主键',
    name varchar(50) default ' ' comment '姓名',
    age decimal(3) default 20 comment '年龄',
    sex char(1) default 'M' comment '性别 M-男,W-女',
    phone varchar(20) comment '手机号',
    email varchar(30) comment '电子邮箱',
    rsv1 varchar(100) comment '备注字段',
		primary key (id)
) engine=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COMMENT '学生信息表';

-- 订单信息表
create table tb_order_info(
	order_id			varchar(10)						not null comment '订单id',
	payment				decimal(18,2)	default 0.00		comment '支付金额',
	goods_name			varchar(256)	default ''			comment '商品名称',
	payment_type		char(1)			default	'1'			comment '支付类型 : 1-在线支付,2-货到付款',
	post_fee			decimal(18,2)	default 0.00		comment '邮费',
	status				char(1)			default '1'			comment '订单状态:1-未付款,2-已付款,3-未发货,4-已发货,5-交易成功,6-交易关闭',
	create_time			date comment '订单创建时间',
	constraint pk_order_id primary key(order_id)
) engine=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 comment '订单信息表';

3.1、insert操作

3.1.1、配置文件及实体类

1)需要修改我们的SqlMapConfig文件SqlMapConfig-insert.xml,增加mappers节点,并引入我们的sqlMapper文件

2)新建sqlMapper文件StudentInfoMapper,并添加我们需要的方法,这里是:addStudentInfo

SqlMapConfig
  • 首先我们配置一下我们的SqlMapConfig文件
  • SqlMapConfig-insert.xml
  • SqlMapConfig-insert.xml文件中添加mappers节点,并引入sqlMapper文件,如下:
<?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>
    <environments default="environment">
        <environment id="environment">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/david"></property>
                <property name="username" value="root"></property>
                <property name="password" value="123456"></property>
            </dataSource>
        </environment>
    </environments>
    <!-- 手工引入我们的mapper.xml文件 -->
    <mappers>
        <mapper resource="config/mapper/StudentInfoMapper.xml"></mapper>
    </mappers>
</configuration>
StudentInfoMapper
  • 看一下我们的数据库mapper文件,StudentInfoMapper
  • mapper文件的路径在:resources/config/mapper路径下
  • 在其中增加addStudentInfo方法,内容如下:
<?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.iambest.study.dao.StudentInfoMapper">

    <!-- 登记数据库表 -->
    <insert id="addStudentInfo" parameterType="com.iambest.study.entity.StudentInfoDo">
        insert into t_student_info (id,name,age,sex,phone,email,rsv1)
        values
        (#{id},#{name},#{age},#{sex},#{phone},#{email},#{rsv1})
    </insert>
</mapper>
StudentInfoDo
  • StudentInfoDo为数据表的映射文件
  • 这里我们将其与数据库的字段一一对应起来,内容如下:
package com.iambest.study.entity;

import java.util.Objects;

/**
 * StudentInfoDo数据实体</br>
 *
 * <b>映射的是t_student_info数据库表的字段</b>
 *
 */
public class StudentInfoDo {

    private String id;

    private String name;

    private Integer age;

    private String sex;

    private String phone;

    private String email;

    private String rsv1;

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

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

    public String getRsv1() {
        return rsv1;
    }

    public void setRsv1(String rsv1) {
        this.rsv1 = rsv1;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        StudentInfoDo that = (StudentInfoDo) o;
        return Objects.equals(id, that.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    @Override
    public String toString() {
        return "StudentInfoDo{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", phone='" + phone + '\'' +
                ", email='" + email + '\'' +
                ", rsv1='" + rsv1 + '\'' +
                '}';
    }
}
3.1.2、编写单元测试代码

1)配置完成之后,我们在test目录下编写单元测试代码,测试insert

  • testInsert 方法
   @Test
    public void testInsert() throws IOException {
        String config = "config/SqlMapConfig-insert.xml";
        Reader reader = Resources.getResourceAsReader(config);
        // 创建Builder对象
        SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
        // 创建Factory对象
        SqlSessionFactory factory = sfb.build(reader);
        // 通过factory对象生成session对象
        SqlSession session = factory.openSession();

        // 这里我们手工创studentInfo建一个新的对象
        StudentInfoDo studentInfo = new StudentInfoDo();
        studentInfo.setId("10002");
        studentInfo.setName("李四");
        studentInfo.setSex("W");
        studentInfo.setAge(18);
        studentInfo.setPhone("18100002222");
        studentInfo.setEmail("lisi@163.com");
        studentInfo.setRsv1("这里是李四的备注");
        // 打印一下李四的信息
        System.out.println(studentInfo);

        // 使用sqlSession对象执行插入操作
        session.insert("addStudentInfo",studentInfo);
        // 提交事务
        session.commit();
        // 关闭
        session.close();
        System.out.println("执行插入成功!");
    }
3.1.3、测试并验证结果

1)执行单元测试用例,看一下控制台的输出以及数据库的数据是否插入成功

  • 执行单元测试用例,控制台的输出:

在这里插入图片描述

  • 查询数据库,新增数据成功:
    在这里插入图片描述

3.2、update操作

3.2.1、配置文件

1)在sqlMapper文件StudentInfoMapper.xml文件中,添加update方法updateById

  • StudentInfoMapper
   <!-- 根据ID更新数据库 -->
    <update id="updateById" parameterType="com.iambest.study.entity.StudentInfoDo">
        update t_student_info set NAME=#{name},AGE=#{age},SEX=#{sex},PHONE=#{phone},
        EMAIL=#{email},RSV1=#{rsv1} where ID=#{id}
    </update>
3.2.2、编写单元测试代码

1)编写单元测试代码testUpdate,将已经存在的信息进行更新,

  • testUpdate
	@Test
    public void testUpdate() throws IOException{
        String config = "config/SqlMapConfig-insert.xml";
        Reader reader = Resources.getResourceAsReader(config);
        // 创建Builder对象
        SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
        // 创建Factory对象
        SqlSessionFactory factory = sfb.build(reader);
        // 通过factory对象生成session对象
        SqlSession session = factory.openSession();

        // 这里我们手工创studentInfo建一个新的对象
        StudentInfoDo studentInfo = new StudentInfoDo();
        studentInfo.setId("10002");
        studentInfo.setName("李四");
        studentInfo.setSex("W");
        studentInfo.setAge(18);
        // 把手机号修改掉
        studentInfo.setPhone("15988887777");
        studentInfo.setEmail("lisi@163.com");
        // 把备注信息修改掉
        studentInfo.setRsv1("李四是张三的妹妹");
        // 打印一下李四的信息
        System.out.println(studentInfo);

        // 使用sqlSession对象执行更新操作
        session.insert("updateById",studentInfo);
        // 提交事务
        session.commit();
        // 关闭
        session.close();
        System.out.println("执行更新成功!");
    }
3.2.3、测试并验证结果

1)执行单元测试用例,查看控制台的数据,并通过终端工具查看更新的结果

  • 执行单元测试,查看单元测试用例结果,如下:
    在这里插入图片描述
  • 查看数据库的更新结果,李四的手机号及备注已经被更新,表示成功了,如下:

在这里插入图片描述

3.3、select操作

3.3.1、配置文件

1)查询操作,我们这里通过ID进行查询,在StudentInfoMapper文件中添加selectById方法

2)返回的结果集,我们通过对象StudentInfoDo的方式进行包装

3)同时,我们添加查询所有结果的方法findAll,其返回结果是一个对象的列表集合

4)我们预置了一条数据,id为10003

  • StudentInfoMapper中添加selectById方法,如下:
    <!-- 根据ID查询 -->
    <select id="selectById" resultType="com.iambest.study.entity.StudentInfoDo">
        select id,name,age,sex,phone,email,rsv1 from t_student_info where ID=#{id}
    </select>
  • findAll方法
   <select id="findAll" resultType="com.iambest.study.entity.StudentInfoDo">
        select id,name,age,sex,phone,email,rsv1 from t_student_info
   </select>
3.3.2、编写单元测试代码

1)在测试类中添加 testSelectById方法,测试根据ID的查询结果

2)添加testFindAll方法,测试查询所有记录的查询方法

  • testSelectById

     @Test
    public void testSelectById() throws IOException{
        String config = "config/SqlMapConfig-insert.xml";
        Reader reader = Resources.getResourceAsReader(config);
        // 创建Builder对象
        SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
        // 创建Factory对象
        SqlSessionFactory factory = sfb.build(reader);
        // 通过factory对象生成session对象
        SqlSession session = factory.openSession();

        StudentInfoDo studentInfoDo = session.selectOne("selectById","10003");
        System.out.println(studentInfoDo);
        session.close();

    }
  • testFindAll

    @Test
    public void testFindAll() throws IOException {
        String config = "config/SqlMapConfig-insert.xml";
        Reader reader = Resources.getResourceAsReader(config);
        // 创建Builder对象
        SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
        // 创建Factory对象
        SqlSessionFactory factory = sfb.build(reader);
        // 通过factory对象生成session对象
        SqlSession session = factory.openSession();
        List<StudentInfoDo> lists = session.selectList("findAll");
        for (StudentInfoDo node : lists) {
            System.out.println(node);
        }
        session.close();
    }
3.3.3、测试并验证结果

1)分别通过运行单元测试,测试查询的结果

testSelectById
  • 查看控制台的输出

在这里插入图片描述

testFindAll
  • 查看控制台的输出

在这里插入图片描述

3.4、delete操作

3.4.1、配置文件

1)在SQLMapper文件中,添加根据id删除数据的方法deleteById

  • StudentInfoMapper
    <!-- 根据ID进行删除 -->
    <delete id="deleteById" parameterType="java.lang.String">
        delete from t_student_info where ID=#{id}
    </delete>
3.4.2、编写单元测试代码

1)编写单元测试代码testDelete,删除我们刚刚预置的数据

  • testDelete
   @Test
    public void testDelete() throws IOException {
        String config = "config/SqlMapConfig-insert.xml";
        Reader reader = Resources.getResourceAsReader(config);
        // 创建Builder对象
        SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
        // 创建Factory对象
        SqlSessionFactory factory = sfb.build(reader);
        // 通过factory对象生成session对象
        SqlSession session = factory.openSession();
        int resultTot = session.delete("deleteById","10003");
        System.out.println("成功删除的总条数为:" + resultTot);
        // 提交事务
        session.commit();
        session.close();

    }
3.4.3、测试并验证结果

1)执行我们的单元测试用例,查看控制台的输出,

2)通过终端工具查询数据库,验证数据是否真的被删除

  • 执行测试用例,查看控制台的输出

在这里插入图片描述

  • 查询数据库,验证数据是否被真的删除了;这里可以看到数据已经被删除

在这里插入图片描述

3.5、说明

  • 我们的示例代码中,mybatis默认获取到的sqlsession是不能自动提交事务的
  • 那么DML语句执行完成之后,需要手工执行commit,才能提交事务,使操作失效
  • 如果想自动提交事务,需要在opensession(true)时,设置autoCommit为true即可

4、使用RowBounds实现分页查询(强烈不推荐)

4.1、预置数据

1)我们预置了一个订单表tb_order_info,里面通过程序生成了50万条数据,利用此表来实现分页查询

4.1.1、预置数据的相关代码
实体类OrderInfo

1)OrderInfo 实体类与tb_order_info字段进行映射,属性采用驼峰命名法

2)完整代码如下:

package com.iambest.study.entity;

import java.math.BigDecimal;
import java.util.Date;

/**
 *
 */
public class OrderInfo {

    private String orderId;
    private BigDecimal payment;
    private String goodsName;
    private String paymentType;
    private BigDecimal postFee;
    private String status;
    private Date createTime;

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public BigDecimal getPayment() {
        return payment;
    }

    public void setPayment(BigDecimal payment) {
        this.payment = payment;
    }

    public String getGoodsName() {
        return goodsName;
    }

    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }

    public String getPaymentType() {
        return paymentType;
    }

    public void setPaymentType(String paymentType) {
        this.paymentType = paymentType;
    }

    public BigDecimal getPostFee() {
        return postFee;
    }

    public void setPostFee(BigDecimal postFee) {
        this.postFee = postFee;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Date getCreateTime() {
        return createTime;
    }

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

    @Override
    public String toString() {
        return "OrderInfo [orderId=" + orderId + ", payment=" + payment
                + ", goodsName=" + goodsName + ", paymentType=" + paymentType
                + ", postFee=" + postFee + ", status=" + status
                + ", createTime=" + createTime + "]";
    }
}
数据库连接的工具类ConnectionSource

1)ConnectionSource类通过读取配置文件、封装了获取数据库连接的方法

2)同时使用了连接池的策略,完整代码如下:

package com.iambest.study.utils;

import org.apache.commons.dbcp.BasicDataSource;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class ConnectionSource {
    private static BasicDataSource dataSource = null;

    private ConnectionSource() {

    }
    public static void init() {
        Properties prop = new Properties();
        try {
            prop.load(ConnectionSource.class.getClassLoader()
                    .getResourceAsStream("config/db_mysql.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        String driver = prop.getProperty("jdbc.driver");
        String url = prop.getProperty("jdbc.url");
        String username = prop.getProperty("jdbc.username");
        String password = prop.getProperty("jdbc.password");

        String initialSize = prop.getProperty("dataSource.initialSize");
        String minIdle = prop.getProperty("dataSource.minIdle");
        String maxIdle = prop.getProperty("dataSource.maxIdle");
        String maxWait = prop.getProperty("dataSource.maxWait");
        String maxActive = prop.getProperty("dataSource.maxActive");

        dataSource = new BasicDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);

        if (initialSize != null && initialSize.trim().length() != 0) {
            dataSource.setInitialSize(Integer.parseInt(initialSize));
        }
        if (minIdle != null && minIdle.trim().length() != 0) {
            dataSource.setMinIdle(Integer.parseInt(minIdle));
        }
        if (maxIdle != null && maxIdle.trim().length() != 0) {
            dataSource.setMaxIdle(Integer.parseInt(maxIdle));
        }
        if (maxWait != null && maxWait.trim().length() != 0) {
            dataSource.setMaxWait(Integer.parseInt(maxWait));
        }
        if (maxActive != null && maxActive.trim().length() != 0) {
            dataSource.setMaxActive(Integer.parseInt(maxActive));
        }

    }

    /**
     *
     * @return
     * @throws SQLException
     */
    public static synchronized Connection getConnection() throws SQLException {
        if (dataSource == null) {
            System.out.println("dataSource对象为空,调用创建对象的方法");
            init();
        }
        Connection conn = null;
        if (dataSource != null) {
            conn = dataSource.getConnection();
        }
        return conn;
    }
}
数据库配置文件db_mysql.properties

1)db_mysql.properties 配置了数据库连接的相关信息

#JDBC Connection INFO
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/david
jdbc.username=root
jdbc.password=123456

#JDBC Pool INFO
dataSource.initialSize=10
dataSource.maxIdle=20
dataSource.minIdle=5
dataSource.maxActive=50
dataSource.maxWait=1000
预置50万条数据TestInitDataBaseData

1)我们通过批量提交的方式,初始化50万条数据到mysql的数据库

2)代码如下:

package com.iambest.study;


import com.iambest.study.entity.OrderInfo;
import com.iambest.study.utils.ConnectionSource;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
import java.util.Random;

/**
 *
 * 初始化数据库表中的数据
 *
 * @author zhang_wei
 *
 */
public class TestInitDataBaseData {

    private static final Random rand = new Random();

    private static final String paymentTypes[] = new String[] { "1", "2" };

    private static final BigDecimal payments[] = new BigDecimal[] {
            new BigDecimal("5299.00"), new BigDecimal("5899.00"),
            new BigDecimal("6099.00"), new BigDecimal("4999.00") };

    private static final String status[] = new String[] { "1", "2", "3", "4",
            "5", "6" };

    private static final String goodsKind[] = new String[] { "iPhone X ",
            "iPhone XS ", "华为Mate 30 ", "小米8 ", "锤子手机 ", "华为Mate30 Pro " };

    private static final String goodsSize[] = new String[] { "64G ", "128G ",
            "256G ", "512 G" };

    private static final String goodsColor[] = new String[] { "白色 ", "银灰色 ",
            "红色 ", "黑色 " };

    private static final BigDecimal postFees[] = new BigDecimal[] {
            new BigDecimal("5.00"), new BigDecimal("10.00"),
            new BigDecimal("8.00"), new BigDecimal("0.00") };

    public static void main(String[] args) throws SQLException {
        TestInitDataBaseData tst = new TestInitDataBaseData();
        System.out.println("开始初始化数据...");
        long start = System.currentTimeMillis();
        tst.initMysqlData();
        long end = System.currentTimeMillis();
        System.out.println("初始化数据完成...");
        System.out.println("总耗时:" + (end - start) + " ms");
    }

    /**
     *
     * 初始化数据
     *
     * @throws SQLException
     */
    public void initData() throws SQLException {

        Connection conn = ConnectionSource.getConnection();
        String sql = "insert into david.tb_order_info(order_id,payment,goods_name,payment_type,post_fee,status,create_time) "
                + "values(seq_order_id.nextval,?,?,?,?,?,?)";
        PreparedStatement prep = conn.prepareStatement(sql);
        for (int i = 0; i < 1000; i++) {
            long start = System.currentTimeMillis();
            for (int j = 0; j < 1000; j++) {
                OrderInfo order = genOrderInfo();
                prep.setBigDecimal(1, order.getPayment());
                prep.setString(2, order.getGoodsName());
                prep.setString(3, order.getPaymentType());
                prep.setBigDecimal(4, order.getPostFee());
                prep.setString(5, order.getStatus());
                prep.setDate(6, new java.sql.Date(order.getCreateTime()
                        .getTime()));
                prep.addBatch();
            }
            prep.executeBatch();
            prep.clearBatch();
            long end = System.currentTimeMillis();
            System.out.println("执行成功:" + i +" 总耗时:" + (end - start) + " ms");
        }

        prep.close();
        conn.close();
    }

    /**
     *
     * MySQL的数据初始化
     *
     * @throws SQLException
     */
    public void initMysqlData() throws SQLException{
        Connection conn = ConnectionSource.getConnection();
        int index = 102000000;
        String sql = "insert into tb_order_info(payment,goods_name,payment_type,post_fee,status,create_time,order_id) "
                + "values(?,?,?,?,?,?,?)";
        PreparedStatement prep = conn.prepareStatement(sql);
        for (int i = 0; i < 500; i++) {
            long start = System.currentTimeMillis();
            for (int j = 0; j < 1000; j++) {

                OrderInfo order = genOrderInfo();
                prep.setBigDecimal(1, order.getPayment());
                prep.setString(2, order.getGoodsName());
                prep.setString(3, order.getPaymentType());
                prep.setBigDecimal(4, order.getPostFee());
                prep.setString(5, order.getStatus());
                prep.setDate(6, new java.sql.Date(order.getCreateTime()
                        .getTime()));
                prep.setString(7, String.valueOf(index));
                index ++;
                prep.addBatch();
            }

            long aa = System.currentTimeMillis();
            prep.executeBatch();
            prep.clearBatch();
            long bb = System.currentTimeMillis();

            System.out.println("生成数据的时间:" + (aa-start));
            System.out.println("插入的执行时间:" + (bb-aa));

            long end = System.currentTimeMillis();
            System.out.println("执行成功:" + i +" 总耗时:" + (end - start) + " ms\r\n");
        }

        prep.close();
        conn.close();
    }

    /**
     *
     * 随机生成一个OrderInfo实体对象
     *
     * @return 随机生成的OrderInfo实体对象
     */
    public static OrderInfo genOrderInfo() {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setPayment(payments[getIndex(payments.length)]);
        orderInfo.setGoodsName(goodsKind[getIndex(goodsKind.length)]
                + goodsColor[getIndex(goodsColor.length)]
                + goodsSize[getIndex(goodsSize.length)]);
        orderInfo.setPaymentType(paymentTypes[getIndex(paymentTypes.length)]);
        orderInfo.setPostFee(postFees[getIndex(postFees.length)]);
        orderInfo.setCreateTime(new Date());
        orderInfo.setStatus(status[getIndex(status.length)]);

        return orderInfo;
    }

    /**
     *
     * 根据指定长度,随机生成下标
     *
     * @param length
     *            指定的长度
     * @return 下标
     */
    public static int getIndex(int length) {
        return rand.nextInt(length);
    }
}

4.2、RowBounds实现分页查询

原理:

​ 1)MyBatis中实现分页的原理是将所有的数据都查出来,放到内存中,而后通过上送的参数进行截取

缺点:

​ 1)由于需要将所有符合条件的数据全部查询出来,并放到内存中,因此当查询的结果集过大时,容易产生内存溢出

​ 2)结果集的数据量过大,也会导致查询速度便面,增加数据库的压力

​ 3)因此我们强烈不推荐使用该方式来实现分页查询,本文只是为了阐述原理

解决方案:(后续我专门写一篇文章来实现)

​ 1)需要重写MyBatis的相关组件,来实现自定义的分页查询实现策略

​ 2)mysql和oracle的分页实现策略是不一样的,我在另一篇文章中专门阐述了相关的实现方式,请移步链接

Oracle 和 MySQL 中的分页查询实现

4.2.1、调整SqlMapConfig.xml文件

1)在原有的SqlMapConfig.xml文件SqlMapConfig-insert.xml中引入我们新建的OrderInfoMapper.xml文件

    <!-- 手工引入我们的mapper.xml文件 -->
    <mappers>
        <mapper resource="config/mapper/StudentInfoMapper.xml"></mapper>
        <mapper resource="config/mapper/OrderInfoMapper.xml"/>
    </mappers>
4.2.2、新建OrderInfoMapper.xml文件

1)在resources/config/mapper目录下新建文件OrderInfoMapper.xml

  • OrderInfoMapper.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.iambest.study.dao.OrderInfoMapper">
    <!-- 这里为了和entity中的字段映射上,每个字段使用别名进行包装 -->
    <select id="findAllOrderInfos" resultType="com.iambest.study.entity.OrderInfo">
        select order_id AS ORDERID,
        payment AS PAYMENT,
        goods_name AS GOODS_NAME,
        payment_type AS PAYMENTTYPE,
        post_fee AS POSTFEE,
        status AS STATUS,
        create_time AS CREATETIME
        from tb_order_info
    </select>
</mapper>
4.2.3、编写单元测试用例并测试

1)我们这里查询的数据为,从第100001个下标开始,查询10条数据

2)代码如下所示:

题外话:

1)一般来说,我们封装的分页查询需要上送的参数是当前页和每页显示的条数,通过自己的计算,赋值给SQL语句需要的起始下标和查询的条数

  • TestPage
package com.iambest.study;
import	java.io.IOException;

import com.iambest.study.entity.OrderInfo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.Reader;
import java.util.List;
/**
 * 分页测试用例
 */
public class TestPage {
    @Test
    public void testPage() throws IOException{
        String config = "config/SqlMapConfig-insert.xml";
        Reader reader = Resources.getResourceAsReader(config);
        // 创建Builder对象
        SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
        // 创建Factory对象
        SqlSessionFactory factory = sfb.build(reader);
        // 通过factory对象生成session对象
        SqlSession session = factory.openSession();

        //起点坐标
        int offset = 100001;
        // 查询几个
        int limit = 10;

        RowBounds rowBounds = new RowBounds(offset, limit);
        List<OrderInfo> list = session.selectList("findAllOrderInfos",null,rowBounds);

        for (OrderInfo order: list) {
            System.out.println(order);
        }
    }
}
  • 执行单元测试用例,查看控制台的输出如下,表示成功:

在这里插入图片描述

5、使用Map作为返回的结果集

5.1、配置文件

1)我们在上文中所有的返回结果集都是一个实体对象

2)不过MyBatis也支持将返回的结果集封装成Map对象

3)对于常用的数据类型及集合框架中的几种类型,MyBatis封装了一些简写方式,我们配置的使用不需要再配置全称路径

  • 配置我们的sqlMapper文件OrderInfoMapper.xml,新增一个方法selectByOrderId
  • 内容如下:
   <select id="selectByOrderId" resultType="java.util.HashMap" parameterType="string">
        select * from tb_order_info where order_id=#{order_id}
   </select>

5.2、单元测试用例及测试

1) 我们编写单元测试,测试返回结果为Map

  • testMap
    @Test
    public void testMap() throws IOException {
        String config = "config/SqlMapConfig-insert.xml";
        Reader reader = Resources.getResourceAsReader(config);
        // 创建Builder对象
        SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
        // 创建Factory对象
        SqlSessionFactory factory = sfb.build(reader);
        // 通过factory对象生成session对象
        SqlSession session = factory.openSession();
        Map<String,Object> resultMap = session.selectOne("selectByOrderId","102000000");
        System.out.println(resultMap);
        System.out.println(resultMap.get("GOODS_NAME"));// 娶不到值,key为小写
        session.close();
    }
  • 运行单元测试,看控制台的输出,输出的结果为map,如下:

在这里插入图片描述

6、使用Mapper接口实现数据库操作

问题探讨:

​ 1)在上述的过程中,我们发现每次都是通过sqlSession对象来操作数据库实现CRUD的操作,非常的繁琐

​ 2)在MyBatis中还有另外一种方式,我们可以通过Mapper接口来实现数据库的操作

思路:

​ 1)编写一个Mapper接口,该Mapper接口和SqlMapper同名,并在SqlMapper中的命名空间指定

​ 2)在Mapper接口中编写方法,并且方法的名称和SqlMapper中的每个id的命名保持一致

​ 3)通过SqlSession提供的getMapper方法,来获取一个Mapper接口实例

​ 4)我们通过该接口实例及对应的方法来实现数据库的操作

6.1、编写Mapper接口

1)编写接口StudentInfoMapper文件

2)在StudentInfoMapper中一一编写对应sqlMapper.xml中的方法

3)sqlMapper.xml文件中指定命名空间为:com.iambest.study.dao.StudentInfoMapper

  • StudentInfoMapper
package com.iambest.study.dao;

import com.iambest.study.entity.StudentInfoDo;

import java.util.List;

/**
 * 数据库Dao层
 */
public interface StudentInfoMapper {

    /**
     * 登记学生信息
     * @param studentInfoDo
     */
    public void addStudentInfo(StudentInfoDo studentInfoDo);

    /**
     * 更新学生信息
     * @param studentInfoDo
     */
    public void updateById(StudentInfoDo studentInfoDo);

    /**
     * 根据ID删除
     * @param id
     */
    public void deleteById(String id);

    /**
     * 根据ID进行查询
     * @param id
     * @return 查询的数据实体
     */
    public StudentInfoDo selectById(String id);

    /**
     * 查询所有的记录
     * @return
     */
    public List<StudentInfoDo> findAll();
}

6.2、编写单元测试用例并测试

1)这里我们以findAll为示例,查询所有的记录信息,其他的大同小异,都是一样的处理逻辑

2)编写单元测试用例TestMapper

  • TestMapper
package com.iambest.study.mapper;

import com.iambest.study.dao.StudentInfoMapper;
import com.iambest.study.entity.StudentInfoDo;
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 org.junit.Test;

import java.io.IOException;
import java.io.Reader;
import java.util.List;

public class TestMapper {

    @Test
    public void testMapper() throws IOException {
        String config = "config/SqlMapConfig-insert.xml";
        Reader reader = Resources.getResourceAsReader(config);
        // 创建Builder对象
        SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
        // 创建Factory对象
        SqlSessionFactory factory = sfb.build(reader);
        // 通过factory对象生成session对象
        SqlSession session = factory.openSession();
        // 获取到Mapper接口对象
        StudentInfoMapper studentInfoMapper = session.getMapper(StudentInfoMapper.class);
        // 通过mapper接口对象的方法执行查询
        List<StudentInfoDo> lists = studentInfoMapper.findAll();
        for (StudentInfoDo entry : lists) {
            System.out.println(entry);
        }
        session.close();
    }
}
  • 运行单元测试,查看控制台的输出,如下图表示成功:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jack_David

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值