【Mybatis】歸納總結

Mybatis


1.什麼是Mybatis

MyBatis 是一款優秀的持久層框架,它支持定製化 SQL存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。

2.Mybatis的作用域和生命週期

  • SqlSessionFactoryBuilder    這個類可以被實例化、使用和丟棄,一旦創建了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 實例的最佳作用域是方法作用域(也就是局部方法變量)。你可以重用 SqlSessionFactoryBuilder 來創建多個 SqlSessionFactory 實例,但是最好還是不要讓其一直存在以保證所有的 XML 解析資源開放給更重要的事情。
  • SqlSessionFactory    SqlSessionFactory 一旦被創建就應該在應用的運行期間一直存在,沒有任何理由對它進行清除或重建。使用 SqlSessionFactory 的最佳實踐是在應用運行期間不要重複創建多次,多次重建 SqlSessionFactory 被視爲一種代碼“壞味道(bad smell)”。因此 SqlSessionFactory 的最佳作用域是應用作用域。有很多方法可以做到,最簡單的就是使用單例模式或者靜態單例模式。
  • SqlSession    每個線程都應該有它自己的 SqlSession 實例。SqlSession 的實例不是線程安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。絕對不能將 SqlSession 實例的引用放在一個類的靜態域,甚至一個類的實例變量也不行。也絕不能將 SqlSession 實例的引用放在任何類型的管理作用域中,比如 Servlet 架構中的 HttpSession。如果你現在正在使用一種 Web 框架,要考慮 SqlSession 放在一個和 HTTP 請求對象相似的作用域中。換句話說,每次收到的 HTTP 請求,就可以打開一個 SqlSession,返回一個響應,就關閉它。這個關閉操作是很重要的,你應該把這個關閉操作放到 finally 塊中以確保每次都能執行關閉。下面的示例就是一個確保 SqlSession 關閉的標準模式:
public class DBTools {
    public static SqlSessionFactory sessionFactory;
    
