Spring學習手冊(13)—— Spring整合mybatis

Spring學習手冊(12)—— Spring JDBC數(shù)據(jù)庫訪問我們學習了如何使用Spring的JDBC抽象進行數(shù)據(jù)庫訪問涩盾,這極大的簡化了開發(fā)者的工作量:不需要關心數(shù)據(jù)庫連接、關閉蚀之;查詢語句的構(gòu)造闽烙、執(zhí)行......但我們依然需要使用?來占空查詢參數(shù)翅睛、解析查詢返回結(jié)果集。本文我們就來學習對象關系映射(Object Relational Mapping (ORM))訪問數(shù)據(jù)庫黑竞。本文主要學習當下較為流行的mybatis框架捕发。

一、mybatis簡介

MyBatis 是支持定制化 SQL很魂、存儲過程以及高級映射的優(yōu)秀的持久層框架扎酷。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數(shù)以及獲取結(jié)果集。MyBatis 可以對配置和原生Map使用簡單的 XML 或注解遏匆,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數(shù)據(jù)庫中的記錄法挨。
在2.0版本之前谁榜,該框架叫ibatis,后3.0版本更名為mybatis凡纳。由于Spring官方只整合了ibatis2窃植,mybati社區(qū)為在Spring中支持mybatis,創(chuàng)建了mybatis-spring子項目使mybaits無縫的整合到Spring中去。

二惫企、引入相關jar包依賴

Spring項目整合mybatis框架需要依賴mybatis和mybatis-spring jar包撕瞧,因此我們需要首先添加該依賴。build.gradle文件依賴項修改如下:

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
    compile 'mysql:mysql-connector-java:6.0.6'
    compile 'org.mybatis:mybatis:3.4.2'
    compile 'org.mybatis:mybatis-spring:1.3.1'
    compile 'org.springframework:spring-jdbc:4.3.6.RELEASE'
    compile 'org.springframework:spring-context:4.3.6.RELEASE'
}

這里mybatis版本號為3.4.2狞尔,mybatis-spring版本號為1.3.1丛版。IDEA會自動編譯項目下載依賴jiar包,當然你也可以在項目根目錄下運行如下命令編譯(已將gradle添加到path目錄):

  gradle build

三偏序、spring整合mybatis實戰(zhàn)

我們添加了相關Jar包的依賴页畦,本節(jié)我們就來展示如何在Spring中整合mybatis。
在開始代碼實例之前研儒,我們首先新建數(shù)據(jù)庫score_manager(數(shù)據(jù)庫名可任意命名豫缨,但需保持dataSource中URL配置根數(shù)據(jù)庫名一致)、新建數(shù)據(jù)表student端朵,表結(jié)構(gòu)如下:

列名 類型
id int
name varchar(20)
gender char(1)
age int

同時我們創(chuàng)建Student領域模型如下:

public class Student {

    private int id;

    private String name;

    private String gender;

    private int age;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString(){
        return "["+id+"好芭,"+name+","+gender+","+age+"]";
    }
}

