美文网首页
一:初步了解Mybatis

一:初步了解Mybatis

作者: 煎包小混沌 | 来源:发表于2020-04-11 16:48 被阅读0次

1:使用maven导入mybatis的依赖

1.0:使用idea创建一个maven项目
image.png
image.png
1.1:一个maven的空项目,目录大概这样
image.png
1.2:在pom.xml中导入mybatis的依赖,大概需要以下依赖
 <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--slf4j-api提供日志的api标准,不能直接打印-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.29</version>
        </dependency>
        <!--log4j-over-slf4j 提供 slf4j 与 log4j 直接的链接-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
            <scope>test</scope>
        </dependency>
        <!--log4j 日志-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!--测试依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

2:开始配置mybatis

2.0:创建测试数据库表
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `student_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '编号',
  `name` VARCHAR(20) DEFAULT NULL COMMENT '姓名',
  `phone` VARCHAR(20) DEFAULT NULL COMMENT '电话',
  `email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
  `sex` TINYINT(4) DEFAULT NULL COMMENT '性别',
  `locked` TINYINT(4) DEFAULT NULL COMMENT '状态(0:正常,1:锁定)',
  `gmt_created` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '存入数据库的时间',
  `gmt_modified` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改的时间',
  PRIMARY KEY (`student_id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='学生表';

这是根据上面的表,创建的实体类StudentModel,也可以采用mybatis逆向生成的方式生成,后面会讲到

package mybatis.entity;

import java.io.Serializable;
import java.util.Date;

public class StudentModel implements Serializable {
    /**
     * 编号
     */
    private Integer student_id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 电话
     */
    private String phone;

    /**
     * 邮箱
     */
    private String email;

    /**
     * 性别
     */
    private Byte sex;

    /**
     * 状态(0:正常,1:锁定)
     */
    private Byte locked;

    /**
     * 存入数据库的时间
     */
    private Date gmt_created;

    /**
     * 修改的时间
     */
    private Date gmt_modified;

    private static final long serialVersionUID = 1L;

    public Integer getStudent_id() {
        return student_id;
    }

    public void setStudent_id(Integer student_id) {
        this.student_id = student_id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone == null ? null : phone.trim();
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email == null ? null : email.trim();
    }

    public Byte getSex() {
        return sex;
    }

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

    public Byte getLocked() {
        return locked;
    }

    public void setLocked(Byte locked) {
        this.locked = locked;
    }

    public Date getGmt_created() {
        return gmt_created;
    }

    public void setGmt_created(Date gmt_created) {
        this.gmt_created = gmt_created;
    }

    public Date getGmt_modified() {
        return gmt_modified;
    }

    public void setGmt_modified(Date gmt_modified) {
        this.gmt_modified = gmt_modified;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", student_id=").append(student_id);
        sb.append(", name=").append(name);
        sb.append(", phone=").append(phone);
        sb.append(", email=").append(email);
        sb.append(", sex=").append(sex);
        sb.append(", locked=").append(locked);
        sb.append(", gmt_created=").append(gmt_created);
        sb.append(", gmt_modified=").append(gmt_modified);
        sb.append(", serialVersionUID=").append(serialVersionUID);
        sb.append("]");
        return sb.toString();
    }
}
2.1:接着需要创建mybatis的xml的配置文件,配置文件的一些属性可以参考https://mybatis.org/mybatis-3/zh/configuration.html#properties,当前的目录 image.png
配置文件mybatis.config.xml的内容

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--注意配置参数的顺序-->
<configuration>
    <!--引用外部的属性文件-->
    <properties resource="sql/jdbc.properties"></properties>
    <settings>
        <!--使mybatis打印出sql语句-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--对类的完全包名进行重命名:mybatis.entity.StudentModel -> StudentModel,后面直接使用 StudentModel 就可以了-->
    <typeAliases>
        <!--单个实体模式 和 包模式-->
        <!--<typeAlias alias="StudentModel" type="mybatis.entity.StudentModel"/>-->
        <package name="mybatis.entity"/>
    </typeAliases>
     <!--可以配置其他的环境,开发和发布等-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC">
                <property name="" value=""/>
            </transactionManager>
            <!--数据库的参数-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverClass}"/>
                <property name="url" value="${jdbc.connectionURL}"/>
                <property name="username" value="${jdbc.userId}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--映射文件的路径,可以是包路径也可以设置单个文件的路径-->
    <mappers>
        <mapper resource="myBatisMapper/StudentDao.xml"/>
    </mappers>
</configuration>
jdbc.properties文件内容
#mysql驱动的路径
jdbc.driverLocation=/Users/apple/Tomcat/apache-tomcat-9.0.14/webapps/ROOT/WEB-INF/lib/mysql-connector-java-5.1.6.jar
jdbc.driverClass=com.mysql.cj.jdbc.Driver
#修改为自己的数据库地址
jdbc.connectionURL=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&useSSL=false&useServerPrepStmts=true&cachePrepStmts=true
jdbc.userId=root
jdbc.password=*******
2.2:创建映射接口与映射文件StudentDao.xml
image.png

映射接口StudentDao

package mybatis.dao;

import mybatis.entity.StudentModel;

import java.util.List;

public interface StudentDao {
//    int deleteByPrimaryKey(Integer student_id);
//    单条数据插入
    int insert(StudentModel record);
//    批量插入
    int insertBatch(List<StudentModel> list);
//    校验参数插入
    int insertSelective(StudentModel record);
//
//    StudentModel selectByPrimaryKey(Integer student_id);
//
//    int updateByPrimaryKeySelective(StudentModel record);
//
//    int updateByPrimaryKey(StudentModel record);
}

特别注意:在<insert>语句中 insert into student 这里的 student 不能带有双引号 "student",因为后面采用mybatis逆向生成时自动增加的双引号,导致执行时报错

<?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="mybatis.dao.StudentDao">
   <!--定义一个返回类型的映射,这里的type原本应该是完整的包路径,但是在配置文件中使用了<typeAliases>,所以可以直接写成类名-->
  <resultMap id="BaseResultMap" type="StudentModel">
    <id column="student_id" jdbcType="INTEGER" property="student_id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="phone" jdbcType="VARCHAR" property="phone" />
    <result column="email" jdbcType="VARCHAR" property="email" />
    <result column="sex" jdbcType="TINYINT" property="sex" />
    <result column="locked" jdbcType="TINYINT" property="locked" />
    <result column="gmt_created" jdbcType="TIMESTAMP" property="gmt_created" />
    <result column="gmt_modified" jdbcType="TIMESTAMP" property="gmt_modified" />
  </resultMap>
  <!--定义sql语句使用的参数名称,后面引用 Base_Column_List 就可以使用里面的参数名称-->
  <sql id="Base_Column_List">
    student_id, name, phone, email, sex, locked, gmt_created, gmt_modified
  </sql>
  <sql id="insert_Column_List">
    name, phone,
    email, sex, locked,
    gmt_created, gmt_modified
  </sql>
  <!--单条数据插入 useGeneratedKeys="true" keyProperty="student_id" 插入并返回主键-->
  <insert id="insert" useGeneratedKeys="true" keyProperty="student_id" parameterType="StudentModel" >
    insert into student
    (<include refid="insert_Column_List"/>)
    values (#{name,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR},
    #{email,jdbcType=VARCHAR}, #{sex,jdbcType=TINYINT}, #{locked,jdbcType=TINYINT},
    #{gmt_created,jdbcType=TIMESTAMP}, #{gmt_modified,jdbcType=TIMESTAMP})
  </insert>
  <!--批量数据插入-->
  <insert id="insertBatch">
    insert into student (name, phone,
    email, sex, locked,
    gmt_created, gmt_modified)
    VALUES
    <foreach collection ="list" item="item" separator =",">
      (#{item.name,jdbcType=VARCHAR}, #{item.phone,jdbcType=VARCHAR},
      #{item.email,jdbcType=VARCHAR}, #{item.sex,jdbcType=TINYINT}, #{item.locked,jdbcType=TINYINT},
      #{item.gmt_created,jdbcType=TIMESTAMP}, #{item.gmt_modified,jdbcType=TIMESTAMP})
    </foreach >
  </insert>
  <!--prefix="(" suffix=")" suffixOverrides="," 指定字符串开头和截取最后,-->
  <insert id="insertSelective" useGeneratedKeys="true" keyProperty="student_id" parameterType="StudentModel">
    insert into student
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="name != null">
        name,
      </if>
      <if test="phone != null">
        phone,
      </if>
      <if test="email != null">
        email,
      </if>
      <if test="sex != null">
        sex,
      </if>
      <if test="true">
        locked,
      </if>
      <if test="gmt_created != null">
        gmt_created,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="phone != null">
        #{phone,jdbcType=VARCHAR},
      </if>
      <if test="email != null">
        #{email,jdbcType=VARCHAR},
      </if>
      <if test="sex != null">
        #{sex,jdbcType=TINYINT},
      </if>
      <if test="true">
        #{locked,jdbcType=TINYINT},
      </if>
      <if test="gmt_created != null">
        #{gmt_created,jdbcType=TIMESTAMP},
      </if>
    </trim>
  </insert>
</mapper>

3:开始使用mybatis,

3.1:创建mybatis的操作类,请参考https://mybatis.org/mybatis-3/zh/getting-started.html
image.png

这里采用单例模式,来保证 SqlSessionFactory 只被创建一次

package mybatis;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

//sqlSessionFactory 的单例模式
public class MyBatisSessionFactory {
    private SqlSessionFactory factory;
    /**
     * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
     * 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
     */
    private static class SingletonHolder {
        /**
        * 静态初始化器,由JVM来保证线程安全
        */
        private static MyBatisSessionFactory instance = new MyBatisSessionFactory();
    }
    /**
    * 私有化构造方法
    */
    private MyBatisSessionFactory() {
        // 通过配置文件创建 sqlSessionFactory 的实列,sqlSessionFactory 用来生成 sqlSession
        String resource = "myBatis/mybatis.config.xml";
        try {
            InputStream inputStream = Resources.getResourceAsStream(resource);
            factory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static  MyBatisSessionFactory getInstance(){
        return SingletonHolder.instance;
    }

    public SqlSessionFactory getFactory() {
        return factory;
    }
}
3.2:创建测试类,添加测试方法
package mybatis;

import mybatis.dao.StudentDao;
import mybatis.entity.StudentModel;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;

import org.slf4j.Logger;

public class MybatisTest {
    private static final Logger logger = LoggerFactory.getLogger(MybatisTest.class);
//    单条插入
    @Test
    public void insert() {
        long start = System.currentTimeMillis();
        SqlSession session = myBatisSessionFactory.getInstance().getFactory().openSession();
        StudentDao studentDaoMapper = session.getMapper(StudentDao.class);
        for (int i = 0; i < 500; i++) {
            StudentModel model = buildStudentModel(i);
            int result = studentDaoMapper.insert(model);
            logger.debug("插入 = " + String.valueOf(result) + ", student_id =" + model.getStudent_id());
        }
        // 提交
        session.commit();
        long end = System.currentTimeMillis();
        logger.info("时间----" +(end - start));
//        insertBatch();
    }
//    批量插入
    @Test
    public void insertBatch() {
        long start = System.currentTimeMillis();
        SqlSession session = myBatisSessionFactory.getInstance().getFactory().openSession();
        StudentDao studentDaoMapper = session.getMapper(StudentDao.class);
        ArrayList<StudentModel> arrayList = new ArrayList<StudentModel>();
        for (int i = 0; i < 1500; i++) {
            StudentModel model = buildStudentModel(i);
            arrayList.add(model);
        }
        studentDaoMapper.insertBatch(arrayList);
        // 提交
        session.commit();
        long end = System.currentTimeMillis();
        logger.info("时间----" +(end - start));
    }
//    判断插入值为空,则不插入此值
    @Test
    public void insertSelective() {
        SqlSession session = myBatisSessionFactory.getInstance().getFactory().openSession();
        StudentDao studentDaoMapper = session.getMapper(StudentDao.class);
        StudentModel model = buildStudentModel(0);
        int result =  studentDaoMapper.insertSelective(model);
        logger.info("插入 = " + String.valueOf(result) + ", student_id =" + model.getStudent_id());
        // 提交
        session.commit();
    }
    static double phone = 10000000000.f;
    static int name = 1;
    static int email = 1;
    private StudentModel buildStudentModel(int i) {
        StudentModel model = new StudentModel();
        model.setName("二天" + name);
        model.setPhone(String.valueOf(phone));
        model.setSex(Byte.parseByte("1"));
        model.setEmail("email" + email);
        model.setGmt_created(new Date());
        model.setStudent_id(1);
        return model;
    }
}

测试打印

Reader entry: ����1�
Checking to see if class mybatis.entity.StudentModel matches criteria [is assignable to Object]
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 351877391.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@14f9390f]
==>  Preparing: insert into student ( name, phone, email, sex, locked, gmt_created, gmt_modified ) values (?, ?, ?, ?, ?, ?, ?) 
==> Parameters: 二天1(String), 1.0E10(String), email1(String), 1(Byte), null, 2020-04-11 16:44:43.363(Timestamp), null
<==    Updates: 1
Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@14f9390f]
四月 11, 2020 4:44:43 下午 mybatis.MybatisTest insert
信息: 循环插入时间----872

测试大量数据插入的有效方法

1500条数据插入的对比
四月 11, 2020 4:48:25 下午 mybatis.MybatisTest insert
信息: 循环插入时间----1827
四月 11, 2020 4:48:25 下午 mybatis.MybatisTest insertBatch
信息: 批量插入时间----418

参考的文章:
https://mybatis.org/mybatis-3/zh/getting-started.html
https://www.cnblogs.com/homejim/p/9613205.html
https://www.cnblogs.com/huangjinyong/p/11209753.html

相关文章

网友评论

      本文标题:一:初步了解Mybatis

      本文链接:https://www.haomeiwen.com/subject/ftvymhtx.html