[Mybatis from entry to actual combat tutorial] Chapter 1 Introduction to Mybatis

1. Getting started with Mybatis

1.1 What is MyBatis

    MyBatis was originally iBatis, an open source project of Apache. In 2010, the project was migrated from Apache Software Foundation to Google Code and renamed MyBatis. Migrated to Github in November 2013.
    
    The word iBATIS comes from the combination of "internet" and "abatis", which is a Java-based persistence layer framework. The persistence layer framework provided by iBATIS includes SQL Maps and Data Access Objects (DAOs).

    A software framework (software framework) usually refers to a software component specification to implement a certain industry standard or complete a specific basic task, and also refers to a software product that provides the basic functions required by the specification in order to implement a certain software component specification. It can be simply understood that the framework is a semi-finished project, and we can develop projects based on the framework to improve development efficiency. Internet companies now put efficiency first. If the development cycle is too long, similar products may appear in the market soon, and the opportunity will be lost.
    
    Currently, the latest version is MyBatis 3.5.9, and its release date is December 26, 2021.
    
    MyBatis is an excellent persistence layer framework. It encapsulates the process of JDBC to operate the database, so that developers only need to pay attention to SQL itself, without spending energy on processing such as registering drivers, creating connections, creating statements, manually setting parameters, and results. JDBC complex process code such as set retrieval.
    
    MyBatis configures various statements to be executed through xml files or annotations, and generates the final executed sql statement through mapping between Java objects and the dynamic parameters of sql in the statement, and finally the mybatis framework executes sql and maps the results into Java objects and return.

1.2 Advantages of MyBatis

    Easy to learn: itself is small and simple. Without any third-party dependencies, the simplest installation only needs two jar files + configuration of several sql mapping files. Easy to learn, easy to use. Through the documentation and source code, you can fully grasp its design ideas and implementation.

    Flexible: Mybatis does not impose any impact on the existing design of the application or database. SQL is written in xml, which is convenient for unified management and optimization. All requirements for operating the database can be met through sql statements.

    Uncoupling sql and program code: By providing a DAO layer, business logic and data access logic are separated, making the system design clearer, easier to maintain, and easier to unit test. The separation of sql and code improves maintainability.

    Provides mapping tags and supports ORM field relationship mapping between objects and databases.

    Object-relational mapping tags are provided to support object-relational building and maintenance.

    Provide xml tags and support writing dynamic sql.

1.3 Problems in JDBC programming

    In the actual development process, we generally use the ORM framework to replace the traditional JDBC, such as Mybatis or Hibernate, but JDBC is the basis for Java to achieve data access, mastering it is very helpful for us to understand the data operation process of Java.

    ORM: Object Relational Mapping (ORM) mode is a technology to solve the mismatch between object-oriented and relational databases. Simply put, ORM automatically persists the objects in the program to the relational database by using the metadata describing the mapping between the object and the database.

    Typical ORM middleware for Java include: Hibernate, Mybatis, speedframework.

    ORM technical features:
        1. Improved development efficiency. Since ORM can automatically map fields and attributes between Entity objects and Tables in the database, we may not actually need a dedicated and huge data access layer. 

        2. ORM provides a mapping to the database, without directly coding with sql, and can obtain data from the database like an operation object. 

    Then why do we use some ORM frameworks instead of traditional JDBC in actual development? Next, let's take a look at a simple implementation of a JDBC program and analyze its shortcomings, as follows:

1.3.1 JDBC program

@Override
public void insertUser(User user) {
    Connection conn = DBUtil.getConnection();
    PreparedStatement stmt = null;
    String sql = "insert into sys_user(NAME,ACCT,PWD,CRTIME,UPTIME) values(?,?,?,now(),now())";
    try {
        stmt = conn.prepareStatement(sql);
        stmt.setString(1, user.getName());
        stmt.setString(2, user.getAcct());
        stmt.setString(3, user.getPwd());
        stmt.executeUpdate();
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        DBUtil.closeAll(conn, stmt, null);
    }
}

1.3.2 JDBC programming steps

    1. Load the database driver;

    2. Create and obtain the database connection Connection;

    3. Create a PreparedStatement object that executes the SQL statement;

    4. Set the placeholder parameters in the SQL statement;

    5. Execute Sql through PreparedStatement and get the result set;

    6. Analyze and process the Sql execution results;

    7. Release resources (Connection, Preparedstatement, ResultSet).

