Mybatis入门看这一篇就够了

学Mybatis,入门看这一篇就够你学的了! 首先什么是MyBatis? MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。是一个基于Java的持久层框架 基本概念你总得给摸清楚 为什么我们要用Mybatis? 无论是Mybatis、Hibernate都是ORM的一种实现框架,都是对JDBC的一种封装! 本人在这里整理了20多家公司的面试题,以及各种关于Spring、Spring boot、Spring 阅读详情

什么是MyBatis

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。是一个基于Java的持久层框架

为什么我们要用Mybatis?

无论是Mybatis、Hibernate都是ORM的一种实现框架,都是对JDBC的一种封装!

这里写图片描述

到目前为止,我们已经在持久层中学了几种技术了…

  • Hibernate
  • jdbc
  • SpringDAO

那我们为啥还要学Mybatis呢???现在Mybatis在业内大行其道,那为啥他能那么火呢??

Hibernate是一个比较老旧的框架,用过他的同学都知道,只要你会用,用起来十分舒服…啥sql代码都不用写…但是呢,它也是有的缺点::处理复杂业务时,灵活度差, 复杂的HQL难写难理解,例如多表查询的HQL语句

而JDBC很容易理解,就那么几个固定的步骤,就是开发起来太麻烦了,因为什么都要我们自己干..

而SpringDAO其实就是JDBC的一层封装,就类似于dbutils一样,没有特别出彩的地方….

我们可以认为,Mybatis就是jdbc和Hibernate之间的一个平衡点…毕竟现在业界都是用这个框架,我们也不能不学呀!


Mybatis快速入门

其实我们已经学过了Hibernate了,对于Mybatis入门其实就非常类似的。因此就很简单就能掌握基本的开发了…

导入开发包

导入Mybatis开发包

  • mybatis-3.1.1.jar
  • commons-logging-1.1.1.jar
  • log4j-1.2.16.jar
  • cglib-2.2.2.jar
  • asm-3.3.1.jar

导入mysql/oracle开发包

  • mysql-connector-java-5.1.7-bin.jar
  • Oracle 11g 11.2.0.1.0 JDBC_ojdbc6.jar

准备测试工作

创建一张表


create table students(
  id  int(5) primary key,
  name varchar(10),
  sal double(8,2)
);

创建实体:


/**
 * Created by ozc on 2017/7/21.
 */

public class Student {
    private Integer id;
    private String name;
    private Double sal;

