Mybatis配置文件

MyBatis映射文件sql

Editor:SimpleWu數據庫

MyBatis真正的核心是在映射文件,因爲它的異常強大,若是拿它和相同功能的JDBC代碼相比,你會發現它省掉了將近95%的代碼。編程

MyBatis實體類映射文件緩存

MyBatis有一下幾個頂級元素session

select:映射查詢語句mybatis

<select id="findAll" resultType="com.simple.mybatis.entitys.Employee">
        select * from tal_employee
</select>

insert:映射插入語句app

使用#{參數屬性名}賦值框架

<insert id="saveEmp" parameterType="com.simple.mybatis.entitys.Employee">
        insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
</insert>

update:映射修改語句函數

<update id="updateEmp" parameterType="com.simple.mybatis.entitys.Employee">
        update tal_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id}
</update>

delete:映射刪除語句測試

<delete id="deleteEmp" parameterType="Integer">
        delete from tal_employee where id=#{id}
</delete>

sql:能夠被其它sql語句重用的sql語句。
resultMap:是最複雜也是最強大的元素,用來和數據庫表和實體類進行映射。

<resultMap type="com.simple.mybatis.entitys.Employee" id="Employee">
    <id property="id" column="id"/>
    <result property="lastName" column="last_name"/>
    <result property="email" column="email"/>
    <result property="gender" column="gender"/>
</resultMap>

<!-- 返回外部resultMap格式的類型。-->
<select id="findAll" resultMap="Employee">
    select id,last_name AS lastName,email,gender from tal_employee
</select>

cache:給定命名空間的緩存配置。
cache-ref:其它命名空間緩存配置的引用。

咱們結合第一章,使用以前與數據庫互交的方式:

sqlSession.selectList("命名空間.select標籤ID");
sqlSession.selectOne("命名空間.select標籤ID");
sqlSession.update("命名空間.update標籤ID", "Object類型參數");
sqlSession.delete("命名空間.delete標籤ID", "Object類型參數");
sqlSession.insert("命名空間.insert標籤ID", "Object類型參數");

增刪改必須提交事務:sqlSession.commit();

使用XML映射文件方式來在執行方法時,因爲是經過字符串方式來調用方法,對類型的約束也不是強制性的,可讀性較差,這是早期ibatis的調用方式。除此以外Mybatis還提供另外兩種實現方式

MyBatis註解方式

  1. @Select:用來修飾使用查詢語句的方法
  2. @Insert:用來修飾使用增長語句的方法、
  3. @Update:用來修飾使用修改修改的方法。
  4. @Delete:用來修飾使用刪除語句的方法。

    public interface EmployeeAnnotation {
    @Select("select id,last_name AS lastName,email,gender from tal_employee")
    List findAll();

    @Insert("insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})")
     int saveEmp(Employee employee);
    
     @Update("update tal_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id}")
     boolean updateEmp(Employee employee);
    
     @Delete("elete from tal_employee where id=#{id}")
     long deleteEmp(Integer id);

    }

而後咱們須要在mybatis主配置文件中映射這個註解接口

<!-- 映射註解類 -->
<mapper class="com.simple.mybatis.dao.EmployeeAnnotation"/>

@Test
    public void testAnnotation(){
        SqlSession session = sqlSessionFactory.openSession();
        EmployeeAnnotation employeeAnnotation = session.getMapper(EmployeeAnnotation.class);
        Employee employee = new Employee("測試註解增長", "email", "男");
        employeeAnnotation.saveEmp(employee);
        //提交事務
        session.commit();
        session.close();
}

使用註解雖然更加方便,可是配置複雜sql語句時較爲複雜。因此不少時候採用兩種相結合的方式。

Mybatis接口編程

咱們首先添加一個接口

public interface EmployeeMapper {
    List<Employee> findAll();
    
    int saveEmp(Employee employee);
    
    boolean updateEmp(Employee employee);
    
    long deleteEmp(Integer id);
}

實體類映射文件命名空間(namespace)必須對應接口全名,而且裏面的方法須要對應裏面增刪改查標籤ID完成綁定

<?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.simple.mybatis.dao.EmployeeMapper">
    <resultMap type="com.simple.mybatis.entitys.Employee" id="Employee">
        <id property="id" column="id"/>
        <result property="lastName" column="last_name"/>
        <result property="email" column="email"/>
        <result property="gender" column="gender"/>
    </resultMap>

    <!-- 返回外部resultMap格式的類型。-->
    <select id="findAll" resultMap="Employee">
        select id,last_name AS lastName,email,gender from tal_employee
    </select>
    
    <insert id="saveEmp" parameterType="com.simple.mybatis.entitys.Employee">
        insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
    </insert>
    
    <update id="updateEmp" parameterType="com.simple.mybatis.entitys.Employee">
        update tal_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id}
    </update>
    
    <delete id="deleteEmp" parameterType="Integer">
        delete from tal_employee where id=#{id}
    </delete>
</mapper>

