1. 程式人生 > >【(開課吧javaEE)每日一學190802】mybatis基礎概述與第一個程式

【(開課吧javaEE)每日一學190802】mybatis基礎概述與第一個程式

mybatis簡介

什麼是mybatis

  • MyBatis是一個優秀的持久層框架,它是一個半自動化的ORM框架
  • 它對使用JDBC操作資料庫的過程進行封裝,使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如註冊驅動、建立connection、建立statement、手動設定引數、結果集檢索等jdbc繁雜的過程程式碼。

mybatis在哪寫sql語句

  • Mybatis通過XML或註解的方式,將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來。
  • 並通過java物件和statement中的sql進行對映生成最終執行的sql語句,最後由mybatis框架執行sql並將結果對映成java物件並返回

JDBC程式碼存在問題以及mybatis解決方式

  • 建立資料庫連線相關操作,存在硬編碼 解決方案:通過Mybatis全域性配置檔案,對資料庫連線進行配置

  • statement相關操作,存在硬編碼 解決方案:通過Mapper對映檔案,對statement相關處理進行配置。

  • 頻繁開啟資料庫連線,會降低資料庫處理效能。 解決方案:通過Mybatis全域性配置檔案,配置連線池

mybatis架構原理

  • mybatis配置檔案

    • SqlMapConfig.xml,此檔案作為mybatis的全域性配置檔案,配置了mybatis的執行環境等資訊。
    • Mapper.xml,此檔案作為mybatis的sql對映檔案,檔案中配置了操作資料庫的sql語句。此檔案需要在SqlMapConfig.xml中載入。
  • SqlSessionFactory

    • 通過mybatis環境等配置資訊構造SqlSessionFactory,即會話工廠。
  • sqlSession

    • 通過會話工廠建立sqlSession即會話,程式設計師通過sqlsession會話介面對資料庫進行增刪改查操作。
  • Executor執行器

    • mybatis底層自定義了Executor執行器介面來具體操作資料庫,Executor介面有兩個實現,一個是基本執行器(預設)、一個是快取執行器,sqlsession底層是通過executor介面操作資料庫的。
  • Mapped Statement 它也是mybatis一個底層封裝物件,它包裝了mybatis配置資訊及sql對映資訊等。mapper.xml檔案中一個select\insert\update\delete標籤對應一個Mapped Statement物件,select\insert\update\delete標籤的id即是Mapped statement的id。

    • Mapped Statement對sql執行輸入引數進行定義,包括HashMap、基本型別、pojo,Executor通過Mapped Statement在執行sql前將輸入的java物件對映至sql中,輸入引數對映就是jdbc程式設計中對preparedStatement設定引數。
    • Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本型別、pojo,Executor通過Mapped Statement在執行sql後將輸出結果對映至java物件中,輸出結果對映過程相當於jdbc程式設計中對結果的解析處理過程。

idea中建立maven專案步驟

選擇file之後new project或者new module後來到如下的頁面:

next之後自己輸入專案點group ID,artifacted id,點選next,然後就是配置maven

配置完之後點選finish即可,但是使用idea建立maven專案時是沒有java和resources以及test目錄的,此時需要自己新建,可以參考別人的文章

同樣的如果是需要test資料夾,首先是在src目錄下建立一個普通的資料夾,然後在test目錄下建立java資料夾和resources資料夾並且設定好對應關係即可:

mybatis的第一個小案例

專案整體目錄結構

資料庫

表的建立語句為:

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '使用者名稱稱',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性別',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', '測試1', null, '2', null);
INSERT INTO `user` VALUES ('10', '張三', '2014-07-10', '1', '北京市');
INSERT INTO `user` VALUES ('11', '李四', null, '1', null);
INSERT INTO `user` VALUES ('16', '張小明', null, '1', '河南鄭州');
INSERT INTO `user` VALUES ('22', '陳小明', null, '1', '河南鄭州');
INSERT INTO `user` VALUES ('24', '張三丰', null, '1', '河南鄭州');
INSERT INTO `user` VALUES ('25', '陳小明', null, '1', '河南鄭州');
INSERT INTO `user` VALUES ('26', '王五', null, null, null);

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>
    <!--載入配置檔案-->
    <properties resource="db.properties"></properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>