    public Student() {
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Double getSal() {
        return sal;
    }

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

创建mybatis配置文件

创建mybatis的配置文件,配置数据库的信息….数据库我们可以配置多个,但是默认的只能用一个…


<?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="db.properties"/>

    <!-- 设置一个默认的连接环境信息 -->
    <environments default="mysql_developer">
        <!-- 连接环境信息,取一个任意唯一的名字 -->
        <environment id="mysql_developer">
            <!-- mybatis使用jdbc事务管理方式 -->
            <transactionManager type="jdbc"/>
            <!-- mybatis使用连接池方式来获取连接 -->
            <dataSource type="pooled">
                <!-- 配置与数据库交互的4个必要属性 -->
                <property name="driver" value="${mysql.driver}"/>
                <property name="url" value="${mysql.url}"/>
                <property name="username" value="${mysql.username}"/>
                <property name="password" value="${mysql.password}"/>
            </dataSource>
        </environment>


        <!-- 连接环境信息,取一个任意唯一的名字 -->
        <environment id="oracle_developer">
            <!-- mybatis使用jdbc事务管理方式 -->
            <transactionManager type="jdbc"/>
            <!-- mybatis使用连接池方式来获取连接 -->
            <dataSource type="pooled">
                <!-- 配置与数据库交互的4个必要属性 -->
                <property name="driver" value="${oracle.driver}"/>
                <property name="url" value="${oracle.url}"/>
                <property name="username" value="${oracle.username}"/>
                <property name="password" value="${oracle.password}"/>
            </dataSource>
        </environment>
    </environments>


</configuration>

编写工具类测试是否获取到连接

使用Mybatis的API来创建一个工具类,通过mybatis配置文件与数据库的信息,得到Connection对象


package cn.itcast.javaee.mybatis.util;

import java.io.IOException;
import java.io.Reader;
import java.sql.Connection;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
 * 工具类
 * @author AdminTC
 */
public class MybatisUtil {
    private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
    private static SqlSessionFactory sqlSessionFactory;
    /**
     * 加载位于src/mybatis.xml配置文件
     */
    static{
        try {
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    /**
     * 禁止外界通过new方法创建 
     */
    private MybatisUtil(){}
    /**
     * 获取SqlSession
     */
    public static SqlSession getSqlSession(){
        //从当前线程中获取SqlSession对象
        SqlSession sqlSession = threadLocal.get();
        //如果SqlSession对象为空
        if(sqlSession == null){
            //在SqlSessionFactory非空的情况下,获取SqlSession对象
            sqlSession = sqlSessionFactory.openSession();
            //将SqlSession对象与当前线程绑定在一起
            threadLocal.set(sqlSession);
        }
        //返回SqlSession对象
        return sqlSession;
    }
    /**
     * 关闭SqlSession与当前线程分开
     */
    public static void closeSqlSession(){
        //从当前线程中获取SqlSession对象
        SqlSession sqlSession = threadLocal.get();
        //如果SqlSession对象非空
        if(sqlSession != null){
            //关闭SqlSession对象
            sqlSession.close();
            //分开当前线程与SqlSession对象的关系,目的是让GC尽早回收
            threadLocal.remove();
        }
    }   
    /**
     * 测试
     */
    public static void main(String[] args) {
        Connection conn = MybatisUtil.getSqlSession().getConnection();
        System.out.println(conn!=null?"连接成功":"连接失败");
    }
}



创建实体与映射关系文件

配置实体与表的映射关系


<?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 namespace="cn.itcast.javaee.mybatis.app04.Student"> 

    <!-- resultMap标签:映射实体与表 
         type属性:表示实体全路径名
         id属性:为实体与表的映射取一个任意的唯一的名字
    -->
    <resultMap type="student" id="studentMap">
        <!-- id标签:映射主键属性
             result标签:映射非主键属性
             property属性:实体的属性名
             column属性:表的字段名  
        -->                         
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sal" column="sal"/>
    </resultMap>

</mapper>

现在我们已经有了Mybatis的配置文件和表与实体之前的映射文件了,因此我们要将配置文件和映射文件关联起来


    <mappers>
        <mapper resource="StudentMapper.xml"/>
    </mappers>

在测试类上,我们是可以获取得到连接的

这里写图片描述


编写DAO


public class StudentDao {


    public void add(Student student) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        sqlSession.insert();
    }

    public static void main(String[] args) throws Exception {

        StudentDao studentDao = new StudentDao();

        Student student = new Student(1, "zhongfucheng", 10000D);
        studentDao.add(student);

    }
}

到现在为止,我们实体与表的映射文件仅仅映射了实体属性与表的字段的关系…

我们在Hibernate中如果想要插入数据什么的,只要调用save()方法就行了。Hibernate是自动化屏蔽掉了数据库的差异,而我们Mybatis是需要自己手动编写SQL代码的…

那么SQL代码是写在哪里的呢???明显地,我们作为一个框架,不可能在程序中写SQL,我们是在实体与表的映射文件中写的!

Mybatis实体与表的映射文件中提供了insert标签【SQL代码片段】供我们使用


    //在JDBC中我们通常使用?号作为占位符,而在Mybatis中,我们是使用#{}作为占位符
    //parameterType我们指定了传入参数的类型
    //#{}实际上就是调用了Student属性的get方法

    <insert id="add" parameterType="Student">

        INSERT INTO ZHONGFUCHENG.STUDENTS (ID, NAME, SAL) VALUES (#{id},#{name},#{sal});
    </insert>

在程序中调用映射文件的SQL代码片段


    public void add(Student student) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
            sqlSession.insert("StudentID.add", student);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

值得注意的是:Mybatis中的事务是默认开启的,因此我们在完成操作以后,需要我们手动去提交事务!

Mybatis工作流程

  • 通过Reader对象读取Mybatis映射文件
  • 通过SqlSessionFactoryBuilder对象创建SqlSessionFactory对象
  • 获取当前线程的SQLSession
  • 事务默认开启
  • 通过SQLSession读取映射文件中的操作编号,从而读取SQL语句
  • 提交事务
  • 关闭资源

完成CRUD操作

我们在上面中已经简单知道了Mybatis是怎么使用的以及工作流程了,这次我们使用Mybatis来完成CRUD的操作,再次巩固Mybatis的开发步骤以及一些细节

包与类之间的结构

这里写图片描述

增加学生

配置文件

<?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="db.properties"/>

    <!-- 设置一个默认的连接环境信息 -->
    <environments default="mysql_developer">
        <!-- 连接环境信息,取一个任意唯一的名字 -->
        <environment id="mysql_developer">
            <!-- mybatis使用jdbc事务管理方式 -->
            <transactionManager type="jdbc"/>
            <!-- mybatis使用连接池方式来获取连接 -->
            <dataSource type="pooled">
                <!-- 配置与数据库交互的4个必要属性 -->
                <property name="driver" value="${mysql.driver}"/>
                <property name="url" value="${mysql.url}"/>
                <property name="username" value="${mysql.username}"/>
                <property name="password" value="${mysql.password}"/>
            </dataSource>
        </environment>


        <!-- 连接环境信息,取一个任意唯一的名字 -->
        <environment id="oracle_developer">
            <!-- mybatis使用jdbc事务管理方式 -->
            <transactionManager type="jdbc"/>
            <!-- mybatis使用连接池方式来获取连接 -->
            <dataSource type="pooled">
                <!-- 配置与数据库交互的4个必要属性 -->
                <property name="driver" value="${oracle.driver}"/>
                <property name="url" value="${oracle.url}"/>
                <property name="username" value="${oracle.username}"/>
                <property name="password" value="${oracle.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="zhongfucheng/StudentMapper.xml"/>
    </mappers>
</configuration>

映射文件

<!-- namespace属性是名称空间,必须唯一 -->
<mapper namespace="StudentID">

    <!-- resultMap标签:映射实体与表 
         type属性:表示实体全路径名
         id属性:为实体与表的映射取一个任意的唯一的名字
    -->
    <resultMap type="zhongfucheng.Student" id="studentMap">
        <!-- id标签:映射主键属性
             result标签:映射非主键属性
             property属性:实体的属性名
             column属性:表的字段名
        -->
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sal" column="sal"/>
    </resultMap>

    <insert id="add" parameterType="zhongfucheng.Student">
        INSERT INTO ZHONGFUCHENG.STUDENTS (ID, NAME, SAL) VALUES (#{id},#{name},#{sal});
    </insert>

</mapper>

插入数据


public class StudentDao {

    public void add(Student student) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
            sqlSession.insert("StudentID.add", student);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }
    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        Student student = new Student(3, "zhong3", 10000D);
        studentDao.add(student);
    }
}

这里写图片描述

根据ID查询数据

增加select标签


    <!--
        查询根据id
        resultMap这个属性代表是返回值类型,返回值的类型是Student,就是上面实体类型
    -->
    <select id="findById" parameterType="int" resultMap="studentMap">
        SELECT * FROM STUDENTS WHERE id = #{id};
    </select>

查询出来的结果是一个Student对象,我们调用SelectOne方法


    public Student findById(int id) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
            return sqlSession.selectOne("StudentID.findById",id);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }
    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        Student student = studentDao.findById(1);
        System.out.println(student.getName());

    }

这里写图片描述

查询所有数据


