Mybatis3 快速入門

Mybatis3 快速入門

目前常見的持久層java框架有Hibernate,Mybatis,SpringData。筆者比較喜歡用SpringData。Hibernate 和 Mybatis 也經常用。今天通過 Mybatis 的簡介,數據的增刪改查,表的級聯查詢,動態SQL語句 來快速入門 Mybatis 。

1 Mybatis 簡介

摘錄百度百科的內容:MyBatis 是一款優秀的持久層框架,它支持定製化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄

如果 Hibernate 是自動化持久層框架,那麼 Mybatis 就是半自動化持久層框架。 半自動 ??? 聽起來好像 lower 了。其實不然,Mybatis 將 sql 和 java 分離開。讓專業的db工程師負責 sql 的優化,提高其性能,在高併發的場景,系統依然 穩如dog 。程序員可以把更多的精力放在業務邏輯上。

Mybatis:https://github.com/mybatis/mybatis-3/

2 Mybatis 快速入門

需求:使用 mybatis 框架完成數據的增刪改查操作,和級聯查詢,模糊查詢,調用存儲過程,使用mybatis的一二級緩存

技術:mybatis,maven

源碼:見文章底部

說明:本文內容屬於快速入門,通過手寫 xml 映射文件瞭解 mybatis 的工作原理。實際開發中,一般採用官方提供的逆向工程自動生成需要的 java 文件和 xml 文件

結構:
![806956-20171112163901606-1696704597.png][1]

準備:

Mysql數據庫表結構
![806956-20171112170403638-636083194.png][2]

創建四張表,其中 person 獨立存在。classroom 和 student,teacher 存在主外鍵關係。

① classroom 的 student_id 和 student 的 class_id 存在主外鍵關係,並且是一對多的關係

② classroom 的 teacher_id 和 teacher 的 id 存在主外鍵關係,並且是一對一的關係

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for classroom
-- ----------------------------
DROP TABLE IF EXISTS `classroom`;
CREATE TABLE `classroom` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `room` varchar(255) DEFAULT NULL,
  `teacher_id` int(11) DEFAULT NULL,
  `student_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `c_t_id` (`teacher_id`),
  KEY `c_s_id` (`student_id`),
  CONSTRAINT `c_t_id` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of classroom
-- ----------------------------
INSERT INTO `classroom` VALUES ('1', 'JavaEE', '1', '1');
INSERT INTO `classroom` VALUES ('2', 'Linux', '2', '2');

-- ----------------------------
-- Table structure for person
-- ----------------------------
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(255) DEFAULT NULL,
  `last_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of person
-- ----------------------------
INSERT INTO `person` VALUES ('1', '[email protected]', 'lxl');
INSERT INTO `person` VALUES ('2', '[email protected]', 'cyy');
INSERT INTO `person` VALUES ('3', '[email protected]', 'itdragon');
INSERT INTO `person` VALUES ('4', '[email protected]', 'java');

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `class_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `s_c_id` (`class_id`),
  CONSTRAINT `s_c_id` FOREIGN KEY (`class_id`) REFERENCES `classroom` (`student_id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', 'ITDragon', '1');
INSERT INTO `student` VALUES ('2', 'Marry', '1');
INSERT INTO `student` VALUES ('3', 'XiaoMing', '2');

-- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `subject` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of teacher
-- ----------------------------
INSERT INTO `teacher` VALUES ('1', 'Java');
INSERT INTO `teacher` VALUES ('2', 'Docker');

Maven 項目的核心文件 pom.xml (有些不是必要的,後續做整合會用到)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.itdragon.mybatis</groupId>
  <artifactId>mybatis-basic</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <properties>
          <commons-lang3.version>3.3.2</commons-lang3.version>
        <commons-io.version>1.3.2</commons-io.version>
        <commons-net.version>3.3</commons-net.version>
        <junit.version>4.12</junit.version>
        <slf4j.version>1.6.4</slf4j.version>
        <mybatis.version>3.2.8</mybatis.version>
        <mybatis.spring.version>1.2.2</mybatis.spring.version>
        <mybatis.paginator.version>1.2.15</mybatis.paginator.version>
        <mysql.version>5.1.6</mysql.version>
        <druid.version>1.0.9</druid.version>
    </properties>

    <dependencies>
        <!-- Apache工具組件 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons-lang3.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commons-io.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>${commons-net.version}</version>
        </dependency>
        <!-- 單元測試 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <!-- 日誌處理 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>${mybatis.spring.version}</version>
        </dependency>
        <dependency>
            <groupId>com.github.miemiedev</groupId>
            <artifactId>mybatis-paginator</artifactId>
            <version>${mybatis.paginator.version}</version>
        </dependency>
        <!-- MySql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <!-- 連接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>
    </dependencies>

