首頁  >  文章  >  Java  >  Mybatis映射檔的詳解

Mybatis映射檔的詳解

不言
不言轉載
2018-10-12 14:50:554242瀏覽

這篇文章帶給大家的內容是關於Mybatis映射檔的詳解,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

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

MyBatis實體類別映射檔案

MyBatis有幾個頂級元素

select:映射查詢語句

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

insert:映射插入語句

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

<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>

:可以被其它sql語句重用的sql語句。
:是最複雜也是最強大的元素,用來和資料庫表和實體類別進行映射。

<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>

:給定命名空間的快取配置。
:其它命名空間快取配置的參考。

我們結合第一章,使用先前與資料庫互交的方式:

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
#

 @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傳回型別

    #對於增刪改的方法,Mybatis會自動對結果進行封裝,傳回int,Boolean,long都可以。
  1. 對於傳回實體物件和List集合,resultType可以設定為實體類型。
  2. 如果傳回單一對象,也可以封裝為Map1384ae87b3aa4d7618d5d6d4b582a21b,resultType設定為map。
  3. 如果傳回Map集合對象,例如Mapbfb6431144afb6dca75c307d25533a56,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"/>

以上是Mybatis映射檔的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除