    <!--
        查询所有数据
        返回值类型讲道理是List<Student>的,但我们只要写集合中的类型就行了
    -->
    <select id="findAll" resultMap="studentMap">
        SELECT * FROM STUDENTS;
    </select>

我们查询出来的结果不单单只有一个对象了,因此我们使用的是SelectList这个方法

  public List<Student> findAll() throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
            return sqlSession.selectList("StudentID.findAll");
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }
    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        List<Student> students = studentDao.findAll();
        System.out.println(students.size());

    }

根据id删除


    <!--根据id删除-->
    <delete id="delete" parameterType="int">
        DELETE FROM STUDENTS WHERE id=#{id};

    </delete>

调用delete方法删除



    public void delete(int id ) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
            sqlSession.delete("StudentID.delete", id);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }
    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        studentDao.delete(1);

    }

这里写图片描述

修改


    <!--更新-->
    <update id="update" parameterType="zhongfucheng.Student">

        update students set name=#{name},sal=#{sal} where id=#{id};

    </update>

查询出对应的对象,对其进行修改



    public void update(Student student ) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
            sqlSession.update("StudentID.update", student);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }
    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        Student student = studentDao.findById(2);
        student.setName("fucheng");
        student.setSal(2000D);
        studentDao.update(student);

    }

这里写图片描述