1.3.3 JDBC problems are summarized as follows

From the above procedures, the summary is as follows:

    1. The database connection is created when it is used, and released immediately when it is not in use, so that the database is frequently operated, resulting in waste of resources and affecting performance; optimization idea: use the database
        connection pool to manage database objects;

    2. sql is hard-coded into the Java program. If you change sql, you have to recompile the Java code, which is not conducive to the maintenance of the system in the later stage; optimization idea: configure the sql statement
        in xml, even if you change the sql, you don’t need to recompile the source code ;

    3. Setting parameters to PreparedStatement is also hard-coded into the Java program, which is not conducive to later maintenance;
        optimization idea: all the sql statements, placeholders and parameters are configured in xml, and the source code does not need to be recompiled for changes;

    4. When traversing the result set data from the resultset, there is also hard coding, which is not conducive to the maintenance of the later system;
        optimization idea: automatically map the query result set into a Java object;

    In response to the above problems, many solutions to optimize JDBC have naturally appeared, that is, the ORM persistence layer framework that appeared later, such as Mybatis and Hibernate, etc.; this is why ORM frameworks are preferred in actual development. up.
    
    With this concept, then we will start to learn about Mybatis...

    NOTE: Hardcoding is the software development practice of embedding data directly into the source code of a program or other executable object, as opposed to obtaining data externally or generating it at runtime. Hardcoded data can usually only be modified by editing the source code and recompiling the executable.

1.4 MyBatis Architecture

    1. MyBatis configuration:
        mybatis-config.xml (the name is not fixed), this file is used as the global (core) configuration file of MyBatis, and configures the operating environment of MyBatis and other information.
        The mapper.xml file is the Sql mapping file, and the Sql statement for operating the database is configured in the file. This file needs to be loaded in mybatis-config.xml.

    2. Construct SqlSessionFactory, that is, the session factory, through configuration information such as the MyBatis environment.

    3. The SqlSession is created by the session factory, that is, the session, and the operation of the database needs to be performed through the SqlSession.

    4. The bottom layer of MyBatis customizes the Executor interface to operate the database. The Executor interface has two implementations, one is the basic executor and the other is the cache executor.

    5. MappedStatement is also an underlying encapsulation object of MyBatis. Mybatis loads SQL configuration information into MappedStatement objects (including incoming parameter mapping configuration, executed SQL statement, and result mapping configuration) and stores them in memory. A Sql in the mapper.xml file corresponds to a MappedStatement object, and the id of the Sql is the id of the MappedStatement.

    6. MappedStatement defines the input parameters for Sql execution, including HashMap, basic type, string type, and entity class type. Executor maps the input Java object to Sql through MappedStatement before executing Sql. The input parameter mapping is JDBC programming. PreparedStatement sets parameters.

    7. MappedStatement defines the output results of Sql execution, including HashMap, basic types, string types, and entity class types. Executor maps the output results to Java objects after executing SQL through MappedStatement. The output result mapping process is equivalent to JDBC programming. The process of parsing the results.

Principle analysis:

    1. Load configuration: The configuration comes from two places, one is the configuration file, the other is the annotation of the Java code, and the SQL configuration information is loaded into each MappedStatement object (including the incoming parameter mapping configuration and the executed SQL statement , result mapping configuration), stored in memory.

    2. SQL parsing: When the API interface layer receives a call request, it will receive the ID of the incoming SQL and the incoming object (which can be a Map, JavaBean or basic data type), and Mybatis will find the corresponding MappedStatement according to the ID of the SQL. Then the MappedStatement is parsed according to the incoming parameter object, and the final SQL statement and parameters to be executed can be obtained after parsing.

    3. SQL execution: take the final SQL and parameters to the database for execution, and obtain the result of operating the database.

    4. Result mapping: convert the result of operating the database according to the mapping configuration, which can be converted into HashMap, JavaBean or basic data type, and return the final result.

1.5 Build MyBatis project

1.5.1 Create a Java project

    MyBatis is a persistence layer framework, which is used when operating the database. There is no need to create a JavaWEB project, just create a Maven Java project.

1.5.2 Import MyBatis framework jar package

    The code of Mybaits is managed by github.com, download address: https://github.com/mybatis/mybatis-3/releases

