MyBatis學習二

1.   MyBatis 介紹

  • 1.  MyBatis SQL參數傳遞(掌握)
  • 2.  (多對一)關聯映射(掌握)
  • 3. (一對多,多對多)集合映射(掌握)
  • 4.  SQL映射器Mapper(掌握)
  • 5. SSM集成(掌握)
  1. MyBatis SQL參數傳遞

#{OGNL表達式} 和 ${OGNL表達式} 的區別css

2.1.  #{OGNL表達式}html

MyBatis會把這個表達式使用?(佔位符)替換,做爲一個sql參數使用java

     好比name的值爲: web

     定義SQL: select * from t_user where name = #{name}面試

     最終SQL: select * from t_user where name = ?spring

2.2.  ${OGNL表達式}sql

MyBatis會把這個表達式的值替換到sql中,做爲sql的組成部分;數據庫

該方式主要用於程序拼接SQL;apache

     好比name的值爲:  '1  or 1=1'緩存

     定義SQL: select * from t_user where name = ${id}

     最終SQL: select * from t_user where name = 1 or 1=1 出現sql注入

 

若是sql中使用${OGNL},而且參數的類型是(integer,string....)那麼OGNL表達式能夠寫成任意東西;

2.3.  Sql注入

預防sql注入,使用佔位符查詢

select * from employee where username=? and password=?

select * from employee where username='admin' and password='admin'

字符串拼接,出現sql注入

select * from employee where username='admin' and password='0000' or '1'='1'

2.4.  ${OGNL}表達式的應用場景:不能用在登陸場景,會出現sql注入

用在order by 的場景

Map<String,Object> 

map.put("orderBy",'name desc');

map.put("begin",0);

map.put("end",10);

 

在jdbc的sql代碼order by後面不能使用佔位符?,只能進行字符串的拼接

2.5.  複雜參數傳遞  

 

  1. (多對一)關聯映射

3.1.  導入sql文件

 

 