小细节


    <!-- 
        注意:这个insert/update/delete标签只是一个模板,在做操作时,其实是以SQL语句为核心的
             即在做增/删/时,insert/update/delete标签可通用,
             但做查询时只能用select标签
             我们提倡什么操作就用什么标签
    --> 

Mybatis分页

分页是一个非常实用的技术点,我们也来学习一下使用Mybatis是怎么分页的…

我们的分页是需要多个参数的,并不是像我们之前的例子中只有一个参数。当需要接收多个参数的时候,我们使用Map集合来装载!


    public List<Student>  pagination(int start ,int end) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL


            /**
             * 由于我们的参数超过了两个,而方法中只有一个Object参数收集
             * 因此我们使用Map集合来装载我们的参数
             */
            Map<String, Object> map = new HashMap();
            map.put("start", start);
            map.put("end", end);
            return sqlSession.selectList("StudentID.pagination", map);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }
    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        List<Student> students = studentDao.pagination(0, 3);
        for (Student student : students) {

            System.out.println(student.getId());

        }

    }

那么在实体与表映射文件中,我们接收的参数就是map集合



    <!--分页查询-->
    <select id="pagination" parameterType="map" resultMap="studentMap">

        /*根据key自动找到对应Map集合的value*/
        select * from students limit #{start},#{end};

    </select>

这里写图片描述

动态SQL

何为动态SQL??回顾一下我们之前写的SSH项目中,有多条件查询的情况,如下图

这里写图片描述

我们当时刚开始做的时候,是需要在Controller中判断SQL是否已经有条件了,因为SQL语句需要拼接起来….这样干的话,就非常容易出错的。

如下的代码,如果有多个条件的话,那么拼接起来很容易出错!


  public String listUI() {

        //查询语句
        String hql = "FROM Info i ";
        List<Object> objectList  = new ArrayList<>();

        //根据info是否为null来判断是否是条件查询。如果info为空,那么是查询所有。
        if (info != null) {
            if (StringUtils.isNotBlank(info.getTitle())) {
                hql += "where i.title like ?";
                objectList.add("%" + info.getTitle() + "%");
            }
        }
        infoList = infoServiceImpl.findObjects(hql,objectList);
        ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);
        return "listUI";
    }

后来,我们觉得这样不好,于是就专门写了一个查询助手类:


package zhongfucheng.core.utils;

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

/**
 * Created by ozc on 2017/6/7.
 */
public class QueryHelper {

    private String fromClause = "";
    private String whereClause = "";
    private String orderbyClause = "";
    private List<Object> objectList;

    public static String ORDER_BY_ASC = "asc";
    public static String ORDER_BY_DESC = "desc";



    //FROM子句只出现一次
    /**
     * 构建FROM字句,并设置查询哪张表
     * @param aClass 用户想要操作的类型
     * @param alias  别名
     */
    public QueryHelper(Class aClass, String alias) {
        fromClause = "  FROM " + aClass.getSimpleName() + "  " + alias;
    }
    //WHERE字句可以添加多个条件,但WHERE关键字只出现一次
    /**
     * 构建WHERE字句
     * @param condition
     * @param objects
     * @return
     */
    public QueryHelper addCondition(String condition, Object... objects) {
        //如果已经有字符了,那么就说明已经有WHERE关键字了
        if (whereClause.length() > 0) {
            whereClause += " AND  " + condition;
        } else {
            whereClause += " WHERE" + condition;
        }
        //在添加查询条件的时候,?对应的查询条件值
        if (objects == null) {
            objectList = new ArrayList<>();
        }

        for (Object object : objects) {
            objectList.add(object);
        }

        return this;
    }
    /**
     *
     * @param property 要排序的属性
     * @param order 是升序还是降序
     * @return
     */
    public QueryHelper orderBy(String property, String order) {

        //如果已经有字符了,那么就说明已经有ORDER关键字了
        if (orderbyClause.length() > 0) {
            orderbyClause += " ,  " + property +"   " + order;
        } else {
            orderbyClause += "  ORDER BY " + property+"   " + order;
        }
        return this;
    }

    /**
     * 返回HQL语句
     */
    public String returnHQL() {
        return fromClause + whereClause + orderbyClause;
    }

    /**
     * 得到参数列表
     * @return
     */
    public List<Object> getObjectList() {
        return objectList;
    }
}

这样一来的话,我们就不用自己手动拼接了,给我们的查询助手类去拼接就好了。