</project>

Mybatis 的配置文件 SqlMapConfig.xml

<?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>

    <!-- 標籤必須按順序寫,否則會提示錯誤:The content of element type "configuration" must match "(properties?,settings?,...)". -->  

    <!-- 引入配置文件 -->
    <properties resource="db.properties" />

    <!-- 配置實體類的別名 -->
    <typeAliases>
        <!-- 給指定包取別名,別名爲實體類對應的簡單類名,如 com.itdragon.pojo.Person 的別名就是 Person -->
        <package name="com.itdragon.pojo" />
    </typeAliases>

    <!-- 配置數據庫鏈接 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>

    <!-- 註冊映射文件 -->
    <mappers>
        <mapper resource="com/itdragon/mapper/PersonMapper.xml" />
        <mapper resource="com/itdragon/mapper/ClassroomMapper.xml" />
    </mappers>

</configuration>

數據庫的配置文件 db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/jpa?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

到這裏準備工作就做完了。

3 數據的增刪改查

Person.java 實體類

package com.itdragon.pojo;

// 學習 mybatis crud 實體類
public class Person {
    private Integer id;
    private String email;
    private String lastName; // 這裏lastName 在數據庫中對應的是 last_name, 這會出現:字段名與實體類屬性名不相同的衝突問題

    public Person() {
    }

    public Person(Integer id, String email, String lastName) {
        this.id = id;
        this.email = email;
        this.lastName = lastName;
    }

    public Integer getId() {
        return id;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email == null ? null : email.trim();
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName == null ? null : lastName.trim();
    }

    @Override
    public String toString() {
        return "Person [id=" + id + ", email=" + email + ", lastName=" + lastName + "]";
    }

}

PersonMapper.xml 查詢數據的映射文件