CREATE TABLE `t_dept` (

 `id` bigint(20) NOT NULL AUTO_INCREMENT,

 `name` varchar(255) DEFAULT NULL,

 PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

CREATE TABLE `t_user` (

 `id` bigint(20) NOT NULL AUTO_INCREMENT,

 `name` varchar(255) DEFAULT NULL,

 `password` varchar(255) DEFAULT NULL,

 `dept_id` bigint(20) DEFAULT NULL,

 PRIMARY KEY (`id`),

 KEY `fk1` (`dept_id`),

 CONSTRAINT `fk1` FOREIGN KEY (`dept_id`) REFERENCES `t_dept` (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.2.  創建Dept、User的模型

 

3.3.  配置文件MyBatis-Config.xml

<!-- 單向多對一 -->

<mapper resource="cn/itsource/mybatis/day2/_1_manytoone/DomainMapper.xml" />

3.4.  映射文件DomainMapper.xml

<mapper namespace="cn.itsource.mybatis.day2._1_manytoone.DomainMapper">

 

         <!-- 保存部門 -->

         <insert id="saveDept" parameterType="cn.itsource.mybatis.day2._1_manytoone.Dept" useGeneratedKeys="true"

                  keyProperty="id">

                  insert into t_dept(name) values(#{name})

         </insert>

         <!-- 保存用戶 -->

         <insert id="saveUser" parameterType="cn.itsource.mybatis.day2._1_manytoone.User" useGeneratedKeys="true"

                  keyProperty="id">

                  insert into t_user(name,password,dept_id) values(#{name},#{password},#{dept.id})

         </insert>

 

</mapper>

3.5.  保存測試數據

String NAME_SPACE = "cn.itsource.mybatis.day2._1_manytoone.DomainMapper";

 

@Test

public void testSave() {

         SqlSession session = MyBatisUtils.getSession();

         // 先保存部門

         Dept dept1 = new Dept();

         dept1.setName("部門1");

         Dept dept2 = new Dept();

         dept2.setName("部門2");

         session.insert(NAME_SPACE + ".saveDept", dept1);

         session.insert(NAME_SPACE + ".saveDept", dept2);

 

         // 在保存用戶

         for (int i = 1; i < 11; i++) {

                  User user = new User();

                  user.setName("user" + i);

                  user.setPassword("admin");

                  if (i % 2 == 0) {

                           user.setDept(dept1); // insert into t_user(dept_id) values(#{dept.id})

                  } else {

                           user.setDept(dept2);

                  }

                  session.insert(NAME_SPACE + ".saveUser", user);

         }

 

         session.commit();

         session.close();

}

3.6.  2個表關聯查詢的方式

3.6.1.   單表查詢,不能查詢部門的名稱

select * from t_user

3.6.2.   等值鏈接

select u.*,d.*

from t_user u,t_dept d

where u.dept_id=d.id

3.6.3.   內鏈接

select u.*,d.*

from t_user u

join t_dept d

on u.dept_id=d.id

3.6.4.   左外鏈接

select u.*,d.*

from t_user u

left join t_dept d

on u.dept_id=d.id

3.7.  MyBatis提供兩種方式處理咱們關聯對象,嵌套查詢和嵌套結果。

 

3.8.  測試getAll方法

@Test

public void testGetAll() {

         SqlSession session = MyBatisUtils.getSession();

         List<User> list = session.selectList(NAME_SPACE + ".getAll");

         for (User user : list) {

                  System.out.println(user);

                  System.out.println(user.getDept());

         }

         session.close();

}

3.9.  嵌套結果(發一條左外鏈接sql解決問題,映射文件Mapper結果的手動封裝ResultMap)

使用嵌套結果映射來處理重複的聯合結果的子集。--這種方式,全部屬性都要本身來!!

 

<!-- 嵌套結果(發一條左外鏈接sql解決問題,映射文件Mapper結果的手動封裝ResultMap) -->

<select id="getAll" resultMap="userResultMap">

         select u.id,u.name,u.password,d.id did,d.name dname

         from t_user u

         left join t_dept d

         on u.dept_id=d.id

</select>

 

<resultMap type="cn.itsource.mybatis.day2._1_manytoone.User" id="userResultMap">

         <!-- 多方User的id -->

         <id property="id" column="id" />

         <!-- 多方User的屬性 -->

         <result property="name" column="name" />

         <result property="password" column="password" />

         <!-- 一方Dept的id和屬性 -->

         <association property="dept" javaType="cn.itsource.mybatis.day2._1_manytoone.Dept">

                  <!--一方Dept的id -->

                  <id property="id" column="did" />

                  <!--一方Dept的屬性 -->

                  <result property="name" column="dname" />

         </association>

</resultMap>

3.10.         嵌套查詢(發1查詢user+N查詢dept條sql解決問題,映射文件Mapper結果的自動封裝ResultMap)

經過執行另一個SQL映射語句來返回預期的複雜類型。

    <association ...>

<association ...>

 

select * from t_department where id = #{id}

 

 

  1. (一對多,多對多)集合映射

4.1.  常見的關係

員工和部門:

   在部門方,須要查詢到當前部門下的全部員工。----集合查詢

 

一個部門  擁有   多個員工

 

學生和課程

多  對  多

 

一個學生   能夠學習    多門課程

一門課程   能夠有      多個學生

4.2.  collection

<collection property="集合數據" ofType="集合中元素類型">

  

</collection>

 

4.3.  嵌套結果(一條sql)

嵌套查詢在crm項目裏面再講

<mapper namespace="cn.itsource.mybatis.day2._3_onetomany.DomainMapper">

         <!-- 嵌套結果(發一條左外鏈接sql解決問題,映射文件Mapper結果的手動封裝ResultMap) -->

         <select id="getAll" resultMap="deptResultMap">

                  select d.id,d.name,u.id uid,u.name uname,u.password

                  from t_dept d

                  left join t_user u

                  on d.id=u.dept_id

         </select>

 

         <resultMap type="cn.itsource.mybatis.day2._3_onetomany.Dept" id="deptResultMap">

                  <!-- 處理一方 -->

                  <id property="id" column="id" />

                  <result property="name" column="name" />

                  <!-- 處理多方 -->

                  <!-- // 單向一對多 -->

                  <!-- private Set<User> users = new HashSet<User>(); -->

                  <collection property="users" javaType="cn.itsource.mybatis.day2._3_onetomany.User">

                           <id property="id" column="uid" />

                           <result property="name" column="uname" />

                           <result property="password" column="password" />

                  </collection>

         </resultMap>

</mapper>

  1. 嵌套結果和嵌套查詢的使用場景

5.1.  嵌套結果:一條sql

用在多對一的表結構

多個數據字典明細和一個數據字典類型

多個員工屬於一個部門

多個部門有一個部門經理

5.2.  嵌套查詢:1+n條sql

用在一對多或者多對多的表結構

展現數據的時候,在一行第一列顯示一方,第二列顯示多個多方,

一對多:

部門1   員工1。。。員工n

多對多:

員工1   角色1。。。角色n

  1. SQL映射器Mapper

MyBatis基於代理機制,可讓咱們無需再編寫Dao的實現。

6.1.  傳統Dao接口,如今名稱統一以Mapper結尾

 

6.2.  接口實現方式一(傳統)

 

6.3.  接口實現方式二(映射器):

 

6.4.  實現步驟

6.4.1.   根據需求,建立模型相關的Mapper接口(UserMapper)

6.4.2.   編寫映射文件

  1. Mapper。Xml的命名空間,必須和接口的「全限定類名」一致
  2. 定義sql標籤的id,須要和「接口的方法」一致,參數一致,返回值一致
  3. 緩存

7.1.  默認支持一級緩存,二級緩存須要配置,同JPA一致

緩存是一種典型的「以空間換時間」的策略。

7.2.  一級緩存

    SqlSession級別緩存,緩存對象存儲週期爲第一次獲取,到sqlsession被銷燬掉,或是sqlSession().clearCache();

7.3.  二級緩存

    SqlSessionFactory級別緩存,緩存對象存儲週期爲第一次獲取,到SqlSessionFactory被銷燬掉(應用中止了);

默認狀況下,只開啓一級緩存,若是須要開啓二級緩存咱們須要在Mapper.xml添加一個<cache>標籤和在主配置文件中<setting name="cacheEnabled" value="true"/>;

  1.    注意:須要緩存的對象,應該實現java.io.Serializable;

   

  1. SSM集成

若是要作三大框架集成,咱們先保證在一個項目,每個框架都可以獨立運行!!

8.1.  集成SpringMvc

8.1.1.   導入21個jar文件(包含spring的jar)

aop,tx,jdbc,web,webmvc

dbcp,fileupload,jackson

 

8.1.2.   applicationContext.xml

Spring使用一個配置,SpringMVC使用另外一個配置

1個,組件掃描,<context:component-scan base-package="cn.itsource.ssm" />

<import resource="classpath:applicationContext-mvc.xml" />

8.1.3.   applicationContext-mvc.xml  4個

mvc靜態資源放行,mvc註解支持

視圖解析器,上傳解析器

<!-- 開啓spring對springmvc的註解支持 -->

<mvc:annotation-driven />

 

<!-- 對於靜態資源(圖片,css,js)進行放行 -->

<mvc:default-servlet-handler />

 

<!-- 設置視圖路徑的先後綴,該配置可讓咱們寫視圖路徑的時候更簡單。 -->

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

         <!--前綴: jsp在當前工程文件夾的路徑 -->

         <property name="prefix" value="/WEB-INF/views/" />

         <!--後綴:擴展名 -->

         <property name="suffix" value=".jsp" />

</bean>

 

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

         <!-- 設置上傳文件的最大尺寸爲1MB -->

         <property name="maxUploadSize">

                  <!-- spring el寫法:5MB -->

                  <value>#{1024*1024*5}</value>

         </property>

</bean>

8.1.4.   web.xml

1.post亂碼過濾器

2.springmvc核心控制器

<!-- post提交中文亂碼的過濾器 -->

<filter>

         <filter-name>CharacterEncodingFilter</filter-name>

         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

         <init-param>

                  <!-- 按照什麼格式進行轉碼 -->

                  <param-name>encoding</param-name>

                  <param-value>UTF-8</param-value>

         </init-param>

</filter>

 

<filter-mapping>

         <filter-name>CharacterEncodingFilter</filter-name>

         <url-pattern>/*</url-pattern>

</filter-mapping>

 

<!-- 核心控制器 -->

<servlet>

         <servlet-name>dispatcher</servlet-name>

         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

         <init-param>

                  <param-name>contextConfigLocation</param-name>

                  <param-value>classpath:applicationContext.xml</param-value>

         </init-param>

         <load-on-startup>1</load-on-startup>

</servlet>

8.2.  集成MyBatis環境

8.2.1.   加入MyBatis相關9個 jar包(mybatis-spring-1.2.0.jar)

  1. 核心包
  2. 依賴包(刪除一個commons-logging-1.1.1.jar)
  3. 數據庫鏈接包

 

8.3.  Spring和MyBatis的集成方式

8.3.1.   框架集成核心

若是你的項目中,用到了Spring框架,那麼其餘框架主要就是和Spring集成!!

8.3.2.   和Spring集成的順序

  1. 把當前框架的核心類,交給Spring管理
  2. 若是框架有事務,那麼事務也要統一交給Spring管理

8.4.  Spring配置文件

8.4.1.   jdbc配置文件&數據源dataSource

<!-- Jdbc配置文件 -->

<context:property-placeholder location="classpath:jdbc.properties" />

 

<!-- 數據源dataSource -->

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

         <!-- 依賴注入鏈接池須要的屬性 -->

         <!-- property name="是BasicDataSource的set方法,本質屬性" -->

         <!-- property value="是jdbc.properties配置文件的key" -->

         <property name="driverClassName" value="${jdbc.driverClassName}" />

         <property name="url" value="${jdbc.url}" />

         <property name="username" value="${jdbc.username}" />

         <property name="password" value="${jdbc.password}" />

         <!--maxActive: 最大鏈接數量 -->

         <property name="maxActive" value="150" />

         <!--minIdle: 最小空閒鏈接 -->

         <property name="minIdle" value="5" />

         <!--maxIdle: 最大空閒鏈接 -->

         <property name="maxIdle" value="20" />

         <!--initialSize: 初始化鏈接 -->

         <property name="initialSize" value="30" />

         <!-- 鏈接被泄露時是否打印 -->

         <property name="logAbandoned" value="true" />

         <!--removeAbandoned: 是否自動回收超時鏈接 -->

         <property name="removeAbandoned" value="true" />

         <!--removeAbandonedTimeout: 超時時間(以秒數爲單位) -->

         <property name="removeAbandonedTimeout" value="10" />

         <!--maxWait: 超時等待時間以毫秒爲單位 1000等於60秒 -->

         <property name="maxWait" value="1000" />

         <!-- 在空閒鏈接回收器線程運行期間休眠的時間值,以毫秒爲單位. -->

         <property name="timeBetweenEvictionRunsMillis" value="10000" />

         <!-- 在每次空閒鏈接回收器線程(若是有)運行時檢查的鏈接數量 -->

         <property name="numTestsPerEvictionRun" value="10" />

         <!-- 1000 * 60 * 30 鏈接在池中保持空閒而不被空閒鏈接回收器線程 -->

         <property name="minEvictableIdleTimeMillis" value="10000" />

         <property name="validationQuery" value="SELECT NOW() FROM DUAL" />

</bean>

8.4.2.   SqlSessionFactoryBean

SSJ集成時候須要entityManagerFactory

SSM集成時候須要sqlSessionFactory

resources\MyBatis集成Spring文檔資料\mybatis-spring整合文檔.exe

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

8.4.3.   ssm注入順序

jdbc.properties->dataSource->sqlSessionFactory->mapper(dao)->service->controller(action)

8.4.4.   獲取sqlSessionFactory方案1

<!-- Mybatis的核心類 -->

         <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

                  <property name="dataSource" ref="dataSource" />

                  <property name="configLocation" value="classpath:mybatis-config.xml"></property>

         </bean>

 

         <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">

                  <property name="sqlSessionFactory" ref="sqlSessionFactory" />

                  <property name="mapperInterface" value="cn.itsource.ssm.mapper.UserMapper" />

         </bean>

 

         <context:component-scan base-package="cn.itsource.ssm"/>

8.4.5.   獲取sqlSessionFactory方案2

<!-- 配置sqlSessionFactory -->

         <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

                  <!-- 注入數據源 -->

                  <property name="dataSource" ref="dataSource" />

                  <!-- 配置mybatis (mapper)映射器路徑 -->

                  <property name="mapperLocations" value="classpath:cn/itsource/ssm/mapper/*Mapper.xml" />

                  <!-- 配置mybatis 類型別名 -->

                  <property name="typeAliasesPackage">

                           <value>

                                    cn.itsource.ssm.domain

                                    Cn.itsource.ssm.query  可能有查詢對象

                           </value>

                  </property>

         </bean>

一勞永逸

         <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

                  <property name="basePackage" value="cn.itsource.ssm.mapper"></property>

         </bean>

 

 

 

  1. 課程總結

9.1.  重點

  1. SSM集成,操做必須很是熟練
  2. 多對一嵌套結果,嵌套查詢
  3. 一對多嵌套結果
  4. 映射器接口

9.2.  難點

  1. 多對一嵌套結果:查詢的有dept表的別名配置
  2. 映射文件裏面使用${}的適用場景:order by
  3. 常見異常
  4. Caused by: java.io.NotSerializableException: cn.itsource.mybatis.day2._5_cache.User

要使用二級緩存,要求domain必須實現序列化接口

  1. 課後練習
  2. 面試題
  3. 擴展知識或課外閱讀推薦

13.1.         擴展知識

  1. java.io.Serializable淺析

http://www.cnblogs.com/gw811/archive/2012/10/10/2718331.html

13.2.         課外閱讀

相關文章
相關標籤/搜索