1. 程式人生 > 其它 >MyBatis框架快速入門

MyBatis框架快速入門

技術標籤:java

MyBatis框架快速入門

入門案例

建立一個關於Mybatis專案

首先建立一個空專案,然後新建一個moudle,選擇quickstart,接下來把模組放到空專案之下。即可

實現mybatis查詢資料庫的功能

實現步驟:

  1. 新建studnet表
  2. 加入maven的mybatis座標,mysql驅動的座標
  3. 建立實體類,Student–儲存表中的一行資料的
  4. 建立持久層的dao介面,定義操作資料庫的方法
  5. 建立一個mybatis使用的配置檔案,叫做sql對映檔案:寫sql語句的。一般一個表一個sql對映檔案。這個檔案是xml檔案
  6. 建立mybatis的主配置檔案:一個專案就一個主配置檔案。主配置檔案提供了資料庫的連線資訊和sql對映檔案的位置資訊
  7. 建立使用mybatis類,通過mybatis訪問資料庫。

建立mysql資料庫和表

資料庫建立表student

CREATE TABLE `student` (
  `id` int NOT NULL,
  `name` varchar(80) DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
);

在pom.xml中新增相關依賴(加入maven的mybatis座標,mysql驅動的座標)

<!--    mybatis的依賴-->
<
dependency
>
<groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.1</version> </dependency> <!--mysql驅動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId
>
<version>8.0.19</version> </dependency>

可以在左側右鍵pom.xml選擇Maven-Reimport,可以在右側maven專案下的Dependencies下檢視依賴項

建立實體類

studnet實體類(domain包下)

package comipingfan.domain;
//推薦和表明一樣。
public class Student {
    private Integer id;
    private String name;
    private String email;
    private Integer age;
    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 String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

建立dao層下的介面

dao介面(dao包下)

package comipingfan.dao;
import comipingfan.domain.Student;
import java.util.List;
//介面,操作Student表
public interface StudentDao {
    //查詢Student表的所有的資料
    public List<Student> selectStudents();
    //插入方法
    public int insertStudent(Student stu);
}

建立mybatis使用的配置檔案,在介面所在的目錄下

StudentDao.xml(dao包下,sql對映檔案)

<?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="comipingfan.dao.StudentDao">
    <select id="selectStudents" resultType="comipingfan.domain.Student">
        select  id,name,email,age from student order by id
    </select>
    <insert id="insertStudnet">
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>
</mapper>

對sql檔案的解析:

sql對映檔案:寫sql語句的,mybatis會執行這些sql
    1.指定約束檔案:
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

