MyBatis overview - add, delete, modify and check

1. Framework overview

1.1 What is a framework

Framework (Framework) is the reusable design of the whole or part of the system, expressed as a set of abstract components and the method of interaction between component instances. Another definition holds that a framework is an application skeleton that can be customized by application developers.
The former is defined from the aspect of application and the latter is given from the aspect of purpose. In short, a framework is actually a semi-finished product of a certain application, a set of components that you can choose to complete your own system. Simply put, it is to use the stage set up by others, and you will perform. Moreover, frameworks are generally mature, continuously upgraded software.

1.2 Problems to be solved by the framework

One of the most important problems to be solved by the framework is the problem of technology integration. In the J2EE framework, there are various technologies. Different software companies need to choose different technologies from J2EE, which makes the final application of software companies Relying on these technologies, the complexity and risk of the technology itself will directly impact the application, and the application is the core of a software enterprise and the key to competitiveness. Therefore, the design of the application itself and the specific implementation Decoupling .
In this way, the research and development of software companies will focus on the design of the application, rather than the specific technical implementation. The technical implementation is the underlying support of the application, and it should not directly affect the application.
The framework is generally in the middle layer between the low-level application platform (such as 12EE) and the high-level business logic .

1.3 The Importance of Layering in Software Development

The importance of the framework is that it implements some functions and can well moderate the low-level application platform and high-level business logic. In order to achieve "high cohesion, low cohesion" in software engineering. Divide the problem into separate solutions, easy to control, easy to extend, and easy to allocate resources. Our regular MVC software design idea is a good layered idea.

1.4 Common frameworks under layered development

Common JavaEE development frameworks:

  1. A framework for solving data persistence problems

MyBatis

MyBatis was originally an open source project of Apache Batis. In 2010, the project was migrated from Apache Software Foundation to Google Code and renamed MyBatis. Migrated to Github in November 2013.
The term iBATIS comes from the combination of "intemer and abatis", which is a Java-based persistence layer framework. The persistence layer framework provided by BATIS includes SQLMaps and DataAccess Objects (DAOs)
as the framework of the persistence layer, and a framework with a higher degree of encapsulation is Hibernate, but the popularity of this framework in China has declined due to various reasons. Now the company Development is also used less and less. It is also a trend to use Spring Data to achieve data persistence.

2. MVC framework to solve WEB layer problems

spring MVC

Spring MVC is a follow-up product of SpringFrameWork, which has been integrated into Sprng Web Flow. The Spring framework provides a full-featured MVC module for building web applications. Use Spring's pluggable MVC architecture, so that when using Spring for WEB development, you can choose to use Spring's SpringlVC framework or integrate other MVC development frameworks, such as Struts1 (generally not used now), Struts2, etc.

3. A framework for solving technology integration problems

spring framework

Spring Strut was created due to the complexity of software development. Sprina uses basic JavaBeans to do things that were previously only possible with EJBs. However, the use of Spring is not limited to server-side development. From the perspective of simplicity, testability and looseness, most Java applications can benefit from Spring.
Spring is a lightweight Inversion of Control (loC) and Aspect-Oriented (AOP) container framework.

2. Introduction to MyBatis

2.1 What is MyBatis?

MyBatis is an open source lightweight data persistence framework, an alternative to DBC and Hibernate

MyBatis, formerly known as Batis, was released by Clinton Begin in 2002. In 2010, it migrated from Apache to Google, and changed its name to MyBatis, and in 2013, it migrated to Github.

  • mybatis is an excellent java-based persistence layer framework. It encapsulates jdbc inside, so that developers only need to pay attention to the sql statement itself, instead of spending energy to deal with complicated processes such as loading drivers, creating connections, and creating statements.

  • Mybatis configures the various statements to be executed through xml or annotations, and generates the final executed sql statement through the mapping between the aa object and the dynamic parameters of sql in the statement. Finally, the mybatis framework executes sql and maps the results to java objects and return.

  • The ORM idea is used to solve the problem of entity and database mapping, and the db is encapsulated, which shields the underlying access details of dbcapi, so that we can complete the persistence operation of the database without dealing with jdbc api.

  • MyBatis supports customized SQL, stored procedures, and advanced mapping to establish a mapping relationship between entity classes and SQL statements. It is a semi-automatic ORM implementation.

Chinese official website of MyBatis: https://mybatis.org/mybatis-3/zh/index.html

2.2 Why use MyBatis?

The main purpose of MyBatis is to simplify JDBC operations and meet the requirements of high concurrency and high response