而且必須在MyBatis主配置文件中加載這個映射文件

<mappers>
        <mapper resource="com/simple/mybatis/entitys/EmployeeMapper.xml" />
</mappers>

使用方式:

@Test
    public void test4(){
        SqlSession session = sqlSessionFactory.openSession();
        //獲取接口。這個接口mybatis會幫我建立代理實現類完成接口與XML映射的綁定
        EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
        employeeMapper.deleteEmp(1);
        session.commit();
        session.close();
    }

獲取插入後的自動增加主鍵

useGeneratedKeys參數只針對 insert 語句生效,默認爲 false。當設置爲 true 時,表示若是插入的表以自增列爲主鍵,則容許 JDBC 支持自動生成主鍵,並可將自動生成的主鍵返回。 keyProperty是要封裝給parameterType="com.simple.mybatis.entitys.Employee中的主鍵ID屬性名

<insert id="saveEmpGetKey" parameterType="com.simple.mybatis.entitys.Employee"
    useGeneratedKeys="true" keyProperty="id"
    >
        insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
</insert>

@Test
    public void saveEmpGetKey(){
        SqlSession session = sqlSessionFactory.openSession();
        EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
        Employee employee = new Employee("自動封裝主鍵", "email", "男");//增長以前主鍵沒賦值
        employeeMapper.saveEmpGetKey(employee);
        session.commit();//提交事務
        System.out.println("增長後主鍵有值: " + employee.getId());
        session.close();//關閉資源
    }

Mybatis參數規則

一個參數時:

直接使用#{xxx}來訪問參數便可。參數名稱任意。例如#{a},#{b}均可以訪問參數值。若是是集合(Collection,List,Set)類型,使用集合名稱小寫做爲key值。

必須接口方法:

long deleteEmp(Integer emp);

映射文件:

<delete id="deleteEmp" parameterType="Integer">
        delete from tal_employee where id=#{id}
</delete>

在這裏能夠看到咱們是沒有給這個賦值的,#{id}我這個屬性名也不叫id而是emp。因此一個參數是名字能夠任意若是是傳入的集合類型

傳入Map參數時取值:

//接口有方法:long deleteEmp(Map<String, Object> map);
<delete id="deleteEmp" parameterType="Map">
        delete from tal_employee where id=#{empID}
</delete>

咱們這裏取值是empID,這想一想都知道建立一個map.put(「empID」,1)做爲參數傳入方法調用就好了

多個參數時:

  1. 默認:就不能使用#{xxx}來訪問參數了。當有多個參數時,mybatis會將參數封裝爲一個map集合,只能經過#{下標}或者#{paramN}的方式來獲取值。
  2. 命名參數:明確指定封裝參數時手動指定map的key。經過在接口方法上添加@Param("key")來指定參數名稱。
  3. 實體類:若是多個參數是封裝好的業務類,那麼直接傳入業務對象便可。能夠經過#{屬性名}獲取屬性便可。Map:若是多個參數不是已封裝的業務類,那麼傳入map集合便可。經過#{key}獲取對應的value值。

{}和${}

MyBatis中,除了可使用#{}來獲取參數的值意外,還可使用${}來獲取參數的值。

區別:#{}:會以預編譯的方式,將參數生成到sql語句中。${}:會直接將值生成到sql語句。

大多數狀況下,咱們都是以#{}來獲取參數,可是有些地方不支持佔位符的地方那麼就可使用${}來獲取參數,好比表名。

resultType返回類型

  1. 對於增刪改的方法,Mybatis會自動對結果進行封裝,返回int,Boolean,long均可以。
  2. 對於返回實體對象和List集合,resultType能夠設置爲實體類型。
  3. 若是返回單個對象,也能夠封裝爲Map<String,Object>,resultType設置爲map。
  4. 若是返回Map集合對象,好比Map<String,Student>,resultType設置爲Student類型,經過@MapKey("id")註解來修飾放入Map中的key值。

ResultMap標籤介紹

ResultMap的經常使用子標籤

  1. id:映射主鍵。result:映射普通列。
  2. association:複雜結果映射。
  3. collection:複雜類型的集合映射。
  4. constructor:構造函數注入。

前面咱們的案例咱們數據庫的字段與實體類的屬性基本上一致,或者不一導致用取別名方案解決,但是每條語句都去取別名是很是麻煩的,ResultMap這個標籤就很好的解決數據庫與實體類字段不對應的問題

咱們新建立一個部門表:

CREATE TABLE tal_dept(
    d_id INT PRIMARY KEY AUTO_INCREMENT,
    d_name VARCHAR(50)
);

對應實體類:

public class Dept {
    private Integer id;
    private Integer name;
}

若是咱們查詢語句直接使用resultType="com.simple.mybatis.entitys.Dept那麼毫無疑問咱們的實體類中名字不對應是賦值爲null的,咱們能夠ResultMap映射實體類與數據庫的對應關係

