數據庫開發 - MyBatis進階

#MyBatis進階java

  • 複雜Java對象與多張數據庫表之間的映射關係
  • 配置數據庫鏈接池提升MyBatis對後端數據庫訪問的性能 ##更爲複雜的E-R圖 學員對課程是多對多關係,而教員與課程是一對多關係
    • 學員 User
    • 課程 Couser
    • 教員 Author

以上實體對應的關係圖以下:
輸入圖片說明
以上關係對應的數據庫表關係以下:
輸入圖片說明
各個實體都具備對應的屬性,可是因爲User與Cousre是多對多關係,則咱們還須要一個多對多關係表UserCourse,來保存User與Course的關係。因爲Teacher與Course是一對多的關係,則咱們在Course中添加Teacher的惟一標示。mysql

##複雜對象關係sql

  • Java對象
    • 關聯 輸入圖片說明
    • 容器
    • 嵌套 輸入圖片說明

##ResultMap 複雜Java關係映射解決,幫助咱們複雜對象到多張數據庫表的轉換。數據庫

  • ResultMap元素師MyBatis中最重要最強大的元素。
  • 數據庫永遠不是你想要的或須要它們是什麼樣的。
  • ResultMap能夠實現複雜查詢結果到複雜對象關聯關係的轉化。

##Constructor 經過構造方法的方式,對對象進行賦值創建映射關係,這種方法通常用於處理關聯時,使用。apache

  • 類在實例化時,用對象的構造函數注入到對象中:
    • idArg - ID參數;標記結果做爲ID能夠幫助提升總體效能
    • arg - 注入到構造方法的一個普通結果

##ResultMap經過構造函數實例 ###定義了MyBatis-conf.xml的SqlSessionFactory的配置文件後端

<?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>
    <environments default="development">
        <environment id="development">
            <!-- 事務管理 -->
            <transactionManager type="jdbc">
                <!--<property name="..." value="..."/>-->
            </transactionManager>
            <!-- 數據庫鏈接數據源 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.1.200/cloud_study"/>
                <property name="username" value="root"/>
                <property name="password" value="dVHJtG0T:pf*"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/hava/cloud_study/repository/userMapper.xml" />
    </mappers>
</configuration>

###聲明Java對象 ####User服務器

public class User {
    private int id;
    private String userName;
    private String corp;
    private List<Course> courses;
    ...
    //Getter and Setter
}

####Coursesession

public class Course {
    private int id;
    private String courseName;
    private Teacher teacher;
    ...
    //Getter and Setter
}

####Teachermybatis

public class Teacher {
    private int id;
    private String teacherName;
    ...
    //Getter and Setter
}

###UserOp接口 咱們經過獲取用戶的方式,來獲取三張數據庫表之間的鏈接查詢,並創建三個對象之間的鏈接關係。app

package com.hava.cloud_study.repository;

import com.hava.cloud_study.entity.User;

/**
 * Created by zhanpeng on 09/10/2016.
 */
public interface UserOp {

    public User getUser(int id);

}

###resultMap核心Mapper 在Mapper文件中添加resultMap的標籤屬性,id在所表示的這個resultMap將會被用在增持該查中設置中。type表示爲要轉換的對象結果。constructor標籤下面表示的是該類的屬性(非鏈接關係的屬性),idArg表示爲行記錄的惟一id,arg表示通常屬性。column必須和對象的屬性名稱相一致。javaType對應的Java的數據類型。

<?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.hava.cloud_study.repository.UserOp">
    <select id="getUser" parameterType="int" resultMap="UserMap">
        select u.id
        as userId,userName,courseName,corp,c.id as courseId,teacher.id as
        teacherId,teacherName from user u left
        join
        UserCourse uc on u.id
        =uc.user_id left join course c on c.id =
        uc.course_id left join teacher
        on teacher.id = c.teacher_id where u.id
        = #{id}
    </select>

    <resultMap id="UserMap"
               type="com.hava.cloud_study.entity.User">
        <constructor>
            <idArg column="userId" javaType="int" />
            <arg column="userName" javaType="String" />
            <arg column="corp" javaType="String" />
        </constructor>
        <collection property="courses"
                    ofType="com.hava.cloud_study.entity.Course">
            <id property="id" column="courseId" />
            <result property="courseName" column="courseName" />
            <association property="teacher" column="teacher_id"

                         javaType="com.hava.cloud_study.entity.Teacher">
                <id property="id" column="teacherId" />
                <result property="teacherName" column="teacherName" />
            </association>
        </collection>
    </resultMap>
</mapper>

必須在User中加入構造函數,構造函數的屬性必須和constructor一致。

###執行

package com.hava.cloud_study.service;

import java.io.InputStream;

import com.hava.cloud_study.entity.User;
import com.hava.cloud_study.repository.UserOp;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class HelloMyBatis {
    public static void main(String[] args) {
        // 1. 聲明配置⽂件的⺫錄瀆職
        String resource = "mybatis-conf.xml";
        // 2. 加載應⽤配置⽂件
        InputStream is = HelloMyBatis.class.getClassLoader()
                .getResourceAsStream(resource);
        // 3. 建立SqlSessonFactory
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
                .build(is);
        // 4. 獲取Session
        SqlSession session = sessionFactory.openSession();
        try {
            // 5. 獲取操做類
            UserOp userOp = session.getMapper(UserOp.class);
            // 6. 完成查詢操做
            User user = userOp.getUser(25);
            System.out.println(user.getId() + " " + user.getUserName() + " ");
                    System.out.println(user.getCourses().get(0).getCourseName() +" ");
            System.out.println(user.getCourses().get(0).getTeacher().getTeacherName());
        } finally {
            // 7.關閉Session
            session.close();
        }
    }
}