mybatis directory structure:

    lib -> mybatis accessory toolkit

    LICENSE -> License

    mybatis-3.4.6.jar -> mybatis core package
    
    mybatis-3.4.6.pdf -> mybatis manual

    NOTICE -> Legal notice

Method 1: Import the jar package

    mybatis-3.4.6.jar is the core jar package and must be imported.
    
    The jar package in the lib directory is a toolkit, which is optional. We generally introduce log4j as the mybatis log output component.

    The driver package of mysql or oracle database must be imported.  

Method 2: maven dependency configuration

<dependencies>
    <!-- mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
    <!-- oracle:大家在引入oracle依赖的时候肯定出错 -->
    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc6</artifactId>
        <version>11.2.0.1.0</version>
    </dependency>
    <!--  mysql -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.49</version>
    </dependency>
    <!-- log4j Mybatis的日志输出组件 -->
    <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>

    Oracle relies on error resolution: https://blog.csdn.net/qq_38000902/article/details/82759268

    There is ojdbc6.jar in the oracle installation directory: D:\Tools\product\11.2.0\dbhome_1\jdbc\lib (my path)

    Mybatis uses log4j as the output log information by default, and you can also import log4j related files.

1.5.3 Write the global configuration file in MyBatis

    Create mybatis-config.xml in the src/main/resources directory, function: configure the MyBatis operating environment such as data sources, transactions, etc.

    Note: If there is no resources directory under src/main, then we manually create one and make it Resources Root.

<?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 文件的根节点 -->
<configuration>
    <!--
      properties 用于引入外部的properties配置文件
      resource:引入类路径下的文件
      url:引入磁盘或网路
     -->
    <properties/>

    <!-- environments:多个配置环境;通过default属性可以对多个环境快速切换 -->
    <!-- environments default属性的值必须和某个environment的id值一致 -->
    <!-- 和spring整合后 environments配置将废除,了解即可 -->
    <environments default="mysql">
        <environment id="oracle">
            <!-- 配置事务:使用jdbc的事务管理 -->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源:连接数据库的信息
                type: 表示连接是否使用连接池,POOLED表示mybatis中自带的连接池
    JNDI、POOLED、UNPOOLED
             -->
            <dataSource type="POOLED">
                <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
                <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
                <property name="username" value="scott"/>
                <property name="password" value="tiger"/>
            </dataSource>
        </environment>
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&amp;useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

MyBatis configuration file reports an error:

    When writing an xml configuration file to introduce DTD constraints, this error may appear indicating that URI is not registered (Settings | Languages ​​& Frameworks | Schemas and DTDs). At this time, use the shortcut key to select the Fetch external resource or Ignore external resource option.

    Or directly add the problematic path in settings -> languages&frameworks -> schemas and dtds.

1.5.4 Database SQL

CREATE TABLE `dept`  (
  `deptno` int PRIMARY KEY AUTO_INCREMENT,
  `dname` varchar(20),
  `loc` varchar(40)
);

INSERT INTO `dept` VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO `dept` VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO `dept` VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO `dept` VALUES (40, 'OPERATIONS', 'BOSTON');

CREATE TABLE `emp`  (
  `empno` int PRIMARY KEY AUTO_INCREMENT,
  `ename` varchar(20),
  `job` varchar(20),
  `mgr` int,
  `hiredate` date,
  `sal` double,
  `comm` double,
  `deptno` int,
  CONSTRAINT `FK_EMP_DEPTNO` FOREIGN KEY (`deptno`) REFERENCES `dept` (`deptno`)
);

INSERT INTO `emp` VALUES (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 1300, NULL, 20);
INSERT INTO `emp` VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 2100, 300, 30);
INSERT INTO `emp` VALUES (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1750, 500, 30);
INSERT INTO `emp` VALUES (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 3475, NULL, 20);
INSERT INTO `emp` VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1750, 1400, 30);
INSERT INTO `emp` VALUES (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 3350, NULL, 30);
INSERT INTO `emp` VALUES (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2950, NULL, 10);
INSERT INTO `emp` VALUES (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3500, NULL, 20);
INSERT INTO `emp` VALUES (7839, 'KING', 'PRESIDENT', NULL, '1981-11-17', 5500, NULL, 10);
INSERT INTO `emp` VALUES (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 2000, 0, 30);
INSERT INTO `emp` VALUES (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1600, NULL, 20);
INSERT INTO `emp` VALUES (7900, 'JAMES', 'CLERK', 7698, '0198-12-31', 1450, NULL, 30);
INSERT INTO `emp` VALUES (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3500, NULL, 20);
INSERT INTO `emp` VALUES (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1800, NULL, 10);