而如果我们使用Mybatis的话,就可以免去查询助手类了。因为Mybatis内部就有动态SQL的功能【动态SQL就是自动拼接SQL语句】!

动态查询


    <!--多条件查询【动态SQL】-->
    <!--会自动组合成一个正常的WHERE字句-->
    <!--name值会从map中寻找-->

    <select id="findByCondition" resultMap="studentMap" parameterType="map">

        select * from students

        <where>
            <if test="name!=null">
                and name=#{name}
            </if>
            <if test="sal!=null">
                and sal < #{sal}
            </if>
        </where>

    </select>

查询出来小于9000块的人


   public List<Student> findByCondition(String name,Double sal) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
            /**
             * 由于我们的参数超过了两个,而方法中只有一个Object参数收集
             * 因此我们使用Map集合来装载我们的参数
             */
            Map<String, Object> map = new HashMap();
            map.put("name", name);
            map.put("sal", sal);
            return sqlSession.selectList("StudentID.findByCondition", map);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }
    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        List<Student> students = studentDao.findByCondition(null,9000D);
        for (Student student : students) {
            System.out.println(student.getId() + "---" + student.getName() + "----" + student.getSal());
        }


    }

这里写图片描述

动态更新

这里写图片描述


    <!--动态更新-->
    <!--不要忘了逗号-->
    <update id="updateByConditions" parameterType="map">

        update students
        <set>
            <if test="name!=null">
                 name = #{name},
            </if>
            <if test="sal!=null">
                 sal = #{sal},
            </if>
        </set>
        where id = #{id}
    </update>

给出三个更新的字段


    public void updateByConditions(int id,String name,Double sal) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
            /**
             * 由于我们的参数超过了两个,而方法中只有一个Object参数收集
             * 因此我们使用Map集合来装载我们的参数
             */
            Map<String, Object> map = new HashMap();
            map.put("id", id);
            map.put("name", name);
            map.put("sal", sal);
            sqlSession.update("StudentID.updateByConditions", map);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        studentDao.updateByConditions(2,"haha",500D);

    }

这里写图片描述

动态删除

这里写图片描述
以前我们使用JDBC也好,Hibernate也好,想要批量删除的时候,总是使用的是循环删除。而我们现在使用的是Mybatis,SQL语句是自己写的。所以我们可以写下如下的SQL来进行删除


delete from students where id in (?,?,?,?);

而我们的Mybatis又支持动态SQL,所以删除起来就非常方便了!


    <delete id="deleteByConditions" parameterType="int">

        <!-- foreach用于迭代数组元素
             open表示开始符号
             close表示结束符合
             separator表示元素间的分隔符
             item表示迭代的数组,属性值可以任意,但提倡与方法的数组名相同
             #{ids}表示数组中的每个元素值
         -->
        delete from students where id in
         <foreach collection="array" open="(" close=")" separator="," item="ids">
             #{ids}
         </foreach>

    </delete>

删除编号为2,3,4的记录

    public void deleteByConditions(int... ids) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
            /**
             * 由于我们的参数超过了两个,而方法中只有一个Object参数收集
             * 因此我们使用Map集合来装载我们的参数
             */
            sqlSession.delete("StudentID.deleteByConditions", ids);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        studentDao.deleteByConditions(2,3,4);

    }

这里写图片描述

动态插入

我们要想动态插入的话,就比其他的DML语句稍微复杂一点,因为它有两部分是不确定的,平常的SQL语句是这样的:


insert into student(id,name,sal) values(?,?,?)

这里写图片描述

SQL代码块是不能像之前那样帮我们自动去除多余的逗号的,因此我们需要使用trim标签来自己手动去除…

编写insertSQL语句的时候,不要忘了写()括号。


    <!--SQL片段默认是不帮我们自动生成合适的SQL,因此需要我们自己手动除去逗号-->
    <sql id="key">
        <trim suffixOverrides=",">
            <if test="id!=null">
                id,
            </if>

            <if test="id!=null">
                name,
            </if>

            <if test="id!=null">
                sal,
            </if>
        </trim>
    </sql>

    <sql id="value">
        <trim suffixOverrides=",">
            <if test="id!=null">
                #{id},
            </if>

            <if test="id!=null">
                #{name},
            </if>

            <if test="id!=null">
                #{sal},
            </if>
        </trim>
    </sql>
    <!--动态插入-->
    <insert id="insertByConditions" parameterType="zhongfucheng.Student">

        insert into students (<include refid="key"/>) values
        (<include refid="value"/>)

    </insert>