在主配置檔案中對於使用jdbc連線資料庫時使用了佔位符,因此需要寫資料庫配置檔案,同時在mybatis的主配置檔案中載入了mapper檔案,所以也是需要寫sql對映檔案

資料庫配置檔案db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm
username=root
password=admin

sql對映檔案UserMapper.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">
<!--namespace作用是為了分類管理對映檔案中的MapperdStatement物件-->
<mapper namespace="test">
    <select id="findUserById" parameterType="int" resultType="test.User">
    select * from User where id = #{id}
  </select>
</mapper>

POJO

package test;
import java.util.Date;
public class User {
    private int id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

測試類

package test;


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

import java.io.IOException;
import java.io.InputStream;

public class TestUser {

    // 會話工廠
    private SqlSessionFactory sqlSessionFactory;

    // 該註解可以在@test註解之前執行
    @Before
    public void createSqlSessionFactory() throws IOException {
        // 載入配置檔案
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 使用sqlSessionFactoryBuilder從xml中建立sqlsessionfactory
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void test() {
        SqlSession sqlSession = null;
        sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("test.findUserById", 1);
        System.out.println(user);
        sqlSession.close();
    }
}

至此查詢的小案例完成。

擴充套件

測試模糊查詢

sql對映檔案

還是上面的檔案,只是擴充套件了

<!--${value}表示輸入引數將${value}替換,直接做字串的拼接,如果是取簡單型別的引數,括號中的引數名必須是value-->
    <select id="findUserByUsername" parameterType="java.lang.String" resultType="test.User">
      select * from user where username like '%${value}%'
    </select>

測試程式碼

@Test
    public void testLike() {
        SqlSession sqlSession = null;
        sqlSession = sqlSessionFactory.openSession();
        List<Object> list = sqlSession.selectList("test.findUserByUsername", "張三");
        System.out.println(list.size());
        sqlSession.close();
    }

上面這樣是沒有問題,不過在寫sql對映檔案時說過如果是取簡單型別,這裡只能使用value,比如這裡如果使用hello,會出現下面的報錯:

上面顯示的沒有hello沒有get方法,但是即使我換成username(這是在pojo中有),雖然不報錯但是查詢結果不對。至於mybatis的模糊查詢可以檢視借鑑文章

測試新增

sql對映檔案

insert id="insertUser" parameterType="test.User">
        insert into user(username, birthday, sex, address)
        values (#{username}, #{birthday}, #{sex}, #{address})
    </insert>

測試程式碼

@Test
    public void testInsert() {
        SqlSession sqlSession = null;
        sqlSession = sqlSessionFactory.openSession();
        User user = new User();
        user.setUsername("王五");
        user.setAddress("湖北");
        user.setSex("1");
        user.setBirthday(new Date());
        sqlSession.insert("test.insertUser", user);
        // 提交事務
        sqlSession.commit();
        sqlSession.close();
    }

測試主鍵返回

sql對映檔案

<insert id="insertUser" parameterType="test.User">
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
        </selectKey>
        insert into user(username, birthday, sex, address)
        values (#{username}, #{birthday}, #{sex}, #{address})
    </insert>

新增selectKey標籤實現主鍵返回。

  • keyProperty:指定返回的主鍵,儲存在pojo中的哪個屬性
  • order:selectKey標籤中的sql的執行順序,是相對與insert語句來說。由於mysql的自增原理,執行完insert語句之後才將主鍵生成,所以這裡selectKey的執行順序為after。
  • resultType:返回的主鍵對應的JAVA型別
  • LAST_INSERT_ID():是mysql的函式,返回auto_increment自增列新