1.5.5 Writing Entity Classes

    The entity class is used as Mybatis for sql mapping. The entity class usually corresponds to the database table. Emp.java is as follows:

    Note: Entity classes are used to correspond to database tables, we'd better use all reference types.

package com.newcapec.entity;

import java.util.Date;

public class Emp {

    private Integer empno;
    private String ename;
    private String job;
    private Integer mgr;
    private Date hiredate;
    private Double sal;
    private Double comm;
    private Integer deptno;

    public Integer getEmpno() {
        return empno;
    }

    public void setEmpno(Integer empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public Integer getMgr() {
        return mgr;
    }

    public void setMgr(Integer mgr) {
        this.mgr = mgr;
    }

    public Date getHiredate() {
        return hiredate;
    }

    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }

    public Double getSal() {
        return sal;
    }

    public void setSal(Double sal) {
        this.sal = sal;
    }

    public Double getComm() {
        return comm;
    }

    public void setComm(Double comm) {
        this.comm = comm;
    }

    public Integer getDeptno() {
        return deptno;
    }

    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }

    @Override
    public String toString() {
        return "Emp{" +
            "empno=" + empno +
            ", ename='" + ename + '\'' +
            ", job='" + job + '\'' +
            ", mgr=" + mgr +
            ", hiredate=" + hiredate +
            ", sal=" + sal +
            ", comm=" + comm +
            ", deptno=" + deptno +
            '}';
    }
}

1.5.6 Writing a mapping file

    Create a mapper directory under src/main/resources, and create a sql mapping file Emp.xml in this directory.

<?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">
<!--
    namespace: 命名空间,作用是mapper文件进行分类管理,用于隔离sql语句。
    注意:如果使用mapper代理的方式进行开发,namespace有特殊的作用。
-->
<mapper namespace="emp">
    <!-- 在映射文件中编写sql语句 -->
    <!-- 通过员工编号查询员工信息 -->
    <!--
        通过<select>标签编写查询语句
        id: 映射文件中SQL语句的唯一标识
             mybatis会将SQL语句封装到MappedStatement对象中,所以此处的id也可以标识MappedStatement对象的id
             注意:同一个mapper文件中id不能重复,而且id在mapper代理模式下有着重要作用
        parameterType: 输入参数的类型
            sql语句的占位符:#{}
            #{empno}:其中empno表示接收输入的参数值,参数名称为empno
			但是如果参数的类型为简单类型(基本数据类型、包装类、字符串类型),参数名称可以任意指定
		resultType: 输出参数的类型
			需要指定输出数据为Java中的数据类型(实体类的全限定名)
    -->
    <select id="selectById" parameterType="java.lang.Integer" resultType="com.newcapec.entity.Emp">
        select empno,ename,job,hiredate,mgr,sal,comm,deptno from emp where empno=#{empno}
    </select>
</mapper>

1.5.7 Loading the mapping file

    Add the mapping file location in the global configuration file of MyBatis.

<!-- 加载映射文件的位置 -->
<mappers>
    <mapper resource="mapper/Emp.xml"/>
</mappers>

1.5.8 log4j configuration

    Mybatis log output: log4j.properties configuration file.

#井号表示注释,配置内容为键值对格式,每行只能有一个键值对,键值对之间以=连接
#指定logger
#设定log4j的日志级别和输出的目的地
#INFO日志级别 ,Console和logfile输出的目的地
#等级 OFF,ERROR,WARN,INFO,DEBUG,TRACE,ALL
log4j.rootLogger=DEBUG,Console

#指定appender
#设定Logger的Console,其中Console为自定义名称,类型为控制台输出
log4j.appender.Console=org.apache.log4j.ConsoleAppender

#设定Logger的logfile,其中logfile为自定义名称,类型为文件
#org.apache.log4j.FileAppender文件
#org.apache.log4j.RollingFileAppender文件大小到达指定尺寸后产生一个新的文件
#org.apache.log4j.DailyRollingFileAppender每天产生一个日志文件
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
#设定文件的输出路径
log4j.appender.logfile.File=d:/log/test.log
#设定文件最大尺寸  单位可以使KB,MB,GB
log4j.appender.logfile.MaxFileSize=2048KB