3.1 創(chuàng)建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="com.liangwei.learnspring.dao.StudentMapper">

    <resultMap id="student" type="com.liangwei.learnspring.domain.Student">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="gender" column="gender"/>
        <result property="age" column="age"/>
    </resultMap>

    <select id="getStudentNums" resultType="int">
        select count(*) from student
    </select>

    <select id="getStudentById" resultMap="student">
        select * from student where id=#{studentId}
    </select>

    <insert id="insertStudent" parameterType="com.liangwei.learnspring.domain.Student">
        insert student
            (id,name,gender,age)
        values(
             #{id},
             #{name},
             #{gender},
             #{age})
    </insert>

    <delete id="deleteStudent" parameterType="int">
        delete from student where id = #{studentId}
    </delete>
    
    <update id="updateStudent" parameterType="com.liangwei.learnspring.domain.Student">
        update student set gender = #{gender} where id = #{id}
    </update>
</mapper>

我們使用mapper標簽創(chuàng)建映射文件,并且使用namespace屬性指定該mapper的命名空間冲呢,這里我們將命名空間設定為com.liangwei.learnspring.dao.StudentMapper,舍败,之所以如此設置會在后面進行講解。
我們使用resultMap標簽定義了一個返回結(jié)果集的映射關系敬拓,其中idresult內(nèi)部標簽都是表示返回對象和數(shù)據(jù)庫某列的映射關系邻薯,id指代數(shù)據(jù)庫的表主鍵,提升mybatis運行效率乘凸。property屬性表示定義領域?qū)ο蟮膶傩悦Q厕诡,column屬性指定了數(shù)據(jù)表中的列名。定義好resultMap营勤,mybatis就會自動為我們完成結(jié)果集和領域?qū)ο笾g的互相轉(zhuǎn)換灵嫌。
我們分別使用insertdelete葛作、select寿羞、update來定義增刪查改語句,id用于唯一表示該語句进鸠,parameterType指向該語句可接受的參數(shù)稠曼,resultMap屬性設置為前面使用resultMap標簽設置的id值,mybatis就會自動將查詢結(jié)果進行映射。

3.2 定義DataSource

<!--datasource 定義-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/score_manager"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

3.3 定義SqlSessionFactoryBean

在 MyBatis-Spring 中,我們使用SqlSessionFactoryBean來創(chuàng)建Session工廠霞幅,配置信息如下:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/>
    </bean>

dataSource屬性為前面已經(jīng)配置完成的DataSource漠吻,mapperLocations屬性指向我們配置的SQL映射文件,這里我們設置為classpath路徑下mapper文件夾下的所有以Mapper命名結(jié)尾的XML文件司恳。

3.4 使用SqlSessionTemplate

SqlSessionTemplate類是 MyBatis-Spring 的核心途乃。 這個類負責管理 MyBatis 的 SqlSession, 調(diào)用 MyBatis 的 SQL 方法, 翻譯異常。 SqlSessionTemplate 是線程安全的, 可以被多個 DAO 所共享使用扔傅。
SqlSessionTemplate 實現(xiàn)了 SqlSession 接口,我們使用它來定義sqlSession,配置方式如下:

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory" />
    </bean>

其中構(gòu)造器參數(shù)傳入配置好的sqlSessionFactory耍共。

定義StudentDAO,接口定義如下:

public interface StudentDAO {

    Student getStudentById(int studentId);

    int getStudentNums();

    void insertStudent(Student student);

    void deleteStudent(int studentId);

    void updateStudent(Student student);
}

接口方法命名自解釋猎塞,這里就不再對每個方法的意義進行解釋试读。
對StudentDAO方式實現(xiàn)如下:

public class StudentDAOImpl implements StudentDAO{

    private SqlSession sqlSession;

    public Student getStudentById(int studentId) {
        return sqlSession.selectOne("getStudentById",studentId);
    }

    public int getStudentNums() {

        return  sqlSession.selectOne("getStudentNums");
    }

    public void insertStudent(Student student) {
        sqlSession.insert("insertStudent",student);
    }

    public void deleteStudent(int studentId) {
        sqlSession.delete("deleteStudent",studentId);
    }

    public void updateStudent(Student student) {
        sqlSession.update("updateStudent",student);
    }

    public void setSqlSession(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }
}

該實現(xiàn)持有SqlSession類型的私有屬性,我們使用set方法進行注入荠耽,XML配置方式如下:

 <bean id="studentDao" class="com.liangwei.learnspring.dao.impl.StudentDAOImpl">
        <property name="sqlSession" ref="sqlSession"/>
 </bean>

以上我們使用SqlSessionTemplate完成了Spring中整合mybatis的工作钩骇,我們?yōu)槊糠N領域?qū)ο蟮牟僮鞫xDAO接口并實現(xiàn),我們需要為所有的DAO實現(xiàn)注入sqlSession铝量。

3.5 使用SqlSessionDaoSupport(簡單點)

