1. 程式人生 > >(一)Mybatis入門之第一個程式

(一)Mybatis入門之第一個程式

1.框架是什麼

  • 框架(Framework)是整個或部分系統的可重用設計,表現為一組抽象構件及構件例項間互動的方法;另一種定義認為,框架是可被應用開發者定製的應用骨架。前者是從應用方面而後者是從目的方面給出的定義。
  • 一個框架是一個可複用的設計構件,它規定了應用的體系結構,闡明瞭整個設計、協作構件之間的依賴關係、責任分配和控制流程,表現為一組抽象類以及其例項之間協作的方法,它為構件複用提供了上下文(Context)關係。因此構件庫的大規模重用也需要框架。
  • 個人理解:框架最重要的是把我們常用的,可以重複使用的功能抽象出來,不需要我們去重複寫,我們只需要呼叫,或者按照規定配置,按照規則使用就可以了。這樣的缺點是很多時候我們不知道為什麼可以這樣子使用,裡面實現的細節被遮蔽掉了,這也是很多初學者很懵逼的地方,這時候追根問底就有一定必要性了。

2.Mybatis的介紹

Mybatis本來是Apache的一個開源專案iBatis,這個專案2010年由apache遷移到了google,更名為Mybatis,2013年正式遷移到Gihub。
Mybatis是一個java中一個持久層的框架,在裡面封裝了jdbc操作,如果還不瞭解java如何使用jdbc訪問資料庫,那麼可以檢視這篇文章,封裝使開發者只需要把精力放在開發sql語句上,不用去註冊驅動,建立Connection,配置Statement,自己寫程式碼管理事物等等。
Mybatis通過xml或者註解的方式將需要執行的statement配置好,通過對映將java物件與sql中的動態引數一起生成最終的sql語句,執行完之後返回物件,其中也是對映的結果。

3.Mybatis和Hibernate對比

1.Hibernate是全自動的ORM框架,也就是完全實現了POJO和資料庫表之間的對映,會自動生成SQL。但是Mybatis不會自動生成,SQL還是需要自己寫,但是對映關係框架會自動處理,這樣一個好處就是可以看得到SQL,很多時候系統自動生成SQL並不是高效的,我們有時候需要優化SQL,或者一些複雜的查詢可能自動化的很難做到,缺點就是需要花時間寫。
2.使用XML檔案進行配置,分離了了sql與程式碼,這樣比較容易維護。
3.Mybatis是一個輕量級的框架。學習成本比Hibernate低很多,jar包依賴也很少,上手比較快。

4.Mybatis的結構圖:





Mybatis的執行機制:我們通過配置Mybatis.xml(裡面配置好資料庫,需要掃描的mapper.xml檔案等),程式會自動掃描配置好的mapper檔案,當我們請求一個介面(請求資料庫),介面會直接對映到對應的sql標籤,同時將我們所寫的配置檔案讀取並將資料庫欄位與物件屬性匹配(這也是對映,如果不一致,需要自己手寫對映關係),將sql引數傳進去,然後執行相關的sql,返回時又做了一次對映,把物件返回給我們。當然,這麼描述是很表面的,因為mybatis還有事務,快取等方面,以上只是大概。





5.IDEA建立第一個程式