#输出格式
#设定appender布局Layout
#   %d 输出日志的日期和时间,指定格式:%d{yyyy-MM-dd HH:mm:ss SSS}
#   %p 输出的日志级别
#   %c 输出所属类的全类名
#   %M 方法名
#   %m 输出代码中指定消息
#   %n 一个换行符
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d %p %c.%M() --%m%n
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p %c.%M() --%m%n

1.5.9 Writing test programs

    It is recommended to use Junit unit tests.

package com.newcapec;

import com.newcapec.entity.Emp;
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.InputStream;

/**
 * 测试程序
 */
public class MybatisTest {

    @Test
    public void test() throws IOException {
        //1.创建读取全局配置文件的流
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");

        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

        //2.通过配置文件流创建会话工厂
        SqlSessionFactory factory = builder.build(in);

        //3.通过会话工厂创建会话对象(SqlSession)
        SqlSession session = factory.openSession();

        //4.通过会话对象操作数据
        /**
         * 查询单条记录
         * selectOne(String statementId, Object param)
         * 参数1:映射文件中的statementId,命名空间名.statementId
         * 参数2:向sql语句中传入的数据,注意:传入的数据类型必须与映射文件中配置的parameterType保持一致
         * 返回值:就是映射文件中配置的resultType的类型
         * 查询多条记录
         * selectList()
         */
        Emp emp = session.selectOne("emp.selectById", 7369);
        System.out.println(emp);
        //5.关闭资源
        session.close();
    }
}

1.6 Basic operation of adding, deleting, modifying and checking

    Realize the following functions:
        query all employee information

        add staff

        update staff

        delete employee

        Fuzzy query based on employee name

1.6.1 Query operation

mapper file:

<!--
	查询到数据返回多条记录,每一条封装在一个实体类对象中,所有的实体类对象封装在List集合中
	resultType:指定的并不是集合的类型,而是单条数据所对应实体类类型
	resultType="java.util.List" 错误的配置方式
-->
<select id="select" resultType="com.newcapec.entity.Emp">
    select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp order by empno desc
</select>

Java code:

public class CURDTest {

    @Test
    public void testSelect() throws IOException {
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        SqlSession session = factory.openSession();

        /**
         * 查询多条记录
         * selectList(statement-sql语句的id, parameter-参数)
         * 表示将单条记录都存储输出映射对象中,每条记录的映射对象存放在List集合中
         */
        List<Emp> list = session.selectList("emp.select");
        for (Emp emp : list) {
            System.out.println(emp);
        }
        session.close();
    }
}

1.6.2 New operation

mapper file:

<!--
	添加操作使用insert标签
	增删改操作没有resultType,只有查询有resultType;
	因为增删改操作返回值都是int类型,所以我们不需要指明

	注意:给占位符赋值,#{}中编写的内容为实体类型参数中的成员变量名称
		#{empno}    Mybatis会从传递过来的参数对象里面得到emono字段的值
-->
<insert id="insert" parameterType="com.newcapec.entity.Emp">
    insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
    values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
</insert>

Java code:

@Test
public void testInsert() throws IOException {
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
    SqlSession session = factory.openSession();

    Emp emp = new Emp();
    emp.setEname("TOM");
    emp.setJob("CLARK");
    emp.setMgr(1);
    emp.setHiredate(new Date());
    emp.setSal(6500.0);
    emp.setComm(1200.0);

    System.out.println("新增之前的主键值为:" + emp.getEmpno());
    
    int result = session.insert("emp.insert", emp);
    
    System.out.println("影响数据库的条数为:" + result);
    /**
     * mybatis中的事务是jdbc的事务机制,mybatis里面默认是手动提交
     */
    session.commit();
    
    System.out.println("新增之后的主键值为:" + emp.getEmpno());

    session.close();
}

The primary key of the inserted data returns:

  • select last_insert_id(), which means to get the primary key value of the record just inserted, which is applicable to the database with self-increasing primary key;

  • select seq_demo.nextval from dual, which means to get the value generated by the next sequence, which is suitable for databases with sequences;

  • keyProperty: Set the query to the primary key value to which attribute of the object specified by parameterType;

  • order: the execution order of the Sql statement in the selectKey tag relative to the insert statement;

  • resultType: Specify the result type of the Sql statement in the selectKey tag;

