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