Mybatis入門看這一篇就夠了

来源:https://www.cnblogs.com/Java3y/archive/2018/03/12/8547362.html
-Advertisement-
Play Games

什麼是MyBatis MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis。是一個基於Java的持久層框架 為什麼我們要用Mybatis? 無論是Mybatis ...


什麼是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>

            <

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 電腦的組成 1、控制器 2、運算器(CPU) 3、主存儲器(記憶體) 4、外存 5、輸入、輸出設備 存儲器:主存和外存 數據的表示 對於任意一個R進位數,它的每一位數值等於該位的數位乘以該位的權數。權數由Rk表示,K與該位和小數點之間的距離有關。當該位位於小數點左邊,K值是該位和小數點之間的數位的個... ...
  • 簡介 在軟體開發過程中,會遇到很多重覆性的地方,設計模式就是開發前輩將一點一點開發經驗整合成便於他人重覆使用、高效率的代碼模板。學習開發人員使用設計模式開發能大大提高開發效率。從而使得代碼的可維護性、健壯性提高。 單例模式 單例模式要求類只能創建唯一的一個實例。一般情況下,構造器在訪問許可權類型都是公 ...
  • 現在出現了很多中間件解決跨語言問題,使用RPC遠程調用;但是龐大是個問題,而且要按照格式使用。尤其是源碼量比較龐大。 為了簡單易用,我採用訂閱發佈模型,在此基礎上創建了fastRPC,模擬RPC,調用遠端方法。 其實主要過程就是通過提供的類,將每個參數打包為特定格式,按照類型名稱,在服務端匹配轉換; ...
  • 工業互聯網剛剛興起,十九大和兩會領導人也多次提及。但是對於新生事物,每個廠家、每個組織、每個人的都理解都不一樣,甚至千差萬別,正因為如此才會有無限生機。但是也有其共性的東西,1、要是一個雲平臺、2、是一個資源平臺,3、是一個物聯網平臺,4、是一個數據存儲平臺、5、是一個分析平臺......更高是工業 ...
  • 創建型 單例模式 餓漢式 懶漢式 雙重校驗鎖 工廠模式 圖例 簡單工廠模式 工廠模式 簡單工廠VS工廠 相同 : 工廠負責產品類的創建,使用者需要使用產品類的時候直接請求工廠就與產品類複雜的創建和實現分離了,只關註它的介面,只要它的介面滿足使用者要求就不會影響上層模塊,後期當產品類變化時,維護起來也 ...
  • 介紹: 從MVC是一種維護性較強、耦合性低的新的架構MVVM(Model View View-Mode),MVVM正式規範了視圖和控制器緊耦合的性質,並引入新的組件。MVVM主要目的是為了分離視圖(View)和模型(Model)。它促進了 UI 代碼與業務邏輯的分離。它正式規範了視圖和控制器緊耦合的 ...
  • Java如今的市場不如從前,競爭很大,工資非常高,標準非常高,想要勝任一份高薪的工作不是那麼容易,只有掌握最新的行情才能更好的瞭解Java,才能更好的在這個領取發展,讓新手小白瞭解Java市場行情如下:行情一:五年後和五年前的區別,在五年我們這個行業不僅僅缺人才,連新手都缺,那個時候公司願意招聘實習 ...
  • python2和python3中的urllib urllib提供了一個高級的 Web 通信庫,支持基本的 Web 協議,如 HTTP、FTP 和 Gopher 協議,同時也支持對本地文件的訪問。 具體來說,urllib 模塊的功能是利用前面介紹的協議來從網際網路、區域網、本地主機上下載數據。 使用這個 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...