Oracle database:

<insert id="insert" parameterType="com.newcapec.entity.Emp">
    <selectKey resultType="java.lang.Integer" keyProperty="empno" order="BEFORE">
        select seq_demo.nextval from dual
    </selectKey>
    insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
    values(#{empno},#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
</insert>

MySQL database:

<insert id="insert" parameterType="com.newcapec.entity.Emp">
    <selectKey resultType="java.lang.Integer" keyProperty="empno" order="AFTER">
        select last_insert_id()
    </selectKey>
    insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
    values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
</insert>

If it is a primary key self-incrementing database (MySQL), you can also use:

  • useGeneratedKeys: Whether to enable primary key return, false is not enabled by default;

  • keyProperty: Which member variable of the entity class is stored in the obtained primary key value;

<insert id="insert" parameterType="com.newcapec.entity.Emp" useGeneratedKeys="true" keyProperty="empno">
    insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
    values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
</insert>

1.6.3 Modify operation

mapper file:

<update id="update" parameterType="com.newcapec.entity.Emp">
    update emp set ename=#{ename},job=#{job},mgr=#{mgr},hiredate=#{hiredate},sal=#{sal},comm=#{comm},deptno=#{deptno} where empno=#{empno}
</update>

Java code:

@Test
public void testUpdate() throws IOException {
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
    SqlSession session = factory.openSession();

    Emp emp = new Emp();
    emp.setEmpno(7936);
    emp.setEname("JERRY");
    emp.setJob("MANAGER");
    emp.setMgr(7698);
    emp.setHiredate(new Date(new Date().getTime() + 1000*60*60*24));
    emp.setSal(7800.0);
    emp.setComm(800.0);

    int result = session.update("emp.update", emp);
    System.out.println("影响数据库的条数为:" + result);
    
    session.commit();

    session.close();
}

1.6.4 Delete operation

mapper file:

<delete id="delete" parameterType="java.lang.Integer">
    delete from emp where empno=#{empno}
</delete>

Java code:

@Test
public void testDelete() throws IOException {
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
    SqlSession session = factory.openSession();

    int result = session.delete("emp.delete", 7935);
    System.out.println("影响数据库的条数为:" + result);

    session.commit();

    session.close();
}

1.6.5 Fuzzy query

mapper file:

<!--
	条件查询:模糊查询
    1、#{}占位符,防止sql注入
    需要在Java中将传入数据的前后拼接%符号
    where ename like #{ename}
    
	2、使用字符串拼接函数
    where ename like concat('%',#{ename},'%')

    3、${}拼接符号,实现sql的拼接
    where ename like '%${value}%'
    注意:${}不是占位符,如果输入参数为简单类型,${}中的内容必须为value
-->
<select id="selectByEname1" parameterType="java.lang.String" resultType="com.newcapec.entity.Emp">
    select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
    where ename like #{ename}
</select>

Java code:

@Test
public void testSelectByEname() throws IOException {
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
    SqlSession session = factory.openSession();
    String ename = "S";
    List<Emp> list = session.selectList("emp.selectByEname1", "%"+ename+"%");
    for (Emp emp : list) {
        System.out.println(emp);
    }
    session.close();
}

mapper file:

<select id="selectByEname2" parameterType="java.lang.String" resultType="com.newcapec.entity.Emp">
    select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
    where ename like concat('%',#{ename},'%')
</select>

Java code:

@Test
public void testSelectByEname2() throws IOException {
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
    SqlSession session = factory.openSession();
    String ename = "S";
    List<Emp> list = session.selectList("emp.selectByEname2", ename);
    for (Emp emp : list) {
        System.out.println(emp);
    }
    session.close();
}

mapper file:

<select id="selectByEname3" parameterType="java.lang.String" resultType="com.newcapec.entity.Emp">
    select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
    where ename like '%${value}%'
</select>

Java code:

@Test
public void testSelectByEname3() throws IOException {
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
    SqlSession session = factory.openSession();
    String ename = "S";
    List<Emp> list = session.selectList("emp.selectByEname3", ename);
    for (Emp emp : list) {
        System.out.println(emp);
    }
    session.close();
}

1.6.6 Summary

parameterType and resultType:

    parameterType: Specify the input parameter type, MyBatis obtains the parameter value from the input object through ognl and sets it in Sql;

    resultType: Specifies the output result type, and MyBatis maps a row of record data of the Sql query result to an object of the type specified by resultType;

#{} and ${}:

    #{} represents a placeholder symbol, #{} receives input parameters, the type can be simple type, entity class type, HashMap; #{}
    receives simple type, #{} can be written as value or other names;
    #{} receives Entity class object value, read the attribute value in the object through OGNL, and obtain the object attribute value through attribute.attribute.attribute...; ${} represents
  
    a splicing symbol, which will refer to Sql injection, so it is not recommended to use ${ };
    ${} receives input parameters, the type can be simple type, entity class type, HashMap;
    ${} receives simple type, ${} can only be written as value;
    ${} receives entity class object value, read through OGNL The attribute value in the object, get the attribute value of the object through attribute.attribute.attribute...;

selectOne和selectList:

    selectOne means querying a record for mapping;
    if you use selectOne, you can use selectList (there is only one object in the list);
    
    selectList means querying a list (multiple records) for mapping;
    if you use selectList to query multiple records, you cannot Use selectOne;
    if you use selectOne to report an error: org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4  

1.7 Difference between MyBatis and Hibernate

    Hibernate: is a standard ORM framework (object-relational mapping).
        The entry threshold is high, no need to program to write Sql, Sql statement is automatically generated, it is difficult to optimize and modify the sql statement; application
        scenario: applicable to small and medium-sized projects with little change in demand, such as: background management system, erp, crm, oa...;

    MyBatis: Focus on Sql itself, requiring programmers to write Sql statements themselves. Sql modification and optimization are more convenient;
        MyBatis is an incomplete ORM framework. Although programmers write Sql themselves, MyBatis can also implement mapping (input mapping, output mapping) ;
        Application scenario: Applicable and demanding projects, such as: Internet projects  

    The enterprise selects technology, takes low cost and high return as the principle of technology selection, and selects according to the technical strength of the project team.

    Mybatis is different from hibernate, it is not completely an ORM framework, because MyBatis requires programmers to write Sql statements themselves, but mybatis can flexibly configure the sql statements to be run through XML or annotations, and map java objects and sql statements to generate final execution sql, and finally map the results of sql execution to generate java objects.

    Mybatis has a low learning threshold and is easy to learn. Programmers can directly write native sql, which can strictly control sql execution performance and has high flexibility. It is very suitable for software development that does not require high requirements for relational data models, such as Internet software, enterprise operation software, etc. Because the requirements of this type of software change frequently, once the requirements change, the results are required to be output quickly. But the premise of flexibility is that mybatis cannot be database-independent. If you need to implement software that supports multiple databases, you need to customize multiple sets of sql mapping files, which is a heavy workload.

    Hibernate has strong object/relational mapping capabilities and good database independence. If you use hibernate to develop software with high requirements for relational models (such as customized software with fixed requirements), you can save a lot of code and improve efficiency. However, Hibernate has a high learning threshold and a higher threshold for proficiency, and how to design O/R mapping, how to trade off between performance and object model, and how to make good use of Hibernate requires strong experience and ability.

    In short, as long as a software architecture with good maintainability and scalability can be made according to the needs of employees in a limited resource environment, it is a good architecture, so the best framework is only suitable.

1.8 Mybatis solves the problem of JDBC programming

    1. The frequent creation and release of database links causes waste of system resources and affects system performance. If you use a database link pool, this problem can be solved.
        Solution: Configure the data link pool in mybatis-config.xml, and use the connection pool to manage the database link.

    2. Sql statements are written in the code, which makes the code difficult to maintain. The actual application of sql may change a lot, and the change of sql needs to change the java code.
        Solution: Configure the Sql statement in the XXXXmapper.xml file and separate it from the java code.

    3. It is troublesome to pass parameters to the SQL statement, because the where condition of the SQL statement is not necessarily certain, there may be more or less, and the placeholders need to correspond to the parameters one by one.
        Solution: Mybatis automatically maps java objects to sql statements, and defines the type of input parameters through the parameterType in the statement.

    4. It is troublesome to parse the result set. Changes in sql lead to changes in the parsing code, and it needs to be traversed before parsing. It is more convenient to parse the database records into pojo objects.
        Solution: Mybatis automatically maps the sql execution result to the java object, and defines the type of the output result through the resultType in the statement.

Guess you like

Origin blog.csdn.net/ligonglanyuan/article/details/124272162