<?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">
<mapper namespace="com.itdragon.mapper.PersonMapper">
    <!-- CRUD 操作 -->
    <!-- 
        基礎知識: 
        select 查詢數據
        insert 插入數據
        delete 刪除數據
        update 更新數據
        namespace 命名空間
        id 方法名, 命名空間  + 方法名 = 唯一方法
        parameterType 傳入參數類型
        resultType 返回值類型  
        resultMap 以鍵值對的類型返回結果

        參數傳值:#{xxx}
        parameterType 如果不是實體類,對應的參數名可以自定義。如 #{id} 也可以是 #{xxxx}
        如果是實體類,對應的參數名必須是實體類屬性名。爲了避免錯誤,儘量全部都用屬性名。

        擴展知識:
        resultType 的值是 com.itdragon.pojo.Person 全類名,但爲了方便,可以考慮使用別名 
        resultMap 爲了避免類似 lastName 和 last_name 衝突,導致查詢的 last_name 會是 null 問題,可以設置鍵值關係
     -->
    <select id="getPersonById" parameterType="int" resultType="com.itdragon.pojo.Person">
        select * from person where id=#{id}
    </select>

    <!-- 解決字段名與實體類屬性名不相同的衝突問題第一種辦法(不推薦) -->
    <select id="getPersonByIdOne" parameterType="int" resultType="com.itdragon.pojo.Person">
        select id, email, last_name lastName from person where id=#{id}
    </select>

    <select id="getPersonByIdTwo" parameterType="int" resultMap="getPersonMap">
        select * from person where id=#{id}
    </select>
    <!-- 使用 resultMap 設置衝突字段名和實體類屬性名對應關係,(推薦) -->
    <resultMap type="Person" id="getPersonMap">
        <result property="lastName" column="last_name" />
    </resultMap>

    <!-- parameterType 中直接使用了 Person 是因爲在 SqlMapConfig.xml 文件中設置了別名 -->
    <insert id="createPerson" parameterType="Person">
        insert into person(email, last_name) values(#{email}, #{lastName})
    </insert>

    <delete id="deletePersonById" parameterType="int">
        delete from person where id=#{id}
    </delete>

    <update id="updatePersonById" parameterType="Person">
        update person set email=#{email}, last_name=#{lastName} where id=#{id}
    </update>

    <select id="getAllperson" resultType="Person">
        select * from person
    </select>

</mapper>

測試方法:

package com.itdragon.test;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import com.itdragon.pojo.Classroom;
import com.itdragon.pojo.Person;

public class MyBatisTest {

    public SqlSession getSqlSession() {
        String resource = "SqlMapConfig.xml"; 
        InputStream is = MyBatisTest.class.getClassLoader().getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession(true); // false 默認手動提交, true 自動提交
        return session;
    }

    // crud 操作
    @Test
    public void getPersonById() {
        String statement = "com.itdragon.mapper.PersonMapper.getPersonById";
        Person person = getSqlSession().selectOne(statement, 2);
        System.out.println(person);

        statement = "com.itdragon.mapper.PersonMapper.getPersonByIdOne";
        person = getSqlSession().selectOne(statement, 2);
        System.out.println(person);

        statement = "com.itdragon.mapper.PersonMapper.getPersonByIdTwo";
        person = getSqlSession().selectOne(statement, 2);
        System.out.println(person);
    }
    @Test
    public void getAllperson() {
        String statement = "com.itdragon.mapper.PersonMapper.getAllperson";
        List<Person> persons = getSqlSession().selectList(statement);
        System.out.println(persons);
    }
    @Test
    public void createPerson() {
        String statement = "com.itdragon.mapper.PersonMapper.createPerson";
        int result = getSqlSession().insert(statement, new Person(3, "[email protected]", "ITDragon"));
        System.out.println(result);
    }
    @Test
    public void updatePersonById() {
        String statement = "com.itdragon.mapper.PersonMapper.updatePersonById";
        int result = getSqlSession().update(statement, new Person(4, "[email protected]", "ITDragon博客"));
        System.out.println(result);
    }
    @Test
    public void deletePersonById() {
        String statement = "com.itdragon.mapper.PersonMapper.deletePersonById";
        int result = getSqlSession().delete(statement, 4);
        System.out.println(result);
    }

}

4 級聯查詢

爲了滿足一對一和一對多的級聯操作,新增三個實體類,分別是 Classroom(教室),Teacher(老師),Student(學生)

Classroom 和 Teacher 是一對一的關係,Classroom 和 Student 是一對多的關係

package com.itdragon.pojo;

import java.io.Serializable;
import java.util.List;

// 學習 表的關聯關係所用字段,一個教室關聯一個老師(一對一),一個教室關聯一羣學生(一對多)
public class Classroom implements Serializable {

    private Integer id;
    private String room;
    private Teacher teacher;
    private List<Student> students;

    public Classroom() {
    }

    public Classroom(Integer id, String room, Teacher teacher, List<Student> students) {
        this.id = id;
        this.room = room;
        this.teacher = teacher;
        this.students = students;
    }

    public Integer getId() {
        return id;
    }

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

    public String getRoom() {
        return room;
    }

    public void setRoom(String room) {
        this.room = room;
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Classroom [id=" + id + ", room=" + room + ", teacher=" + teacher + ", students=" + students + "]";
    }

}
package com.itdragon.pojo;

import java.io.Serializable;

public class Teacher implements Serializable{

    private Integer id;
    private String subject;

    public Teacher() {
    }

    public Teacher(Integer id, String subject) {
        this.id = id;
        this.subject = subject;
    }

    public Integer getId() {
        return id;
    }

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

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    @Override
    public String toString() {
        return "Teacher [id=" + id + ", subject=" + subject + "]";
    }

}
package com.itdragon.pojo;

import java.io.Serializable;

public class Student implements Serializable {

    private Integer id;
    private String name;

    public Student() {
    }

    public Student(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    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;
    }

    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + "]";
    }

}