我們使用SqlSessionTemplate極大的簡化了我們對SQL的操作倘屹,但是我們依然需要為每一個實現(xiàn)類添加setter注入方法,當然我們可以定義基類然后讓所有的DAO實現(xiàn)繼承該基類慢叨,然后使用Spring提供的自動注入簡化代碼量纽匙。本節(jié)我們學習使用SqlSessionDaoSupport類,它相當于封裝了SqlSessionTemplate的基類拍谐,我們只需要使用getSqlSession()來獲取一個SqlSessionTemplate,剩下的操作就和SqlSessionTemplate的調(diào)用相同了烛缔。

定義StudentDAOSupport接口:

public interface StudentDAOSupport {

    Student getStudentById(int studentId);

    int getStudentNums();

    void insertStudent(Student student);

    void deleteStudent(int studentId);

    void updateStudent(Student student);

StudentDAOSupport接口實現(xiàn):

public class StudentDAOSupportImpl  extends SqlSessionDaoSupport implements StudentDAOSupport {

    public Student getStudentById(int studentId) {
        return getSqlSession().selectOne("getStudentById",studentId);
    }

    public int getStudentNums() {
        return  getSqlSession().selectOne("getStudentNums");
    }

    public void insertStudent(Student student) {

        getSqlSession().insert("insertStudent",student);
    }

    public void deleteStudent(int studentId) {

        getSqlSession().delete("deleteStudent",studentId);
    }

    public void updateStudent(Student student) {
        getSqlSession().update("updateStudent",student);
    }
}

XML配置提供id為studentDaoSupport的bean:

<bean id="studentDaoSupport" class="com.liangwei.learnspring.dao.impl.StudentDAOSupportImpl">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

SqlSessionDaoSupport 需要一個 sqlSessionFactory 或 sqlSessionTemplate 屬性來 設 置 。 以上我們使用顯式的方式設置sqlSessionFactory屬性赠尾,SqlSessionDaoSupport會使用sqlSessionFactory來創(chuàng)建一個SqlSessionTemplate實例力穗,當然我們也可以使用Spring的自動注入來省去配置代碼毅弧。 如 果 兩 者 都 被 設 置 了 , 那 么 SqlSessionFactory 是被忽略的气嫁。

3.6 注入映射器(再簡單點)

SqlSessionTemplateSqlSessionDaoSupport已明顯的減少了我們關于數(shù)據(jù)操作的代碼量寸宵,而mybatis提供了映射器方式,為進一步減少代碼量提供了支持。mybatis使用代理類為我們簡化了具體的接口實現(xiàn)代碼七扰。

定義映射器接口:

public interface StudentMapper {

    Student getStudentById(int studentId);

    int getStudentNums();

    void insertStudent(Student student);

    void deleteStudent(int studentId);