Analyze the above problems with JDBC:

1. Frequent creation and release of database links will waste system resources and affect system performance. If you use a database link pool, this problem can be solved. 2. Sql statements are hard-coded in the code, making the code difficult to maintain, and the actual application of sql may change a lot. SQL changes need to change java

code.

3. There is hard coding in using preparedStatement to pass parameters to the occupancy symbol, because the where condition of the sql statement is not necessarily possible

More or less, modifying sql also requires modifying the code, the system is not easy to maintain

4对结果集解析存在硬编码(查询列名),sql 变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。

再次回顾mybatis特点:

  1. mybatis内部封装了jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement等繁杂的过程。

  1. mybatis通过xml或注解的方式将要执行的各种statement 配置起来,并通过java对象和statement 中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。

  1. 采用ORM思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。

三、MyBatis入门案例

下面我们来用一个入门的案例,了解一下MyBatis的基本操作步骤和使用方法。

  1. 创建数据库和数据表

#创建表
CREATE TABLE user(
    uid int PRIMARY KEY AUTO_INCREMENT,
    uname VARCHAR(32),
    password VARCHAR(32),
    phone VARCHAR(11),
    address VARCHAR(64)
);


INSERT INTO user(uname,password,phone,address) VALUES('张三','666','18965423548','南阳');
INSERT INTO user(uname,password,phone,address) VALUES('李四','333','18754263548','许昌');
INSERT INTO user(uname,password,phone,address) VALUES('小美','123','18565234759','信阳');
  1. 创建一个Java项目并导入mybatis框架的jar包

在项目中创建一个lib文件夹放入mybatis框架的jar包,并导入项目中。
  1. 创建跟表对应的实体类。

在src中创建com.chen.bean包,然后创建User实体类
创建一个DelVO实体类里面放一个批量删除集合
package com.chen.bean;

import java.util.ArrayList;
import java.util.List;

public class DelVO {
    List<Integer> ids = new ArrayList<>();

    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }

    @Override
    public String toString() {
        return "DelVO{" +
                "ids=" + ids +
                '}';
    }
}
package com.chen.bean;

public class User {
    private Integer uid;
    private String uname;
    private String password;
    private String phone;
    private String address;

    public User() {
    }