ClassroomMapper.xml

<?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">
<mapper namespace="com.itdragon.mapper.ClassroomMapper">
    <!-- 關聯表查詢 -->
    <!-- 
        基礎知識:
        association:用於一對一的關聯查詢
            property:對象的屬性名
            javaType:對象的類型
            column:對應數據表中外鍵
            select:使用另外一個查詢的封裝結果
        collection:用於一對多的關聯查詢
            ofType:指定集合對象的類型
    -->

    <!-- 
        需求:通過 id 查詢 classroom, 並打印 teacher 信息
        嵌套查詢:通過執行另外一個SQL映射語句來返回預期的複雜類型
        第一步:先查詢 classroom SELECT * FROM classroom WHERE id=?;
        第二步:再查詢 teacher SELECT * FROM teacher WHERE id=classroom.id //classroom 是第一步的查詢結果
        說明:嵌套查詢的方法,雖然好理解,當時不建議
    -->
    <select id="getClassroomById" parameterType="int" resultMap="getClassroomMap">
        SELECT * FROM classroom WHERE id=#{id}
    </select>

    <select id="getTeacherById" parameterType="int" resultType="Teacher">
        SELECT * FROM teacher WHERE id=#{id}
    </select>

    <resultMap type="Classroom" id="getClassroomMap">
        <association property="teacher" column="teacher_id" select="getTeacherById">
        <!-- 如果 teacher 存在屬性字段和字段衝突,需要在這裏設置 -->
        </association>
    </resultMap>

    <!-- 
        需求:通過 id 查詢 classroom, 並打印 teacher 信息
        嵌套結果:使用嵌套結果映射來處理重複的聯合結果的子集,封裝聯表查詢的數據(去除重複的數據)
        select * from classroom, teacher where classroom.teacher_id=teacher.id and classroom.id=?
    -->
    <select id="getClassroom2ById" parameterType="int" resultMap="getClassroom2Map">
        SELECT * FROM classroom c, teacher WHERE c.teacher_id = teacher.id AND c.id = #{id}
    </select>
    <resultMap type="Classroom" id="getClassroom2Map">
        <id property="id" column="id"/>
        <result property="room" column="room"/>
        <association property="teacher" javaType="Teacher">
            <id property="id" column="id"/>
            <result property="subject" column="subject"/>
        </association>
    </resultMap>

    <!-- 
        需求:通過 id 查詢 classroom, 並打印 teacher 和 student 信息
        嵌套查詢:通過執行另外一個SQL映射語句來返回預期的複雜類型
        第一步:先查詢 classroom SELECT * FROM classroom WHERE id=?;
        第二步:再查詢 teacher SELECT * FROM teacher WHERE id=classroom.id //classroom 是第一步的查詢結果
        第三步:再查詢 student SELECT * FROM student WHERE id=classroom.id //classroom 是第一步的查詢結果
    -->
    <select id="getClassroom3ById" resultMap="getClassroom3Map">
        SELECT * FROM classroom WHERE id=#{id}
    </select>
    <!-- getTeacherById 上面有了,就不重複寫了 -->
    <select id="getStudentById" parameterType="int" resultType="Student">
        SELECT * FROM student WHERE class_id=#{id}
    </select>

    <resultMap type="Classroom" id="getClassroom3Map">
        <association property="teacher" column="teacher_id" select="getTeacherById"></association>
        <collection property="students" column="student_id" select="getStudentById"></collection>
    </resultMap>

    <!-- 
        需求:通過 id 查詢 classroom, 並打印 teacher 和 student 信息
         嵌套結果:使用嵌套結果映射來處理重複的聯合結果的子集,封裝聯表查詢的數據(去除重複的數據)
        SELECT * FROM classroom c, teacher t,student s WHERE c.teacher_id=t.id AND c.id=s.class_id AND c.id=?
     -->
    <select id="getClassroom4ById" parameterType="int" resultMap="getClassroom4Map">
        SELECT * FROM classroom c, teacher t, student s WHERE c.teacher_id=t.id AND c.student_id=s.class_id AND c.id=#{id}
    </select>

    <resultMap type="Classroom" id="getClassroom4Map">
        <id property="id" column="id"/>
        <result property="room" column="room"/>
        <association property="teacher" javaType="Teacher">
            <id property="id" column="id"/>
            <result property="subject" column="subject"/>
        </association>
        <collection property="students" ofType="Student">
            <!-- 
                存在問題
                如果兩表聯查,主表和明細表的主鍵都是id的話,明細表的多條只能查詢出來第一條。
                <id property="id" column="s_id"/>
                解決方法:https://www.cnblogs.com/junge/p/5145881.html
            -->
            <result property="name" column="name"/>
        </collection>
    </resultMap>

