Mybatis入門看這一篇就夠了

什麼是MyBatis

MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,而且更名爲MyBatis。是一個基於Java的持久層框架php

爲何咱們要用Mybatis?

不管是Mybatis、Hibernate都是ORM的一種實現框架,都是對JDBC的一種封裝!java

這裏寫圖片描述

到目前爲止,咱們已經在持久層中學了幾種技術了...mysql

  • Hibernate
  • jdbc
  • SpringDAO

那咱們爲啥還要學Mybatis呢???如今Mybatis在業內大行其道,那爲啥他能那麼火呢??sql

Hibernate是一個比較老舊的框架,用過他的同窗都知道,只要你會用,用起來十分舒服...啥sql代碼都不用寫...可是呢,它也是有的缺點::處理複雜業務時,靈活度差, 複雜的HQL難寫難理解,例如多表查詢的HQL語句數據庫

而JDBC很容易理解,就那麼幾個固定的步驟,就是開發起來太麻煩了,由於什麼都要咱們本身幹..apache

而SpringDAO其實就是JDBC的一層封裝,就相似於dbutils同樣,沒有特別出彩的地方....數組

咱們能夠認爲,Mybatis就是jdbc和Hibernate之間的一個平衡點...畢竟如今業界都是用這個框架,咱們也不能不學呀!微信


Mybatis快速入門

其實咱們已經學過了Hibernate了,對於Mybatis入門其實就很是相似的。所以就很簡單就能掌握基本的開發了...session

導入開發包

導入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

相關文章
相關標籤/搜索