<!--配置返回結果,配置數據庫字段與類屬性的映射-->
<resultMap type="com.simple.mybatis.entitys.Dept" id="DeptResult">
        <id column="d_id" property="id"/>
        <result column="d_name" property="name"/>
</resultMap>
<!--使用resultMap使用指向上面返回結果的ID-->
<select id="getDeptOne" parameterType="Integer" resultMap="DeptResult">
        select * from tal_dept where d_id = #{id}
</select>

關係映射

在數據庫中,許多數據是分佈在多個表中的,有時候須要將多個表的數據關聯起來進行查詢。那麼在ORM框架中,咱們須要處理數據表的映射關係。

常見的映射關係:

  1. 關聯屬性映射association
  2. 映射collection映射

result方式映射屬性

這種方式並不推薦,沒有什麼重用性

<resultMap type="com.simple.mybatis.entitys.Employee" id="EmployeeOrDept">
        <id property="id" column="id"/>
        <result property="lastName" column="last_name"/>
        <result property="email" column="email"/>
        <result property="gender" column="gender"/>
        <!-- 指定Employee中Dept對象屬性 -->
        <result property="dept.id" column="d_id"/>
        <result property="dept.name" column="d_name"/>
</resultMap>
<select id="getEmployeeOrDeptAll" resultMap="EmployeeOrDept">
        select * from tal_employee e inner join tal_dept d on e.d_id=d.d_id
</select>

association映射(分步查詢)

多對一,查詢員工獲取員工中的部門:

<resultMap type="com.simple.mybatis.entitys.Employee" id="EmployeeOrDept">
        <id property="id" column="id"/>
        <result property="lastName" column="last_name"/>
        <result property="email" column="email"/>
        <result property="gender" column="gender"/>
        <!-- property指定實體類中對象dept 指定發過去的參數column="d_id" 
             select指定com.simple.mybatis.dao.DeptMapper映射文件中getDeptOne查詢方法
         -->
        <association property="dept" column="d_id" 
        select="com.simple.mybatis.dao.DeptMapper.getDeptOne"></association>
</resultMap>
<!--resultMap指定使用上面定義的返回結果-->
<select id="getEmployeeOrDeptAll" resultMap="EmployeeOrDept">
        select * from tal_employee e inner join tal_dept d on e.d_id=d.d_id
</select>

Collection查詢

一對多,獲取部門同時部門中員工也獲取:

<!--部門映射-->
<resultMap type="com.simple.mybatis.entitys.Dept" id="DeptResult">
        <id column="d_id" property="id"/>
        <result column="d_name" property="name"/>
        <!--property指定Dept中集合屬性名 ofType指定集合中屬性類型 -->
        <collection property="Employees" ofType="com.simple.mybatis.entitys.Employee" >
            <id property="id" column="id"/>
            <result property="lastName" column="last_name"/>
            <result property="email" column="email"/>
            <result property="gender" column="gender"/>
        </collection>
</resultMap>
<select id="getDeptAll" resultMap="DeptResult">
        select * from tal_dept d left join tal_Employee e on d.d_id = e.d_id
</select>

Collection嵌套查詢

一對多分佈查詢

<resultMap type="com.simple.mybatis.entitys.Dept" id="DeptOrEmployee">
        <id column="d_id" property="id"/>
        <result column="d_name" property="name"/>
        <!--select指定com.simple.mybatis.dao.EmployeeMapper映射文件中的getEmployeeByDeptId-->
        <collection property="Employees" column="d_id"  ofType="com.simple.mybatis.entitys.Employee" 
        select="com.simple.mybatis.dao.EmployeeMapper.getEmployeeByDeptId">
        </collection>
    </resultMap>
<!--com.simple.mybatis.dao.EmployeeMapperXML中方法-->
<select id="getEmployeeByDeptId" parameterType="Integer" resultType="com.simple.mybatis.entitys.Employee">
        select * from tal_employee where d_id = #{id}
    </select>

關聯查詢和分步查詢的區別:

  1. 關聯查詢一次將多個表的數據查詢出來,分步查詢經過屢次查詢獲取查詢結果。
  2. 配置文件不一樣,關聯查詢須要定義額外的映射,分步查詢須要定義外鍵列,和查詢的select方法。
  3. 關聯查詢不支持延遲加載,分步查詢支持延遲加載。fetchType="lazy"

延遲加載

剛纔分佈查詢是一次將結果查詢出來,爲了提升效率,mybatis還支持延遲加載技術,等須要用到對象時才進行查詢。

在mybatis主配置文件中配置:

<!– 經過全局配置文件設置延遲加載-->
<settings>
<!-- 全局啓用或禁用延遲加載。當禁用時,全部關聯對象都會即時加載。 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 當啓用時,有延遲加載屬性的對象在被調用時將會徹底加載任意屬性。不然,每種屬性將會按須要加載。 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>

設置級聯延遲加載

<!– 設置延遲加載屬性-->
<association fetchType="lazy"/>
相關文章
相關標籤/搜索