</mapper>

測試方法:

// 關聯表的查詢
    @Test
    public void getClassroomById() {
        String statement = "com.itdragon.mapper.ClassroomMapper.getClassroomById";
        Classroom classroom = getSqlSession().selectOne(statement, 1);
        System.out.println(classroom);

        statement = "com.itdragon.mapper.ClassroomMapper.getClassroom2ById";
        classroom = getSqlSession().selectOne(statement, 1);
        System.out.println(classroom);

        statement = "com.itdragon.mapper.ClassroomMapper.getClassroom3ById";
        classroom = getSqlSession().selectOne(statement, 1);
        System.out.println(classroom);

        statement = "com.itdragon.mapper.ClassroomMapper.getClassroom4ById";
        classroom = getSqlSession().selectOne(statement, 1);
        System.out.println(classroom);

    }

5 動態SQL語句

這裏通過模糊查詢 Email 來了解動態SQL語句,在 PersonMapper.xml 中添加如下代碼

<!-- 動態SQL與模糊查詢 -->
    <!-- 
        需求:通過模糊查詢郵箱和指定id範圍查詢數據
        動態SQL:
            if:判斷語句  <if test=''></if> 
            where:去掉多餘的 and 和 or 
                <where><if test=''>AND xxx</if></where>
            set:去掉多餘的 ","
                <set><if test=''>xxx , </if></set>
            trim: 代替 where , set
                if + where == <trim prefix="WHERE" prefixOverrides="AND |OR "></trim>
                if + set == <trim prefix="SET" suffixOverrides=","></trim>
            choose: (when, otherwise) 類似java的switch case default
                <choose><when test="">xxx</when><otherwise>xxx</otherwise></choose>
            foreach:類似java的加強for循環
                <foreach collection="array" item="xxx"  open="(" separator="," close=")"></foreach>
        說明:mybatis 提供了自動生成的逆向工程的工具,這裏只需要瞭解即可,雖然是很重要的知識點
        學習博客:http://limingnihao.iteye.com/blog/782190
    -->

    <select id="getPersonLikeKey" parameterType="Person" resultMap="getPersonMap">
        select * from person where 
        <if test='email != "%null%"'>
             email like #{email} and 
        </if>
        id > #{id}
    </select>

測試方法:

// 調用存儲過程
    @Test
    public void getPersonCountGtId(){
        String statement = "com.itdragon.mapper.PersonMapper.getPersonCountGtId";
        Map<String, Integer> parameterMap = new HashMap<String, Integer>();
        parameterMap.put("personId", 1);
        parameterMap.put("personCount", -1);
        getSqlSession().selectOne(statement, parameterMap);
        Integer result = parameterMap.get("personCount");
        System.out.println(result);
    }

6 存儲過程

引用百度百科:存儲過程(Stored Procedure)是在大型數據庫系統中,一組爲了完成特定功能的SQL 語句集,存儲在數據庫中,經過第一次編譯後再次調用不需要再次編譯,用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。存儲過程是數據庫中的一個重要對象。

這裏通過獲取大於Person id 數量的邏輯來了解Mybatis 是如何調用存儲過程的。首先在Mysql 命令行中執行一下代碼