    mybatis-3-mapper.dtd是約束檔案的名稱,副檔名是dtd的。
    2.約束檔案的作用:限制,檢查在當前檔案中出現的標籤,屬性必須符合要求
    3.mapper 是當前問價你的根標籤,必須的。
    namespace:叫做名稱空間,可以是自定義的字串
    要求你使用dao介面的全限定名稱
    4.在當前檔案中,可以使用特定的標籤,表示資料庫的特定操作。
    <select>:表示執行查詢
    <update>:表示更新資料庫的操作

建立mybatis的主配置檔案

在resource下建立mybatis.xml(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>
    <settings>
        <!--設定mybatis輸出日誌-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--環境配置: 資料庫的連線資訊
        default:必須和某個environment的id值一樣。
        告訴mybatis使用哪個資料庫的連線資訊。也就是訪問哪個資料庫
    -->
    <environments default="mydev">
        <environment id="mydev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/springdb?useSSL=false&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="3306"/>
            </dataSource>
        </environment>
    </environments>
    <!-- sql mapper(sql對映檔案)的位置-->
    <mappers>
        <mapper resource="comipingfan/dao/StudentDao.xml"/>
    </mappers>
</configuration>

至此,關於mybatis的配置完成。學過maven的就可以知道點選maven下的compile就能夠對該專案進行編譯。都在target目錄下。此時你可能會發現在你的dao包下只有介面檔案(StudnetDao.class)並沒有(xxx.xml檔案)這是因為預設情況下不會處理xml檔案,需要用過外掛進行編譯。

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

會掃描到properties、xml檔案。

測試

public static void main(String[] args) throws IOException {
        //訪問mybatis讀取Student資料
        //1.定義mybatis主配置檔案的名稱,從類路徑的根開始(target/clasess)
        String config="mybatis.xml";
        //2.讀取這個config表示的檔案
        InputStream in= Resources.getResourceAsStream(config);
        //3.建立了SqlSessionFactoryBuilder物件
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
        //4.建立SqlSessionFactory物件
        SqlSessionFactory factory=builder.build(in);
        //5.獲取SqlSession物件,從SqlSessionFactory中獲取SqlSession
        SqlSession sqlSession=factory.openSession();
        //6.指定執行的sql語句的標識。sql對映檔案中的namespace+"."+標籤的id值
        String sqlId="comipingfan.dao.StudentDao"+"."+"selectStudents";
        //7.執行sql語句
        List<Student>studentList=sqlSession.selectList(sqlId);
        //8.輸出結果
        studentList.forEach(student -> System.out.println(student));
        //9.關閉SqlSession物件
        sqlSession.close();
    }

總結:關於連線資料庫,初學者可能遇到各種各樣的問題,比如找不到mybatis.xml檔案(這是因為mybatis.xml並沒有被編譯到target/classes下。需要在pom中加入外掛)還需要檢查自己的依賴到底是mysql8還是mysql5。另外mybatis-3.5.2需要mysql5.1x以上的版本

優化mybatis的連線操作

建立MyBatisUtiles工具類

public class MyBatisUtiles {
    private static SqlSessionFactory factory=null;
    static {
        String config="mybatis.xml";
        try {
            InputStream in= Resources.getResourceAsStream(config);
            factory=new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //獲取SqlSession方法
    public static SqlSession getSqlSession(){
        SqlSession sqlSession=null;
        if(factory!=null){
            sqlSession=factory.openSession();//非自動提交事務
        }
        return sqlSession;
    }
}

測試

 SqlSession sqlSession= MyBatisUtiles.getSqlSession();
        //指定執行的sql語句的標識。sql對映檔案中的namespace+"."+標籤的id值
        String sqlId="comipingfan.dao.StudentDao"+"."+"selectStudents";
        //執行sql語句
        List<Student>studentList=sqlSession.selectList(sqlId);
        //輸出結果
        studentList.forEach(student -> System.out.println(student));
        //關閉SqlSession物件
        sqlSession.close();

自定義mybatis配置模板

在Editor下的File and Code Templates,點選+好。即可建立模板。

例如建立maper模板

name=mybatis-mapper

<?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="">
    <select id="" resultType="">
      
    </select>
</mapper>

同理,mybatis主配置檔案。

name=mybatis-config

<?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>
    <settings>
        <!--設定mybatis輸出日誌-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--環境配置: 資料庫的連線資訊
        default:必須和某個environment的id值一樣。
        告訴mybatis使用哪個資料庫的連線資訊。也就是訪問哪個資料庫
    -->
    <environments default="mydev8">
        <environment id="mydev8">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/springdb?useSSL=false&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="3306"/>
            </dataSource>
        </environment>
        <environment id="mydev5">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3308/springdb"/>
                <property name="username" value="root"/>
                <property name="password" value="3308"/>
            </dataSource>
        </environment>
    </environments>
    <!-- sql mapper(sql對映檔案)的位置-->
    <mappers>
        <mapper resource="comipingfan/dao/StudentDao.xml"/>
    </mappers>
</configuration>

實現Dao介面的方式訪問資料庫

分析StudentDao介面

我們通過mybatis連線資料庫並進行增刪拆改,可以發現和介面中的方法並沒有直接的關係。正常操作應該是呼叫dao介面中的方法來完成操作的。其實在開發中都是service層來進行訪問資料庫的,而service層去實現dao層的介面的。因此接下來通過實現介面的形式訪問資料庫。

dao層

StudentDao.java

package comipingfan.dao;
import comipingfan.domain.Student;
import java.util.List;
//介面,操作Student表
public interface StudentDao {
    //查詢Student表的所有的資料
    public List<Student> selectStudents();
    //插入方法
    public int insertStudent(Student stu);
}

StudentDao.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="comipingfan.dao.StudentDao">
    <select id="selectStudents" resultType="comipingfan.domain.Student">
        select  id,name,email,age from student order by id
    </select>
    <insert id="insertStudnet">
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>
</mapper>

dao層下的impl包

StudnetDaoImpl.java

public class StudnetDaoImpl implements StudentDao {
    @Override
    public List<Student> selectStudents() {
        SqlSession sqlSession= MyBatisutiles.getSqlSession();
        String sqlId="com.pingfan.dao.StudentDao"+"."+"selectStudents";
        List<Student> list = sqlSession.selectList(sqlId);
        sqlSession.close();
        return list;
    }

    @Override
    public int insertStudent(Student stu) {
        SqlSession sqlSession= MyBatisutiles.getSqlSession();
        String sqlId="com.pingfan.dao.StudentDao"+"."+"insertStudnet";
        int res=sqlSession.insert(sqlId,stu);
        sqlSession.commit();
        sqlSession.close();
        return res;
    }
}

測試:

@Test
public void testSelectStudents(){
    StudentDao dao=new StudnetDaoImpl();
    List<Student> students = dao.selectStudents();
    for(Student stu:students){
        System.out.println(stu);
    }
}

利用動態代理實現Dao介面

上述的實現類StudnetDaoImpl主要作用就是拿到sqlSession物件和sqlId(主要是id和全限定名稱的拼接)。然後去執行相應的方法。而動態代理剛好可以幫我們拿到全限定名稱和id。

分析:

使用mybatis的動態代理機制,使用SqlSession.getMapper(dao介面.class)取這個dao介面的物件
getMapper能獲取dao介面對於的實現類物件
然後就能執行相應的方法

dao層(只需要StudnetDao介面和Studnet.xml)

public interface StudentDao {
    List<Student> selectStudents();
    int insertStudent(Student stu);
}
<?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.item.dao.StudentDao">
    <select id="selectStudents" resultType="com.item.domain.Student">
        select * from student order by id
    </select>
    <insert id="insertStudent" >
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>
</mapper>

測試:(當然獲取SqlSession的工具類和mybatis的主配置檔案上面已給出)

SqlSession sqlSession= MyBatisutiles.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
//呼叫dao的方法,執行資料庫的操作
List<Student>students=dao.selectStudents();
for (Student stu:students){
    System.out.println(stu);
}
SqlSession sqlSession=MyBatisutiles.getSqlSession();
StudentDao dao=sqlSession.getMapper(StudentDao.class);
Student stu=new Student();
stu.setId(1006);
stu.setName("xxx");
stu.setEmail("[email protected]");
stu.setAge(20);
int res = dao.insertStudent(stu);
sqlSession.commit();
System.out.println("res="+res);

深入理解引數

parameterType

介面中方法引數的型別, 型別的完全限定名或別名。這個屬性是可選的,因為 MyBatis 可以推斷出具體傳入語句的引數,預設值為未設定(unset)。介面中方法的引數從 java 程式碼傳入到 mapper 檔案的 sql 語句。

例如:

<delete id="deleteStudent" parameterType="int">
 delete from student where id=#{studentId}
</delete>

等同於

<delete id="deleteStudent" parameterType="java.lang.Integer">
 delete from student where id=#{studentId}
</delete>

當然不寫也是可以的。會自動推斷。

MyBatis 傳遞引數

一個簡單引數

Dao 介面中方法的引數只有一個簡單型別(java 基本型別和 String),佔位符 #{ 任意字元 },和方 法的引數名無關

介面方法: Student selectById(int id);

mapper 檔案:

<select id="selectById" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student where id=#{studentId}
</select>

#{studentId} , studentId 是自定義的變數名稱,和方法引數名無關。

測試:

Student student = studentDao.selectById(1005);
 System.out.println("查詢 id 是 1005 的學生:"+student);

多個引數-使用@Param

當 Dao 介面方法多個引數,需要通過名稱使用引數。在方法形參前面加入@Param(“自定義引數名”), mapper 檔案使用#{自定義引數名}。

例如定義

 List selectStudent( @Param(“personName”) String name ) {} 

mapper 檔案

 select * from student where name = #{ personName}

介面方法:

 List selectMultiParam(@Param("personName") String name, @Param("personAge") int age);

mapper 檔案:

<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student where name=#{personName} or age=#{personAge}
</select>

測試

List<Student> stuList = studentDao.selectMultiParam("李力",20);
 stuList.forEach( stu -> System.out.println(stu));

多個引數-使用物件

使用 java 物件傳遞引數, java 的屬性值就是 sql 需要的引數值。 每一個屬性就是一個引數。

語法格式: #{ property,javaType=java 中資料型別名,jdbcType=資料型別名稱 } javaType, jdbcType 的型別 MyBatis 可以檢測出來,一般不需要設定。常用格式 #{ property }

綜上:使用常用格式即可。

建立儲存引數值的物件 QueryParam

package com.bjpowernode.vo;
public class QueryParam {
 private String queryName;
 private int queryAge;
 //set ,get 方法
}

介面方法:

List<Student> selectMultiObject(QueryParam queryParam);

mapper 檔案:

<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student where name=#{queryName} or age
=#{queryAge}
</select><select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
 select id,name,email,age from student
 where name=#{queryName,javaType=string,jdbcType=VARCHAR}
 or age =#{queryAge,javaType=int,jdbcType=INTEGER}
</select>

測試:

QueryParam qp = new QueryParam();
 qp.setQueryName("李力");
 qp.setQueryAge(20);
 List<Student> stuList = studentDao.selectMultiObject(qp);
 stuList.forEach( stu -> System.out.println(stu));

問題彙總

resource下的mybatis.xml檔案找不到

當你用IDEA右側maven執行clear和compile命令時,如果不加

<resource>
    <directory>src/main/resources</directory>
    <includes>
        <include>**/*.properties</include>
        <include>**/*.xml</include>
    </includes>
    <filtering>false</filtering>
</resource>

則會找不到mybatis.xml檔案。但是如果你一開始就沒有target目錄,而是通過main函式執行或者run-test,則mybatix.xml會被放到target目錄下。所以建議還是放下(一個是編譯src/main下一個是resource下)。

<build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
  </build>