#{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. 複雜參數傳遞
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}
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>
5.1. 嵌套結果:一條sql
用在多對一的表結構
多個數據字典明細和一個數據字典類型
多個員工屬於一個部門
多個部門有一個部門經理
5.2. 嵌套查詢:1+n條sql
用在一對多或者多對多的表結構
展現數據的時候,在一行第一列顯示一方,第二列顯示多個多方,
一對多:
部門1 員工1。。。員工n
多對多:
員工1 角色1。。。角色n
MyBatis基於代理機制,可讓咱們無需再編寫Dao的實現。
6.1. 傳統Dao接口,如今名稱統一以Mapper結尾
6.2. 接口實現方式一(傳統)
6.3. 接口實現方式二(映射器):
6.4. 實現步驟
6.4.1. 根據需求,建立模型相關的Mapper接口(UserMapper)
6.4.2. 編寫映射文件
7.1. 默認支持一級緩存,二級緩存須要配置,同JPA一致
緩存是一種典型的「以空間換時間」的策略。
7.2. 一級緩存
SqlSession級別緩存,緩存對象存儲週期爲第一次獲取,到sqlsession被銷燬掉,或是sqlSession().clearCache();
7.3. 二級緩存
SqlSessionFactory級別緩存,緩存對象存儲週期爲第一次獲取,到SqlSessionFactory被銷燬掉(應用中止了);
默認狀況下,只開啓一級緩存,若是須要開啓二級緩存咱們須要在Mapper.xml添加一個<cache>標籤和在主配置文件中<setting name="cacheEnabled" value="true"/>;
若是要作三大框架集成,咱們先保證在一個項目,每個框架都可以獨立運行!!
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)
8.3. Spring和MyBatis的集成方式
8.3.1. 框架集成核心
若是你的項目中,用到了Spring框架,那麼其餘框架主要就是和Spring集成!!
8.3.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>
9.1. 重點
9.2. 難點
要使用二級緩存,要求domain必須實現序列化接口
13.1. 擴展知識
http://www.cnblogs.com/gw811/archive/2012/10/10/2718331.html
13.2. 課外閱讀