测试三个不同内容的数据


    public void insertByConditions(Student student) throws Exception {
        //得到连接对象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
            sqlSession.insert("StudentID.insertByConditions", student);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        studentDao.insertByConditions(new Student(55, null, null));//name和sal为空

        studentDao.insertByConditions(new Student(66, "haxi", null));//sal为空
        studentDao.insertByConditions(new Student(77, null, 3999d));//name为空


    }

这里写图片描述

总结

  • Mybatis的准备工作与Hibernate差不多,都需要一个总配置文件、一个映射文件。
  • Mybatis的SQLSession工具类使用ThreadLocal来对线程中的Session来进行管理。
  • Mybatis的事务默认是开启的,需要我们手动去提交事务。
  • Mybatis的SQL语句是需要手写的,在程序中通过映射文件的命名空间.sql语句的id来进行调用!
  • 在Mybatis中,增删改查都是需要我们自己写SQL语句的,然后在程序中调用即可了。SQL由于是我们自己写的,于是就相对Hibernate灵活一些。
  • 如果需要传入多个参数的话,那么我们一般在映射文件中用Map来接收。
  • 由于我们在开发中会经常用到条件查询,在之前,我们是使用查询助手来帮我们完成对SQL的拼接的。而Mybatis的话,我们是自己手写SQL代码的。
  • Mybatis也支持一些判断标签,于是我们就可以通过这些标签来完成动态CRUD的操作了。
  • 值得注意的是,我们的sql片段代码是需要我们自己手动去分割,号的。

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y

Mybatis轻松入门,一篇就够 MyBatis简介、搭建MyBatis、核心配置文件详解、MyBatis的增删改查、MyBatis获取参数值的两种方式、MyBatis的各种查询功能、特殊SQL的执行、自定义映射resultMap、动态SQL、MyBatis的缓存、MyBatis的逆向工程、分页插件 阅读详情

相关推荐

气象数据收集

国家气象信息中心-中国气象数据网 (cma.cn)国家气象信息中心-中国气象数据网 (cma.cn)预报数据:需要定制,收费10万+路面数据同化系统,实时。

weixin_42209537的博客 3485

Java基础之—反射(非常重要)

反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)) 一、反射的概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 要想解剖一个类,必须先要获取到该类的

敬业小码哥的博客 76万+

【过检测】2026调试级去虚拟化虚拟机成品

EternalBlaze调试级虚拟机是由恒烈开发的定制化VMware环境,适用于逆向工程、病毒分析等专业场景。该虚拟机基于Windows 10 1909专业版,预装Python/JDK等开发环境和逆向工具包,支持快照回溯功能。特色包括:一键去虚拟化方案、双机调试支持、驱动开发环境等。适用场景涵盖CTF竞赛、软件调试、病毒行为分析等,但不支持DX12游戏和视频盗录。使用前需按步骤关闭安全中心、安装特定VMware版本并执行去虚拟化操作。虚拟机提供基础版和逆向调试增强版两种配置,均预装必要工具链。(149字)

Heng_lie的博客 2665

Java单元测试实践-17.Mybatis与Mock

Java单元测试实践-00.目录(9万多字文档+700多测试示例) https://blog.youkuaiyun.com/a82514921/article/details/107969340 1. Mybatis与Mock 在对Mybatis的Mapper对象进行处理时,可能需要使某个Mapper对象在某些情况下返回指定值,在某些情况下执行真实方法;或者需要对Mapper对象相关的数据库操作进行记录,以下进行说明。 1.1. 测试示例说明 与Mybatis相关的测试类在测试示例的adrninistrator.tes

adrninistrat0r的博客 1万+

FineReport V11.0安装避坑指南:从下载到激活的完整流程(附百度网盘链接)

本文提供FineReport V11.0从下载、安装到激活的完整避坑指南。详细解析了部署前的环境准备、安装过程中的JVM内存等核心配置、激活流程以及安装后的优化与常见问题排查,旨在帮助用户一次部署成功,确保企业级报表平台的稳定运行。

echo99的专栏 1192

2. Android_逆向的历史与发展