    void updateStudent(Student student);
}

配置映射器,使mybatis完成映射器注入:

<bean id="studentMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.liangwei.learnspring.dao.StudentMapper" />
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

我們使用org.mybatis.spring.mapper.MapperFactoryBean定義名為studentMapper的bean。需要為該bean提供mapperInterfacesqlSessionFactory屬性锐膜。sqlSessionFactory我們已多次使用,這里就不過多贅述捞奕;mapperInterface為我們定義的映射器接口(一般命名使用Mapper結(jié)尾)恨搓,上面例子中就是我們定義的StudentMapper接口斧抱。
這樣mybatis會自動為該映射器接口創(chuàng)建代理,并關聯(lián)相關的SQL文件定義(我們在定義sqlSessionFactory時已經(jīng)明確制定要加載的SQL映射文件位置)掂恕。只需這樣兩步乎串,我們完成了映射器接入工作鸯两。
??如果你對我們前面定義的SQL映射文件還有印象鸠匀,應該還記得mapper標簽下有個namespace屬性缀棍,我們設置為com.liangwei.learnspring.dao.StudentMapper,當時之所以如此設置就是為了使其支持映射器方式(目前SqlSessionTemplateSqlSessionDaoSupport方式并沒有強制限制該namespace屬性),如果namespace屬性設置與映射器接口完全限定名不同,則會報方法為找到等類型錯誤哑诊。

更簡單點

當我們需要配置多個映射器時缴饭,按照以上方式的配置也是會花費較多的時間精力担猛,mybatis為我們提供了更方便的方式:使用MapperScannerConfigurer配置智嚷。它會在類路徑下查找映射器稍浆,并將它們創(chuàng)建為MapperFactoryBean。
配置方式:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="com.liangwei.learnspring.dao" />
</bean>

這樣它會為dao包名下的所有映射器類創(chuàng)建為MapperFactoryBean。當然在現(xiàn)實項目實踐中,我們一般將包名命名為mapper結(jié)尾陪竿,如上我們可以改成com.liangwei.learnspring.dao.mapper闰挡,這樣更方便我們閱讀并理解維護代碼。當我們需要設置多個包路徑時礁哄,我們可以使用分號或逗號進行分割解总。

3.7 代碼測試

以上我們使用不同的三種方式整合Spring和mybatis,我們定義了名為studentDao姐仅、studentDaoSupport花枫、studentMapper的三個bean,我們可以獲取它們并直接使用它們的方法掏膏,測試代碼如下:

public class Application {