###執行結果

25 ZhanPeng 
Java 
OldTeacher

##Collection 容器 User當中的List注入,也是經過resultMap,經過collection的標籤來實現。

  • 實現一對多的關聯
    • id - 一個ID結果;標記結果做爲ID能夠幫助提升總體效能
    • result - 注入到字段或者JavaBean屬性的普通結果 - 普通屬性注入

Collection 標籤中property必須和對象的屬性一致。

<?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.hava.cloud_study.repository.UserOp">
    <select id="getUser" parameterType="int" resultMap="UserMap">
        select u.id
        as userId,userName,courseName,corp,c.id as courseId,teacher.id as
        teacherId,teacherName from user u left
        join
        UserCourse uc on u.id
        =uc.user_id left join course c on c.id =
        uc.course_id left join teacher
        on teacher.id = c.teacher_id where u.id
        = #{id}
    </select>

    <resultMap id="UserMap"
               type="com.hava.cloud_study.entity.User">
        <constructor>
            <idArg column="userId" javaType="int" />
            <arg column="userName" javaType="String" />
            <arg column="corp" javaType="String" />
        </constructor>
        <!-- 定義對象爲List的屬性 -->
        <collection property="courses"
                    ofType="com.hava.cloud_study.entity.Course">
            <id property="id" column="courseId" />
            <result property="courseName" column="courseName" />
            <association property="teacher" column="teacher_id"

                         javaType="com.hava.cloud_study.entity.Teacher">
                <id property="id" column="teacherId" />
                <result property="teacherName" column="teacherName" />
            </association>
        </collection>
    </resultMap>
</mapper>

##Association 實現對象與對象之間的鏈接

  • 實現複雜類型之間的關聯
    • id - 一個ID結果;標記結果做爲ID能夠幫助提升總體效能
    • result - 注入到字段或者JavaBean屬性的普通結果 - 普通屬性注入
<?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.hava.cloud_study.repository.UserOp">
    <select id="getUser" parameterType="int" resultMap="UserMap">
        select u.id
        as userId,userName,courseName,corp,c.id as courseId,teacher.id as
        teacherId,teacherName from user u left
        join
        UserCourse uc on u.id
        =uc.user_id left join course c on c.id =
        uc.course_id left join teacher
        on teacher.id = c.teacher_id where u.id
        = #{id}
    </select>

    <resultMap id="UserMap"
               type="com.hava.cloud_study.entity.User">
        <constructor>
            <idArg column="userId" javaType="int" />
            <arg column="userName" javaType="String" />
            <arg column="corp" javaType="String" />
        </constructor>
        <!-- 定義對象爲List的屬性 -->
        <collection property="courses"
                    ofType="com.hava.cloud_study.entity.Course">
            <id property="id" column="courseId" />
            <result property="courseName" column="courseName" />
            <!-- 一對一 -->
            <association property="teacher" column="teacher_id"

                         javaType="com.hava.cloud_study.entity.Teacher">
                <id property="id" column="teacherId" />
                <result property="teacherName" column="teacherName" />
            </association>
        </collection>
    </resultMap>
</mapper>

#MyBatis數據庫鏈接池 ##DataSource

  • MyBatis 3.0 內置數據庫鏈接池
  • dataSource type="POOLED"啓動鏈接池
<!-- 數據庫鏈接數據源 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.1.200/cloud_study"/>
                <property name="username" value="root"/>
                <property name="password" value="dVHJtG0T:pf*"/>
            </dataSource>
        </environment>

##數據庫鏈接生命週期 MyBatis數據庫鏈接池的內部實現,與以前的DBCP鏈接池是很是相似的。MyBatis數據庫鏈接池實際上維護了一個空閒鏈接鏈和活躍鏈接鏈兩個隊列,當MyBatis要實際執行SQL時,獲取一個數據庫鏈接,首先回去判斷空閒的隊列中是否有空閒的數據庫鏈接,若是有返回數據庫鏈接去執行SQL,若是沒有,則判斷當前活躍的數據庫鏈接是否已經滿,若是沒有超過則建立新鏈接並加入到活躍列表中。若是已滿或者超過則回去檢查活躍鏈接隊列中,最先的鏈接是否過時,若是過時則移除數據庫鏈接。在建立新的數據庫鏈接

輸入圖片說明

##鏈接池經常使用配置選項

  • poolMaximumActiveConnections

    • 數據庫最大活躍鏈接數
    • 考慮到隨着鏈接數的增長,性能可能達到拐點,不建議設置過大。
  • poolMaximumIdleConnections

    • 最大空閒鏈接數
    • 經驗值建議設置與poolMaximum相同便可
  • poolMaximumCheckoutTime

    • 獲取鏈接時若是沒有idleConnection同時activeConnection達到最大值,則從activeConnections列表第一個鏈接開始,檢查是否超過poolMaximumCheckoutTime,若是超過,則強制使其失效,返回該鏈接。
    • 因爲SQL執行時間受服務器配置、表結構不一樣,建議設置爲預期最大SQL執行時間。
  • poolTimeToWait

    • 獲取服務器端數據庫鏈接的超時時間,若是超過該時間,則打印日誌,同時從新獲取。
    • 建議使用默認值20s
  • poolPingEnabled

    • 啓動鏈接偵測,檢查鏈接池中的鏈接是否爲有效鏈接
    • 默認關閉,建議啓動,防止服務器端異常關閉,致使客戶端錯誤
  • poolPingQuery

    • 偵測SQL,建議使用select 1開銷較小
  • poolPingConnectionsNotUsedFor

    • 偵測時間,建議小於服務器端超時時間,MySQL默認超時8小時
相關文章
相關標籤/搜索