学完本节,希望你能够:了解 Android 逆向工程的发展历程,从早期 APK 破解到现代应用保护;入门先把这几类「在干啥」搞清楚,后面学脱壳、反反调试会顺很多。(反编译 APK 得到的类汇编代码,相当于程序的「菜谱」)就能绕过验证,到后来混淆、加固、反调试一起上,逆向难度越来越高。(第三节 什么是 CPU 指令集),帮你搞清楚「反汇编看到的那些指令」是从哪来的、和 Android 逆向有啥关系。有必要——先搞清「没加固时怎么玩」,再学脱壳和对抗,思路才顺。读起来费劲,但逻辑还在,耐心一点还能跟。

长沙火山 1390

springboot+mybatis+mockito单元测试

springboot、mybatis这里不做详细介绍,重点介绍一下mockito是什么,以及怎么与springboot、mybatis集成。 mockito是什么?举个简单例子:当service层通过调用dao层接口获取数据,然后进行数据处理。在实际做单元测试时,dao层的数据是从数据库来的,我们想自己构造一些数据跑一下service层的业务逻辑,这个时候就需要将从数据库查询的时候替换为自己构造的数据,也就是service层调用的dao层接口返回的数据需要替换为自己构造的数据,那怎么替换呢?这个时候moc

小冷在努力~ 2634

三极管电平转换电路

摘要:本文介绍了三种基于三极管的电平转换电路方案。第一种采用双NPN三极管实现3.3V转5V反相电平转换;第二种使用单NPN三极管完成5V转3.3V同相转换;第三种利用单PNP三极管实现3.3V转5V同相转换。各方案均通过三极管的开关特性配合电阻网络实现电压域适配,具有结构简单、成本低的优点,适用于不同逻辑电平设备(如MCU与外设)间的信号兼容传输。文中详细分析了各电路的工作原理、元件作用和特性,并通过Multisim仿真验证了其功能有效性。

XU157303764的博客 1855

(五)Mybatis的复杂查询

Mybatis的动态SQL查询和多表查询

lyj_010的博客 976

【30天从零玩转AI应用开发】第16篇:智能体Agent入门——ReAct框架原理+首个会思考、会动手的AI实战

摘要: 本文介绍了AI智能体(Agent)的核心概念及其与普通大模型(LLM)的区别。通过ReAct(Reason+Act)框架,智能体实现了自主思考、调用工具和分步执行的能力。文章详细讲解了LangChain Agent的四大组件,并推荐新手使用ZERO_SHOT_REACT_DESCRIPTION类型。最后提供了一个完整的智能体实战代码示例,该智能体具备数学计算和天气查询功能,能够自主选择工具完成任务,展示了AI从”被动回答“到”主动行动“的关键进化。

在上海谋生的软件喵记录喵生 626

Windows原生与WSL2环境下OpenClaw性能与兼容性的对比分析研究

本文对比分析了Windows原生环境与WSL2环境下运行OpenClaw的性能与兼容性。Windows原生环境提供深度系统集成、图形界面支持和硬件加速优势,适合需要Windows生态集成的用户;WSL2则提供接近原生Linux的性能体验,兼容Linux工具链,适合开发者和跨平台需求。文章详细介绍了两种环境下的推荐硬件配置、系统版本选择及必备工具,并提供了具体的部署步骤指南。研究表明,两种环境各有适用场景,用户可根据需求选择最适合的部署方式。

一键难忘的博客 1218

使用MyBatis实现条件查询

在test/java的net.huawei.mybatis.mapper包里创建TestStudentMapper类。运行测试方法testFindByCondition(),查看结果。运行测试方法testFindByCondition(),查看结果。运行测试方法testFindByCondition(),查看结果。运行测试方法testFindByCondition(),查看结果。比如查询姓“吴”,性别为“女”,同时年龄为19的学生记录。注意:注意:通配符%与_的区别。修改测试方法里的查询条件。

梁辰兴的博客 2818

半导体设备系列(2) 半导体设备与工厂控制仿真器Demo编写

基于C/S架构用C++编写半导体设备仿真器与工厂控制仿真器

追赶时代的博客 610

详细的mybatis入门,看这一篇就够了

简介: MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录 1.创建maven工程 1.1 idea如下 1.2 选择路径及工程名 1.3一个maven项目建成了,目录如下 2.导入..

weixin_44808225的博客 287

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

mybatis 返回string_Mybatis入门看这一篇就够了

什么是MyBatisMyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。是一个基于Java的持久层框架为什么我们要用Mybatis?无论是Mybatis、Hibernate都是ORM的一种实现框架,都是对JDBC的一种封装!到目前为止,我们已经在持久层中学了...