    public User(Integer uid, String uname, String password, String phone, String address) {
        this.uid = uid;
        this.uname = uname;
        this.password = password;
        this.phone = phone;
        this.address = address;
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPhone() {
        return phone;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", uname='" + uname + '\'' +
                ", password='" + password + '\'' +
                ", phone='" + phone + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
  1. 创建针对表操作的接口类。

在src中创建com.chen.dao包,然后创建UserDao的接口,然后在接口中定义针对数据库的增删
改查等操作。
package com.chen.dao;

import com.chen.bean.User;

import java.util.List;

public interface UserDao {
    /**
     * 查询所有用户信息
     * @return
     */
    List<User> selectAll();

    /**
     * 根据id查询用户信息
     * @param uid
     * @return
     */
    User selectByuid(int uid);

   /**
     * 模糊查询
     * @return
     * @param s
     */
    List<User> seach(User user);

    /**
     * 添加用户信息
     * @param user
     * @return
     */
    int add(User user);

    /**
     * 删除用户信息
     * @param uid
     * @return
     */
    int delete(int uid);

    /**
     * 修改用户信息
     * @param user
     * @return
     */
    int update(User user);

    //根据deLVO类封装的id集合进行批量删除
    int deleteByIds(DelVO delVO);
}
  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">
<!--namespace是映射的dao接口-->
<mapper namespace="com.chen.dao.UserDao">

    <!--通过select标签进行查询
        id:映射接口的方法名
        parameterType:指定参数的类型(如果是集合类型只需要指定集合元素的类型即可)
        resultType:指定返回值的类型
    -->
    <select id="selectAll" resultType="com.chen.bean.User">
        select * from user;
    </select>

    <select id="selectByuid" parameterType="int" resultType="com.chen.bean.User">
        select * from user where uid=#{uid};
    </select>

    <insert id="add" parameterType="com.chen.bean.User">
        insert into user (uname,password,phone,address) values(#{uname},#{password},#{phone},#{address});
    </insert>

    <delete id="delete" parameterType="int">
        delete from user where uid = #{uid};
    </delete>

   <update id="update" parameterType="user">
        update user 
        <set>
            <if test="uname !=null and uname !=''">
                uname=#{uname},
            </if>
            <if test="phone !=null and phone !=''">
                phone=#{phone},
            </if>
            <if test="address !=null and address !=''">
                address=#{address},
            </if>
        </set>
        where uid = #{uid}
    </update>

<select id="seach" parameterType="user" resultType="user">
        select * from user
        <where>
            <if test="uname !=null and uname !=''">
                and uname like concat('%',#{uname},'%')
            </if>
            <if test="phone !=null and phone !=''">
                and phone like concat('%',#{phone},'%')
            </if>
            <if test="address !=null and address !=''">
                and address like concat('%',#{address},'%')
            </if>
        </where>
    </select>

  <!--foreach表示对集合进行你迭代
        collection:对象中的集合属性名称
        item:迭代时的临时变量名
        open:开始的字符
        close:结束的字符
        separator:分隔符
        要对delVO这个对象中的ids属性 进行迭代,跌出来的临时变量叫id
        然后配上开始结束、分隔符,把id的值输出进去
    -->
<delete id="deleteByIds" parameterType="delVO">
    delete from user where uid in
    <foreach collection="ids" item="id" open="(" close=")" separator=",">
        #{id}
    </foreach>
</delete>
</mapper>
  1. 在src目录中创建mybatis框架的核心配置文件。

在src中创建一个文件,命名为SqlMapConfig.xml,在该配置文件中配置连接数据库的参数。

jdbc.properties

log4j.properties

<?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="jdbc.properties"/>
    <!--配置mybatis的运行:日志的输出-->
    <settings>
        <setting name="logImpl" value="log4j"/>
    </settings>
    <!--给实体类起别名-->
    <typeAliases>
        <package name="com.chen.bean"/>
    </typeAliases>
     <!--配置环境信息===就是配置连接数据库的参数
        default:指定配置的环境信息的id,表示默认连接该环境
    -->
    <environments default="mysql">
        <environment id="mysql">
        <!--配置事务的处理方式:模式使用JDBC的事务处理-->
            <transactionManager type="JDBC"></transactionManager>
        <!--数据源的默认type设置为pooled,表示使用连接池-->
            <dataSource type="pooled">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
 <!--加载mapper配置文件-->
    <mappers>
        <package name="com.chen.dao"/>
    </mappers>
</configuration>

7.在测试类中进行测试

使用mybatis框架需要按照框架的步骤进行
@Before
前置通知, 在目标方法(切入点)执行之前执行。
value 属性绑定通知的切入点表达式,可以关联切入点声明,也可以直接设置切入点表达式
注意:如果在此回调方法中抛出异常,则目标方法不会再执行,会继续执行后置通知 -> 异常通知。

@After 后置通知, 在目标方法(切入点)执行之后执行
package com.chen.test;

import com.chen.bean.User;
import com.chen.dao.UserDao;
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.After;
import org.junit.Before;
import org.junit.Test;

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

public class UserTest {
    InputStream stream = null;
    SqlSessionFactoryBuilder builder = null;
    SqlSessionFactory factory = null;
    SqlSession sqlSession = null;
    UserDao userDao = null;

    @Before
    public void init() throws IOException {
        //1.创建字节输入流映射核心配置文件
        stream = Resources.getResourceAsStream("mybatis.xml");

        //2.创建 SqlSessionFactoryBuilder 对象 ---mybatis框架使用了建构者模式
        builder = new SqlSessionFactoryBuilder();

        //3.使用建构者模式创建工厂对象
        factory = builder.build(stream);

        //4.使用工厂对象获取sqlsession对象
        sqlSession = factory.openSession();

        //5.使用sqlsession对象创建userdao接口的代理对象
        userDao = sqlSession.getMapper(UserDao.class);
    }

    @Test
    public void select() throws IOException {
        List<User> userList = userDao.selectAll();
        for (User user : userList) {
            System.out.println(user);
        }
    }

    @Test
    public void selectByuid() throws IOException {
        User user = userDao.selectByuid(12);
        System.out.println(user);
    }

    @Test
    public void add() throws IOException {
        User user = new User();
        user.setUname("小美");
        user.setPassword("123");
        user.setPhone("13672834567");
        user.setAddress("信阳");
        int add = userDao.add(user);

        if (add > 0) {
            System.out.println("添加成功");
        } else {
            System.out.println("添加失败");
        }
    }

    @Test
    public void delete() throws IOException {
        int delete = userDao.delete(12);

//      int delete1 = sqlSession.delete("delete",15);
        if (delete > 0) {
            System.out.println("删除成功");
        } else {
            System.out.println("删除失败");
        }
    }

   @Test
    public void testseach() {
        User seach = new User();
        seach.setAddress("信阳");
        
        List<User> userList = userDao.seach(seach);
        for (User user : userList) {
            System.out.println(user);
        }
    }

  @Test
    public void testdelete() {
        List<Integer> ids = new ArrayList<>();
        ids.add(4);
        ids.add(5);
        ids.add(6);
        ids.add(7);

        DelVO delVO = new DelVO();
        delVO.setIds(ids);
        userDao.deleteByIds(delVO);

    }

    @After
    public void distroy() throws IOException {
        sqlSession.commit();
        sqlSession.close();
        stream.close();
    }
}

运行结果如下:

查询所有用户信息:

根据id查询用户信息:

根据姓名模糊查询:

添加用户信息:

删除用户信息:

修改用户信息:

批量删除:

删除17、18、19

四、MyBatis核心对象

从上面的案例中我们可以发现MyBatis一些核心要素:

  • 核心接口和类

  • MyBatis核心配置文件(SqlMapConfigxml)

  • SQL映射文件(xxmapper.xml)

下面首先介绍MyBatis的核心接口和类,如下所示。

每个MyBatis应用程序都以一个SqlSessionFactory对象的实例为核心。

  • 首先获取SqlSessionFactoryBuilder对象,可以根据XML配置文件或者Configuration类的实例构建该对象。

  • 然后获取SqlSessionFactory对象,该对象实例可以通过SqlSessionFactoryBuilder 对象来获取。

  • 有了SalSessionFactory对象之后,就可以进而获取 SqSession 实例。SalSession 对象中完全包含以数据库为背景的所有执行SQL操作的方法,用该实例可以直接执行已映射的SOL语句。

4.1 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 会根据配置信息或者代码生成SqlSessionFactory,并且提供了多个build()方法重载。

配置信息可以以三种形式提供给SqlSessionFactoryBuilder的 build0 方法分别是nputStream(字节流)、Reader (字符流)、Configuration (类)。

由于字节流和字符流都属于读取配置文件的方式,所以就很容易想到构建一个SSessionFactory有两种方式,即:读取XML配置文件和编写代码。
一般习惯为采取XML配置文件的方式来构造SalSessionFactory,这样一方面可以避免硬编码另一方面方便日后配置人员修改,避免重复编译代码。

SqlSessionFactoryBuilder的生命周期和作用域

SqlSessionFactoryBuilder 的最大特点就是用过即丢。创建SqlSessionFactory对象之后,这个类就不存在了,因此SqlSessionFactoryBuilder的最佳范围就是存在于方法体内,也就是局部变量。

4.2 SqlSessionFactory

SqlSessionFactory是工厂接口而不是现实类,他的任务就是创建 SqlSession。所有的 MyBatis 应用都以 SqSessionFactory 实例为中心,SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 对象来获取。有了它以后就可以通过 SqlSession 提供的openSession()方法来获取SqlSession实例。

SqlSessionFactory的生命周期和作用域

SqlSessionFactory对象一旦创建,就会在整个应用程序过程中始终存在,没有理由去销毁或再创建它,并且在应用程序运行中也不建议多次创建 SqlSessionFactory。因此 SqSessionFactory的最佳作用域是Application,即随着应用程序的生命周期-一直存在这种存在于整个应用运行期间,并且只存在一个对象实例”的模式就是所谓的单例模式。

4.3 SqlSession

SqlSession 是用于执行持久化操作的对象,类似于DBC 中的Connection。它提供了面向数据库执行 SQL命令所需的所有方法,可以通过SqlSession实例直接运行已映射的SQL语句。

SglSession的用途主要有两种

1.获取映射器。让映射器通过命名空间和方法名称找到对应的SQL,并发送给数据库,执行后返回结果。

2.直接通过“命名空间(namespace)+SQLid”的方式执行SQL,不需要获取映射器

SqlSession生命周期和作用域。

SqlSession生命周期和作用域

SqlSession 对应一次数据库会话。由于数据库会话不是永久的,因此SqlSession 的生命周期也不是永久的,每次访问数据库时都需要创建SqlSession对象。

需要注意的是:每个线程都有自己的 SqlSession 实例,qSesion 实例不能被共享,也不是线程安全的。因此 SqlSession 的作用域范围是request作用域或方法体作用域内。

Guess you like

Origin blog.csdn.net/weixin_67224308/article/details/129395760