    static{
        try {
            // 方式一
            //使用MyBatis提供的Resources類加載mybatis的配置文件
            //Reader reader = Resources.getResourceAsReader("mybatis.cfg.xml");
            //構建sqlSession的工廠
            //sessionFactory = new SqlSessionFactoryBuilder().build(reader);
            
            // 方式二
            String resource = "org/mybatis/example/mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
    //創建能執行映射文件中sql的sqlSession
    public static SqlSession getSession(){
        return sessionFactory.openSession();
    }
    
}
SqlSession session = sqlSessionFactory.openSession();
try {
  // do work
} finally {
  session.close();
}

3.xml配置

configuration 配置

 3.1 properties

<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>

如果屬性在不只一個地方進行了配置,那麼 MyBatis 將按照下面的順序來加載:

  • 在 properties 元素體內指定的屬性首先被讀取。
  • 然後根據 properties 元素中的 resource 屬性讀取類路徑下屬性文件或根據 url 屬性指定的路徑讀取屬性文件,並覆蓋已讀取的同名屬性。
  • 最後讀取作爲方法參數傳遞的屬性,並覆蓋已讀取的同名屬性。

因此,通過方法參數傳遞的屬性具有最高優先級,resource/url 屬性中指定的配置文件次之,最低優先級的是 properties 屬性中指定的屬性。

 3.2 settings

延遲加載配置

<settings>
    <!-- 打開延遲加載的開關 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 將積極加載改爲消極加載,即延遲加載 -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

如果想單個開啓或禁用延遲加載,可以使用fetchType屬性來實現,fetchType="lazy" 表示使用懶加載   fetchType="eager"表示禁用懶加載。

自動映射級別配置

<setting name="autoMappingBehavior" value="PARTIAL"/>

其中 NONE 表示不啓用自動映射,PARTIAL 表示只對非嵌套的 resultMap 進行自動映射,FULL 表示對所有的 resultMap 都進行自動映射。默認的自動映射模式爲 PARTIAL。

如果在某些 resultMap 中不想使用自動映射,則可以單獨在該 resultMap 中設置 autoMapping 的屬性爲 false。

 3.3 typealiases

方式一:
<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>

方式二:
<typeAliases>
  <package name="domain.blog"/> <-- 包名 -->
</typeAliases>

方式三:(優先級最高)
@Alias("author")
public class Author {
    ...
}

3.4 mappers

<!-- 使用相對於類路徑的資源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定資源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口實現類的完全限定類名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 將包內的映射器接口實現全部註冊爲映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

4.XML映射文件

4.1 高級結果映射(association,collection)

一對一或多對一(多個學生一個數學老師)

<resultMap type="Student" id="studentMap">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
		<result column="class_name" property="className"/>
		<result column="teacher_id" property="teacherId"/>
		<association property="teacher" select="getTeacher" column="teacher_id" javaType="Teacher">
		<!-- 這裏要注意的是column對應的是student中的外鍵,而且需是表字段名 -->
		</association>
	</resultMap>
	
	
	<select id="getStudent" resultMap="studentMap">
		SELECT
			s.id,
			s.name,
			s.class_name,
			s.teacher_id
		FROM
			student s
	</select>
	
	<select id="getTeacher" resultType="Teacher" parameterType="int">
		SELECT
			t.id,
			t.name,
			t.class_name as className 
		FROM teacher t 
		where id = #{teacher_id}
	</select>

一對多(一個老師對多個學生)

<!-- 方式一 -->
<resultMap type="Teacher" id="teacherMap">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
		<collection property="students" ofType="Student" column="id">
			<id column="sid" property="id"/><!-- 這裏的column對應的是下面查詢的別名,而不是表字段名 -->
			<result column="sname" property="name"/><!-- property對應JavaBean中的屬性名 -->
			<result column="className" property="className"/>
		</collection>
	</resultMap>
	
	
	<!-- 查詢所有的老師級各自的所有學生 -->
	<select id="getTeachers" parameterType="Teacher" resultMap="teacherMap">
		SELECT
			t.id,
			t.NAME,
			t.class_Name,
			s.id AS sid,
			s. NAME AS sname,
			s.class_name as className
		FROM
			teacher t
		LEFT JOIN student s ON t.id = s.teacher_id
	</select>


<!-- 方式二(推薦) -->
<resultMap type="Teacher" id="teacherMaps">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
		<result column="class_name" property="className"/>
		<collection property="students" ofType="Student" select="getStudents" column="id">
		</collection>
	</resultMap>
	
	
	<!-- 查詢所有的老師級各自的所有學生 -->
	<select id="getAllTeacher" parameterType="Teacher" resultMap="teacherMaps">
		SELECT
			t.id,
			t.NAME,
			t.class_name
		FROM
			teacher t
	</select>
	
	<select id="getStudents" parameterType="int" resultType="Student">
		select 
			s.id,
			s. NAME,
			s.class_name as className
		from student s
		where teacher_id = #{id}
	</select>

4.2 mybatis 入參方式 

  • 基本類型及其封裝類型,String類型
  1. 單個參數
  2. 多個參數
        
     // 佔位符方式
     public Good selectGood(String id, String name);

     <select id="selectGood" resultMap="GoodMap">

           select * from good where id = #{0} and name=#{1}

     </select>


     // @Param("") 註解方式
     public Good selectGood(@param("id")String id,@param("name")String name);

     <select id="selectGood" resultMap="GoodMap">

          select * from good where id = #{id} and name=#{name}

     </select>
  • 對象類型,Map類型
  • List,數組類型 
  1. List類型,parameterType設置爲java.util.List或者list,< foreach>標籤中collection設置爲list
  2. 數組類型,parameterType設置爲array,< foreach>標籤中collection設置爲array。

 注:

判斷List是否爲空:

<if test="golfCourseList != null and golfCourseList.size() > 0"> 

 判斷Array是否爲空:

<if test="object != null and object.length > 0">

4.2 mybatis 返回值類型  

  • 基本數據類型(int String等)

..................

  • JavaBean類型

..................

  • List類型

..................

  • Map類型

   1.返回單條數據

Map<String,****> select(****);

<select id="***" resultType="map">****************************</>

最後封裝進map中數據格式爲 key:數據庫字段 value:字段對應值

   2.返回多條數據


@MapKey("id")
Map<String,Student> select(****);

<select id="***" resultType="map">****************************</>

最後封裝進map中數據格式爲 key:@Mapkey設置的字段值 value:Student

5.Mybatis動態sql

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ... 
</trim>

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章