#創建存儲過程 傳入Id的值,返回id大於該值的數量
DELIMITER $
#在 jpa 數據庫中,創建一個名爲get_person_count的方法,傳入參數是person_id,返回參數是person_count
CREATE PROCEDURE jpa.get_person_count(IN person_id INT, OUT person_count INT) 
BEGIN  
SELECT COUNT(*) FROM jpa.person WHERE person.id > person_id INTO person_count;
END 
$
#調用存儲過程
DELIMITER ;
SET @person_count = 0;
CALL jpa.get_person_count(1, @person_count);
SELECT @person_count;

打印結果如下,則說明創建成功了
![806956-20171112162939372-1875581711.png][3]

還是在 PersonMapper.xml 文件中添加如下代碼

<!-- 調用存儲過程 -->
    <!-- 
        通過id,獲取大於該id的數量
        CALL jpa.get_person_count(1, @person_count);
        注意:需關閉二級緩存
        Caching stored procedures with OUT params is not supported.  Please configure useCache=false in ...
     -->
    <select id="getPersonCountGtId" parameterMap="getPersonCountMap" statementType="CALLABLE">
        CALL jpa.get_person_count(?,?)
    </select>

    <parameterMap type="java.util.Map" id="getPersonCountMap">
        <parameter property="personId" mode="IN" jdbcType="INTEGER"/>
        <parameter property="personCount" mode="OUT" jdbcType="INTEGER"/>
    </parameterMap>

測試方法:

// 調用存儲過程
    @Test
    public void getPersonCountGtId(){
        String statement = "com.itdragon.mapper.PersonMapper.getPersonCountGtId";
        Map<String, Integer> parameterMap = new HashMap<String, Integer>();
        parameterMap.put("personId", 1);
        parameterMap.put("personCount", -1);
        getSqlSession().selectOne(statement, parameterMap);
        Integer result = parameterMap.get("personCount");
        System.out.println(result);
    }

7 一二級緩存

一級緩存:基於PerpetualCache 的 HashMap本地緩存,其存儲作用域爲 Session,當 Session flush 或 close 之後,該Session中的所有 Cache 就將清空。

  ① 若Session 被關閉了,緩存清空

  ② 若數據執行了 創建,更新,刪除操作,緩存清空

  ③ 如果不是同一個Session,緩存失效

二級緩存:與一級緩存其機制相同,不同在於其存儲作用域爲 Mapper(Namespace),並且可自定義存儲源,如 Ehcache。

  ① 默認是關閉的

  ② 是一個映射文件級的緩存,

  ③ 開啓二級緩存

還是在 PersonMapper.xml 文件中添加如下代碼

<!-- 開啓二級緩存 -->
    <!-- 
        eviction="FIFO"          回收策略爲先進先出
        flushInterval="60000"     自動刷新時間60s
        size="512"                最多緩存512個引用對象
        readOnly="true"            只讀
    -->
    <cache 
        eviction="FIFO" 
        flushInterval="60000"
        size="1024"    
        readOnly="true"/>

打印結果如下

log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
[Person [id=2, email=cyy@qq.com, lastName=cyy]]
1
0
Classroom [id=1, room=JavaEE, teacher=Teacher [id=1, subject=Java], students=null]
Classroom [id=1, room=JavaEE, teacher=Teacher [id=1, subject=Java], students=null]
Classroom [id=1, room=JavaEE, teacher=Teacher [id=1, subject=Java], students=[Student [id=1, name=ITDragon], Student [id=2, name=Marry]]]
Classroom [id=1, room=JavaEE, teacher=Teacher [id=1, subject=Java], students=[Student [id=null, name=ITDragon], Student [id=null, name=Marry]]]
[Person [id=1, email=lxl@qq.com, lastName=null], Person [id=2, email=cyy@qq.com, lastName=null], Person [id=3, email=itdrgon@qq.com, lastName=null]]
Person [id=2, email=cyy@qq.com, lastName=null]
Person [id=2, email=cyy@qq.com, lastName=cyy]
Person [id=2, email=cyy@qq.com, lastName=cyy]
2
1

源碼地址:https://github.com/ITDragonBlog/daydayup/tree/master/mybatis/mybatis-basic

到這裏,Mybatis 的入門知識就講完了。如果大家覺得不錯,可以關注我!後續還有很多不錯的內容提供。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章