5.1建立mysql資料庫
CREATE DATABASE `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE `student` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(20) NOT NULL , 
`age` INT NOT NULL , `score` DOUBLE NOT NULL , PRIMARY KEY (`id`)) ENGINE = MyISAM; 
5.2 使用idea建立專案(Maven)

專案結構圖(bean下面放的類對應我們的資料庫裡面的student表,也就是它的一個實體類,dao包下面放著我們的資料庫的操作,resources下面放著我們的xml或者各種資源):





new –> Project –>點選Maven




點選next,GroupId,ArtifactId可以自己指定,點選下一步




自己指定project name(專案名),點選finish




往pom.xml裡面新增依賴,每一個之間都是一種依賴包,選中專案右鍵–> Maven –> Reimport,這樣就可以下載我們所需要的依賴了:
    <dependencies>
        <!-- mybatis核心包 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.3.0</version>
        </dependency>
        <!-- mysql驅動包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.29</version>
        </dependency>
        <!-- junit測試包 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!-- 日誌檔案管理包 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version> 
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
    </dependencies>

為了能實現日誌的列印功能,我們在pom.xml檔案中已經引入了標籤,在這裡還需要在resources資料夾下新建配置log4j.properties檔案,具體配置代表什麼意思,可以參考log4j 與log4j2詳解

log4j.properties

log4j.rootLogger=DEBUG, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[service] %d - %c -%-4r [%t] %-5p %c %x - %m%n

#log4j.appender.R=org.apache.log4j.DailyRollingFileAppender    
#log4j.appender.R.File=../logs/service.log    
#log4j.appender.R.layout=org.apache.log4j.PatternLayout    
#log4j.appender.R.layout.ConversionPattern=[service] %d - %c -%-4r [%t] %-5p %c %x - %m%n    

#log4j.logger.com.ibatis = debug    
#log4j.logger.com.ibatis.common.jdbc.SimpleDataSource = debug    
#log4j.logger.com.ibatis.common.jdbc.ScriptRunner = debug    
#log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate = debug    
#log4j.logger.java.sql.Connection = debug    
log4j.logger.java.sql.Statement = debug
log4j.logger.java.sql.PreparedStatement = debug
log4j.logger.java.sql.ResultSet =debug

配置好這些之後,前面結構圖上面寫到有一個mybatis.xml檔案,裡面配置了執行的環境(關於資料庫的連線),連線的資料庫可以配置多個,但是必須指定使用哪一個,這樣做的原因的世界在xml檔案進行修改不需要重新編譯,更換資料庫比較簡單,除此之外,裡面還需要配置mapper.xml,也就是對映檔案,我們要告訴它,我們將sql配置寫在哪個檔案。

mybatis.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>
        <!-- 配置執行環境 -->
        <!-- default 表示預設使用哪一個環境,可以配置多個,比如開發時的測試環境,上線後的正式環境等 -->
        <environments default="mysqlEM">        
            <environment id="mysqlEM">
                <transactionManager type="JDBC">        
                </transactionManager>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
            <environment id="testEM">
                <transactionManager type="JDBC">
                </transactionManager>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <!-- 註冊對映檔案 -->
        <mappers>
            <mapper resource="mapper.xml"/>
        </mappers>
  </configuration>

配置好mybatis.xml檔案我們就需要寫sql語句,根據上面的mybatis.xml,我們需要寫mapper.xml檔案,下面的namespace現在可以隨意命名,因為只有一個mapper.xml檔案,sql標籤的id沒有重複,執行時就是根據id來查詢的,同時這裡parameterType對應的是引數型別,型別要寫帶完整路徑名的類:

mapper.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="abc">
    <insert id="insertStudent" parameterType="bean.Student">
        insert into student(name,age,score) values(#{name},#{age},#{score})
    </insert>
</mapper>

在bean包下面建立與資料庫對應的Student類【在bean包下】(這裡先把屬性名字和資料庫的欄位名一致,如果不一致需要自己寫對映),注意裡面的方法我們需要實現set和get方法,這個在IDEA裡面,開啟當前類,右鍵–> Gernarate –>setter and getter全選就可以生成。

Student.class

package bean;
public class Student {
    // id屬性
    private Integer id;
    // 名字屬性
    private String name;
    // 年齡屬性
    private int age;
    //分數屬性
    private double score;
    // 構造方法,除了id,因為我們的id在資料庫中是自增的
    public Student( String name, int age, double score) {
        super();
        this.name = name;
        this.age = age;
        this.score = score;
    }
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public double getScore() {
        return score;
    }
    public void setScore(double score) {
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + ", age=" + age
                + ", score=" + score + "]";
    }

}

在這裡我們需要寫一個介面,來表示操作學生資訊,先寫一個插入學生資訊的介面,那麼肯定是傳一個學生物件進去。

IStduent.class

package dao;
import bean.Student;
public interface IStudentDao {
    public void insertStu(Student student);
}

下面就是介面的實現類(重點):

StudentDaoImpl.class

package dao;
import java.io.IOException;
import java.io.InputStream;
import bean.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class StudentDaoImpl implements IStudentDao {
    // 實現插入的介面方法
    public void insertStu(Student student) {
        try {
            InputStream inputStream;
            // 讀取配置資訊的檔案
            inputStream = Resources.getResourceAsStream("mybatis.xml");
            // 由於這個檔案裡面配置了mapper.xml,框架會幫我們掃描這些mapper.xml,下面是初始化一個SqlSessionFactory物件
            SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
            // 工廠會獲取一個SqlSession物件
            SqlSession sqlSession=sqlSessionFactory.openSession();
            // 通過這個物件可以查詢之前mapper.xml裡面配置好的sql的id與 `insertStudent`相等的,執行對應的sql
            sqlSession.insert("insertStudent",student);
        } catch (IOException e) {

            e.printStackTrace();
        }

    }

}

測試方法,如果不瞭解Junit測試請參考Junit測試詳解

MyTest.class

import bean.Student;
import dao.IStudentDao;
import dao.StudentDaoImpl;
import org.junit.Before;
import org.junit.Test;
public class MyTest {
    private IStudentDao dao;
    @Before
    public void Before(){
        dao=new StudentDaoImpl();
    }
    @Test
    public void testInsert(){
        Student student=new Student("1ADAS",23,94.6);
        dao.insertStu(student);
    }
}

測試的結果,從最後三行我們可以看到執行的sql語句,以及引數等:





5.3 使用eclips,MyEclipse建立專案(Maven)

區別不大,直接建立java Project,如果下面沒有lib這個檔案,就要新建一個,然後把需要的包導(複製貼上)進去,選中lib下面所有的包,右鍵–>Build Path–> Add to Path


下面是myEclipse下面的結構圖,程式碼沒有改變,需要自己下載相關的包


  • 宣告:這樣的寫法不是最好的,但是這是初學者最容易接受的寫法,後面我們會慢慢的精簡,我們到時候不需要寫介面的實現類,同時會把關於sqlSessionFactory相關的操作抽取出來成為一個工具類,就不用寫那麼多相同的程式碼了。