weixin_39997173的博客 3352

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

有类似mybatis的框架吗_Mybatis入门看这一篇就够了

什么是MyBatisMyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。是一个基于Java的持久层框架为什么我们要用Mybatis?无论是Mybatis、Hibernate都是ORM的一种实现框架,都是对JDBC的一种封装!到目前为止,我们已经在持久层中学了...

weixin_34797253的博客 1740

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

mybatis看这一篇就够了,简单全面快速入门

Mybatis如何入门? SSM框架基础入门: SSM框架教程|Spring+SpringMVC+MyBatis全套教程(spring+springmvc+mybatis) 什么是Mybatis?Mybatis有什么用? (1) Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement、等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。 (2) MyBatis可以使用X

Aa112233aA1的博客 940

《Mybatis使用指南》入门使用Mybatis这一篇就够了

MyBatis 简介与入门 MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发。它通过 XML 或注解配置将 Java 对象与数据库表映射,自动处理结果集转换。相比传统 JDBC 需要手动创建连接、解析结果集等繁琐操作,MyBatis 提供更简洁的开发方式,支持连接池管理和日志记录。MyBatis 前身为 iBatis,现已成为主流 ORM 框架之一,常与 Spring Boot 集成使用,默认采用 HikariCP 连接池,也可切换为 Druid 等其他连接池。开发中常用 Lombok 简化

pbrush的博客 1633

Mybatis入门级教学,看这一篇就够了

Mybatis入门级教学,看这一篇就够了 1.MyBatis介绍 MyBatis 是支持 普通 SQL 查询 , 存储过程 和 高级映射 的优秀持久层框架。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索封装。MyBatis 可以使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录.JDBC- dbutils- MyBatis- Hibernate 2.MyB

qq_47897078的博客 504

MyBatis入门教程(入门看这一篇就够了)

MyBatis是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。MyBatis的运行原理晦涩难懂,我的建议是要学会用,运行原理尽量理解就行。如果在读取的过程中发现错误,欢迎在评论区讨论。

m0_75210816的博客 2371

Mybatis的入门到精通这一篇文章就够了

Mybatis的产生idea 的配置idea当中配置好maven工具1Idea当中配置自动编译Mybatis是什么?Mybatis的执行原理图Mybatis的入门Demo对象的详解Resources对象SqlSessionFactoryBuildSqlSessionFactorySqlSession对象xxxMapper.xml文件的详解面向接口发开(应用)准备数据引入依赖核心配置文件引入xxxMapper.xml创建接口文件测试 原生JDBC访问数据库 数据库的连接,使用就创建,不使用就立即释放,对数

weixin_42303792的博客 660

想入门SpringBoot整合MyBatis,看我这一篇就够了

写在前面: MyBatis作为业界优秀的持久层框架,应用广泛,与各类web框架都有着良好的整合性。今天在博客里主要总结一下SpringBoot与MyBatis的整合入门,非常简单,放心看下去吧。 1.添加MyBatis起步依赖 在前几篇博客中提到了,起步依赖算是SpringBoot的一大特点之一。所以大部分优秀的组件与SpringBoot整合额第一步都是添加起步依赖。在pom.xml中添加: &l...

weixin_38107316的博客 382

最新 MyBatis-Plus 从入门到实战,看这一篇就够了

MyBatis-Plus 从入门到实战目录前言MyBatis-Plus 架构MyBatis-Plus 快速入门(结合 SpringBoot )BaseMapper 方法详细说明Insert方法Delete方法Update方法Select方法Wrapper条件封装器MyBatis-Plus 下的实体类详细说明@TableName@TableId@TableField详细讲解 MyBatis-Plus 增删改查操作insert方法主键生成策略update方法delete方法select方法结合案例讲解 Wrap

weixin_44176169的博客 2161

Mybatis使用入门,这一篇就够了

mybatis中,封装了一个sqlsession 对象(里面封装有connection对象),由此对象来对数据库进行CRUD操作。 运行流程 mybatis有一个配置的xml,用于配置数据源、映射Mapping,xml的文件名可以任取,为了方便,我们还是起mybatis-config.xml 我们读取此配置的xml,获得一个sqlsession,之后由此对象类进行数据库的CRUD操作 复...

hys8298的博客 226
上一篇: Struts2【OGNL、valueStack】就是这么简单
下一篇: Mybatis【配置文件】详解
Java3y
Java3y 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 509原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值