    public static void main(String[] args){


        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("dao.xml");


        /*  獲取bean */
        StudentDAO studentDAO = applicationContext.getBean("studentDao", StudentDAO.class);

        /* 獲取學生數(shù)量 */
        System.out.println(studentDAO.getStudentNums());

        /* 查找學生ID為1 的學生信息*/
        System.out.println(studentDAO.getStudentById(1));

        Student student = new Student();
        student.setId(3);
        student.setName("Jane");
        student.setGender("F");
        student.setAge(20);
        /* 插入新數(shù)據(jù) */
        studentDAO.insertStudent(student);
        /* 查詢新插入的數(shù)據(jù)劳翰,ID=3 */
        System.out.println(studentDAO.getStudentById(3));

        student.setGender("M");
        /* 更新學生數(shù)據(jù)信息,將性別改為M */
        studentDAO.updateStudent(student);
        System.out.println(studentDAO.getStudentById(3));

        /*刪除studentID為3 的學生信息*/
        studentDAO.deleteStudent(3);


        /*  SqlSessionDaoSupport使用  */

        StudentDAOSupport studentDAOSupport = applicationContext.getBean("studentDaoSupport", StudentDAOSupport.class);

        System.out.println(studentDAOSupport.getStudentNums());

        System.out.println(studentDAOSupport.getStudentById(1));
        student.setGender("F");
        studentDAOSupport.insertStudent(student);
        System.out.println(studentDAOSupport.getStudentById(3));

        student.setGender("M");
        studentDAOSupport.updateStudent(student);
        System.out.println(studentDAOSupport.getStudentById(3));
        studentDAOSupport.deleteStudent(3);

        /* StudentMapper */
        StudentMapper studentMapper = applicationContext.getBean("studentMapper", StudentMapper.class);

        System.out.println(studentMapper.getStudentNums());

        System.out.println(studentMapper.getStudentById(1));

        student.setGender("F");
        studentMapper.insertStudent(student);

        System.out.println(studentMapper.getStudentById(3));
        student.setGender("M");
        studentMapper.updateStudent(student);
        System.out.println(studentMapper.getStudentById(3));

        studentMapper.deleteStudent(3);
    }
}

如上我們對每種方式的沒種接口方法進行了調(diào)用馒疹,代碼較為簡單且結(jié)合注釋很容易理解佳簸,這里我們就不更進一步解釋了。
運行上述代碼颖变,我們會在控制臺得到如下信息輸出:

2 //數(shù)據(jù)庫中學生個數(shù)
[1生均,Jone,F,20] //查詢studentId為1 的學生信息
[3,Jane,F,20] //插入studentId為3的學生信息后的查詢結(jié)果
[3腥刹,Jane,M,20]//更新了studentId為3的學生信息后的查詢結(jié)果:性別更改為M
2
[1马胧,Jone,F,20]
[3,Jane,F,20]
[3衔峰,Jane,M,20]
2
[1佩脊,Jone,F,20]
[3蛙粘,Jane,F,20]
[3,Jane,M,20]

為方便理解輸出信息威彰,我們在輸出信息上加了些注釋出牧,結(jié)合測試代碼和注釋可以更方便的理解輸出結(jié)果。

代碼下載

四歇盼、總結(jié)

本文我們完成了在Spring框架下mybatis的引入和整合舔痕,我們借助mybatis-spring項目使用三種不同的方式(SqlSessionTemplateSqlSessionDaoSupport映射器)完成整合工作豹缀。通過以上一步步的操作我們已經(jīng)體會到mybatis的簡便性赵讯、易操作性,它拆分了SQL語句和項目代碼接口的依賴耿眉,減輕繁瑣的數(shù)據(jù)庫模版代碼操作边翼,極大的提升了程序開發(fā)人員工作效率。
完成Spring框架內(nèi)整合mybatis后鸣剪,我們剩下的主要工作就是定義DAO或Mapper接口组底,編寫映射器的XML文件,mybatis官網(wǎng)已經(jīng)給出來了較為詳細的文檔筐骇,大家可以到官網(wǎng)查看文檔學習债鸡,這里也不打算寫關于XML文件編寫方便的語法文章了。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铛纬,一起剝皮案震驚了整個濱河市厌均,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌告唆,老刑警劉巖棺弊,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異擒悬,居然都是意外死亡模她,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門懂牧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侈净,“玉大人,你說我怎么就攤上這事僧凤⌒笳欤” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵躯保,是天一觀的道長旋膳。 經(jīng)常有香客問我,道長吻氧,這世上最難降的妖魔是什么溺忧? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任咏连,我火速辦了婚禮盯孙,結(jié)果婚禮上鲁森,老公的妹妹穿的比我還像新娘。我一直安慰自己振惰,他們只是感情好歌溉,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著骑晶,像睡著了一般痛垛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上桶蛔,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天匙头,我揣著相機與錄音,去河邊找鬼仔雷。 笑死蹂析,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的碟婆。 我是一名探鬼主播电抚,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼竖共!你這毒婦竟也來了蝙叛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤公给,失蹤者是張志新(化名)和其女友劉穎借帘,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淌铐,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡姻蚓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了匣沼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狰挡。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖释涛,靈堂內(nèi)的尸體忽然破棺而出加叁,到底是詐尸還是另有隱情,我是刑警寧澤唇撬,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布它匕,位于F島的核電站,受9級特大地震影響窖认,放射性物質(zhì)發(fā)生泄漏豫柬。R本人自食惡果不足惜告希,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望烧给。 院中可真熱鬧燕偶,春花似錦、人聲如沸础嫡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽榴鼎。三九已至伯诬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巫财,已是汗流浹背盗似。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留平项,地道東北人赫舒。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像葵礼,于是被迫代替她去往敵國和親号阿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 1. 簡介 1.1 什么是 MyBatis 鸳粉? MyBatis 是支持定制化 SQL扔涧、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,510評論 0 4
  • 單獨使用mybatis是有很多限制的(比如無法實現(xiàn)跨越多個session的事務),而且很多業(yè)務系統(tǒng)本來就是使用sp...
    七寸知架構(gòu)閱讀 3,444評論 0 53
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理届谈,服務發(fā)現(xiàn)枯夜,斷路器,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • Spring 技術筆記Day 1 預熱知識一艰山、 基本術語Blob類型湖雹,二進制對象Object Graph:對象圖...
    OchardBird閱讀 973評論 0 2
  • 官方文檔 簡介 入門 XML配置 XML映射文件 動態(tài)SQL Java API SQL語句構(gòu)建器 日志 一、 JD...
    拾壹北閱讀 3,544評論 0 52