一、框架概述
day1
1.什么是框架
框架是系統的可重用設計,是對J2EE底層技術的封裝(JDBC,IO流,多線程,Servlet,Socket)。
2.框架解決了哪些問題?
1.解決了技術整合問題
在JavaEE體系中,有着各式各樣的技術,不同的軟件企業,根據自身的業務需求選擇不同的技術,容易造成應用依賴技術,增加了項目開發 的復雜性和技術風險性。企業項目中應該將應用的設計與實現技術解耦。
2.解決提升開發效率的問題
企業項目中使用框架,程序員不再需要重復造輪子,只需要專注實現業務需求,使用框架的方便性,提高開發效率
3.解決了穩定性的問題
一個成熟的框架,經過了眾多企業項目的驗證使用,穩定性有保證
3.J2EE項目的分層:
web層(表現層)-業務層(service)-持久層(dao)
二、總結jdbc開發的問題
1.jdbc開發步驟:
加載驅動
創建數據庫連接對象
定義sql語句
創建Statement語句對象
設置參數
執行
處理結果集
釋放資源
2.jdbc案例程序
第一步:創建項目
第二步:配置pom.xml,導入數據庫驅動包
第三步:編寫案例代碼
1 public class JdbcTest01 { 2 3 public static void main(String[] args) { 4 Connection connection=null; 5 PreparedStatement statement=null; 6 ResultSet resultSet=null; 7 //1.創建jdbc驅動 8 try { 9 Class.forName("com.mysql.jdbc.Driver"); 10 //2.新建連接 11 connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mybatistest", "root", "root"); 12 // //3.書寫sql 13 String sql="SELECT * FROM USER WHERE id =?"; 14 //4.創建預處理對象 15 statement = connection.prepareStatement(sql); 16 //5.獲得結果集對象,設置參數 17 statement.setInt(1,1); 18 //6.執行查詢 19 resultSet = statement.executeQuery(); 20 21 while (resultSet.next()){ 22 System.out.println("用戶的id為:"+resultSet.getInt("id")+"用戶名:"+resultSet.getString("username")); 23 24 } 25 } catch (Exception e) { 26 e.printStackTrace(); 27 }finally { 28 //7.關閉對象 29 try { 30 31 if (resultSet!=null) resultSet.close(); 32 33 if (statement!=null) statement.close(); 34 if (connection!=null) connection.close(); 35 }catch (Exception e){ 36 e.printStackTrace(); 37 } 38 } 39 40 } 41 }
3.總結jdbc開發的問題
1.頻繁創建數據庫連接對象和釋放,容易造成系統資源的浪費,從而影響系統的性能,在企業中,可以通過使用連接池技術解決這個問題,但是使用jdbc需要我們自己來實現連接池,mybatis內部提供連接池
2.sql語句的定義,參數設計,結果集處理存在硬編碼,在企業中sql語句因為需求的變化,所以變化頻繁,一但發生變化,需要修改java代碼,系統需要重新編譯,重新發布,不好維護
3.結果集處理存在重復代碼,每次都要遍歷resultset結果集,獲取一行數據,封裝為對象處理麻煩,如果可以自動把行數據封裝為java對象這樣就方便多了
三、mybatis框架快速入門
1.入門程序實現步驟分析:
第一步:創建Maven項目
第二步:配置pom.xml,導入依賴包
mysql驅動包
mybatis框架包
log4j日志包
第三步:編寫主配置文件(sqlMapConfig.xml)
第四步:編寫用戶實體類
第五步:編寫用戶dao接口
第六步:編寫用戶dao接口的映射文件(建立java對象與sql語句的對應關系)
第七步:在主配置文件sqlMapConfig.xml中,加載接口配置文件
第八步:編寫測試代碼
1 public class MybatisDemo { 2 3 public static void main(String[] args) { 4 5 SqlSession session=null; 6 InputStream inputStream =null; 7 try { 8 //1.加載讀取主配置文件 9 inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); 10 //2.構建新建sqlsessionfatory的必要條件 11 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); 12 //根據配置文件創建sqlsessionfatory 13 SqlSessionFactory sqlSessionFactory = builder.build(inputStream); 14 //3.根據sqlsessionfactory創建session 15 session = sqlSessionFactory.openSession(); 16 17 //4.根據session創建dao代理對象 18 UserDao userDao = session.getMapper(UserDao.class); 19 // System.out.println(userDao.getClass()); 20 21 //5.通過dao代理對象執行sql操作數據庫數據 22 List<User> userList = userDao.selectAllUser(); 23 for (User user:userList){ 24 System.out.println(user); 25 } 26 27 28 } catch (IOException e) { 29 e.printStackTrace(); 30 }finally { 31 try { 32 //6.釋放資源 33 session.close(); 34 inputStream.close(); 35 } catch (IOException e) { 36 e.printStackTrace(); 37 } 38 } 39 } 40 }
四、mybatis框架介紹
mybatis是Apache軟件基金會下的一個開源項目,前身是Ibatis框架。2010年這個項目由apache 軟件基金會遷移到google code下,改名為mybatis。2013年11月又遷移到了github(https://github.com/mybatis/mybatis-3/releases)。
mybatis是一個持久層的框架,是對jdbc操作數據庫的封裝,使開發者只需要關注業務本身,不需要花費精力去處理加載驅動、創建數據庫連接對象、創建statement語句對象、參數設置、結果集處理等一系列繁雜的過程代碼。
mybatis框架通過xml或注解進行配置,將java對象與sql語句中的參數自動映射生成最終執行的sql語句,並將sql語句執行結果自動映射成java對象。
三句話概括介紹:
1. mybatis框架早期版本叫做Ibatis,目前源代碼托管在github
2. mybatis框架是對jdbc操作數據庫的封裝,是一個持久層的框架
3. mybatis框架通過xml或者注解進行配置,實現java對象與sql語句的自動對應關系(orm映射)
五、自定義mybatis框架
1.解析配置文件
1.1.編寫Mapper類:namespace名稱空間,id屬性值,resultType返回值,執行的sql語句
1.2.編寫Configuraton類型:連接數據庫的四個基本要素,數據源對象(c3p0),接口映射文件
線程安全:
SqlSessionFactory:線程安全,因為它是只讀的
SqlSession:線程不安全
兩個用戶:
用戶一:SqlSession新增用戶記錄,操作時間很久。。。。。
用戶二:SqlSession新增訂單記錄,很快就執行完,並且提交事務。
day2
一、mybatis框架實現CRUD操作
1.搭建mybatis框架環境:
第一步:創建maven項目
第二步:配置pom.xml,導入依賴包
mybatis框架包
mysql數據庫驅動包
junit測試包
log4j日志包
第三步:編寫配置文件(sqlMapConfig.xml)
sqlMapConfig.xml
dao接口映射文件
log4j.properties
加載dao接口映射文件
2.實現根據用戶id查詢用戶:
第一步:編寫用戶實體類
第二步:編寫用戶dao(mapper)接口
第三步:編寫用戶dao(mapper)接口映射文件
第四步:在sqlMapConfig.xml,加載dao接口映射文件
根據用戶Id查詢用戶,說明:
3.實現根據用戶名稱模糊查詢用戶:
第一步:聲明mapper接口方法
第二步:配置mapper映射文件
第三步:測試
4.新增用戶:
4.1.事務(增刪改):事務的四個基本特性(ACID)
原子性,一致性,隔離性,持久性
4.2.事務提交方式:
手動提交
自動提交
4.3.注冊成為一個網站的用戶
用戶id是自動增長,不需要傳遞
網站要給我分配權限,需要使用用戶id
要不要查詢出這個id值?答案是要
4.4如何獲取數據庫維護的主鍵值?
5.根據用戶id修改用戶:
第一步:聲明mapper接口方法
第二步:配置mapper映射文件
第三步:測試
6.根據用戶id刪除用戶:
第一步:聲明mapper接口方法
第二步:配置mapper映射文件
第三步:測試
二、mybatis框架輸入輸出映射
1.ParameterType輸入映射(參數)
java簡單類型
pojo類型
pojo包裝類型:就是在pojo中包含了其它的pojo,通常用於接收綜合查詢條件
第一步:編寫pojo包裝類型實體類
第二步:聲明mapper接口方法
第三步:配置mapper映射文件
第四步:測試
2.ResultType返回值輸出
3.ResultMap返回值輸出
需求:查詢全部訂單表數據
需求實現:
編寫訂單實體類
編寫訂單mapper接口
編寫訂單mapper映射文件
在sqlMapConfig.xml加載訂單mapper映射文件
三、mybatis框架持久層開發的兩種方法
1.mapper代理開發方法【重點掌握-記住開發的原則】
2.傳統的dao開發方法【了解】
第一步:編寫mapper映射文件
第二步:編寫dao接口
第三步:編寫dao接口實現類
第四步:測試
四、mybatis框架注意事項
1.占位符#{}與字符串拼接符${}區別【重點】
(1).占位符 #{}
當參數傳遞的是java簡單類型(八種基本類型+字符串String)的時候,花括號中的內容可以是任意字符串
(2).字符串拼接符${}
當參數傳遞的是java簡單類型(八種基本類型+字符串String)的時候,花括號中的內容只能是value
(3).#{}、${}當參數傳遞的pojo類型的時候,花括號中的內容都是pojo的屬性
2.
id:唯一標識名稱,與接口方法名稱一致
parameterType:輸入參數類型,與接口方法形參類型一致
resultType:
返回值類型(暫時注意:它是po類的全限定名稱),與接口方法返回值類型一致,如果是List<User>,這種返回形式,則直接返回User
#{id}:占位符,相當於jdbc中的問號
獲取數據庫維護的主鍵值
selectKey:
作用:查詢數據庫維護的主鍵值
屬性:
keyColumn:主鍵字段
keyProperty:實體類中的屬性(與主鍵字段對應)
resultType:主鍵數據類型
resultMap:用於配置實體類屬性與數據庫表字段一一對應的
type:要映射的java對象類型
id:唯一標識名稱,通過id引用該resultMap
order:在insert語句執行前,還是執行后獲取主鍵值。BEFORE:在insert執行前;AFTER:在insert語句執行后
說明:直接在insert標簽中增加屬性的方式,只適合於支持自動增長主鍵類型的數據庫,比如mysql。
3.注意事項:java程序代碼執行成功,但是數據庫中並沒有新增記錄。原因是沒有提交事務,在對數據庫的更新操作中(增、刪、改)要求提交事務。
自動提交的特點,只要操作一完成,立即提交。如果在同一個方法中,有多個數據庫操作,需要使用手動提交的方式。
(方式一)創建SqlSession,指定自動提交事務。true:自動提交;false:不提交。默認是false
1 SqlSession sqlSession = sqlSessionFactory.openSession(true);
(方式二)手動提交事務
sqlSession.commit();
4 mapper代理開發方法【掌握】
從入門程序開始,一直使用的方式,即mapper代理開發的方法。特點:
1. 在開發的時候,只需要編寫持久層的接口,和持久層接口映射文件(mapper映射文件)。
2. 在執行的時候,mybatis框架通過動態代理生成接口的代理對象。
3. 總結mapper代理開發原則【記住】
1. mapper映射文件中namespace屬性值,必須是mapper接口的全限定名稱
2. mapper映射文件中sql語句標簽的聲明,與mapper接口中接口方法聲明一致
2.1.sql語句標簽中resultType屬性指定的返回值類型,與mapper接口方法返回值類型一致。(如果接口方法返回的是集合list,則resultType指定的是list中存放的類型)
2.2.sql語句標簽中的id屬性值,與mapper接口方法名稱一致
2.3.sql語句標簽中的parameterType屬性指定的類型,與mapper接口方法的形參類型一致
day3
一、mybaits連接池
1.JNDI:java的名稱服務,用於從容器中獲取數據庫的連接(tomcat)
2.POOLED:使用連接池技術
3.UNPOOLED:不使用連接池技術(相當於原生的jdbc操作)
二、mybatis事務控制
1.手動提交
2.自動提交
3.mybatis框架的事務,底層都還是jdbc的事務操作
三、mybatis動態sql
1.動態sql案例(需求:根據用戶名稱和性別查詢用戶)
1.聲明mapper接口方法
2.配置mapper映射文件
2.if標簽
作用:判斷傳入的參數情況,拼裝sql語句片段
1 <!--根據用戶名稱和性別查詢用戶--> 2 <select id="findUserByNameAndSex"parameterType="user"resultType="user"> 3 select * from `user` 4 where <!--username like #{username} and sex=#{sex}--> 5 <!--if:判斷用戶名稱不為空,且不為空字符串,則作為查詢條件--> 6 <if test="username !=null and username !=''"> 7 username like #{username} 8 </if> 9 <!--if:判斷用戶性別不為空,且不為空字符串,則作為查詢條件--> 10 <if test="sex !=null and sex !=''"> 11 and sex=#{sex} 12 </if> 13 </select>
3.where標簽
作用:
1.相當於sql語句中的where關鍵字
2.根據傳入的參數情況,智能的去掉多余的and,or關鍵字
3.根據傳入的參數情況,智能的去掉多余的where關鍵字
1 <!--根據用戶名稱和性別查詢用戶--> 2 <select id="findUserByNameAndSex"parameterType="user"resultType="user"> 3 select * from `user` 4 <!-- where username like #{username} and sex=#{sex}--> 5 <where> 6 <!--if:判斷用戶名稱不為空,且不為空字符串,則作為查詢條件--> 7 <if test="username !=null and username !=''"> 8 username like #{username} 9 </if> 10 <!--if:判斷用戶性別不為空,且不為空字符串,則作為查詢條件--> 11 <if test="sex !=null and sex !=''"> 12 and sex=#{sex} 13 </if> 14 </where> 15 16 </select>
4.set標簽:
作用:
1.相當於sql語句中的set關鍵字
2.根據傳入的參數情況,智能的去掉最后一個多余的逗號
1 <!-- 動態修改用戶數據 --> 2 <update id="dynamicUpdateUser"parameterType="user"> 3 update `user` 4 <!-- set username='小李飛刀',sex='2' where id=2 --> 5 <set> 6 <if test="username != null and username !=''"> 7 username=#{username}, 8 </if> 9 <if test="sex != null and sex !=''"> 10 sex=#{sex}, 11 </if> 12 </set> 13 14 <where> 15 id=#{id} 16 </where> 17 </update>
5.sql(include)標簽:
作用:
1.提取公共的sql語句片段
1 <!--sql:提取公共的sql語句片段,說明: 2 id:唯一標識名稱,通過id引用該sql片段 3 --> 4 <sql id="select_orders_list"> 5 o.id,o.user_id,o.number,o.createtime,o.note 6 </sql> 7 8 <!--查詢全部訂單數據,使用resultType實現--> 9 <select id="findAllOrders"resultType="cn.itheima.po.Orders"> 10 <!--include:引用sql語句片段,說明: 11 refid:sql語句片段的id屬性值 12 --> 13 select <include refid="select_orders_list"></include> from orders o 14 </select>
6.foreach標簽:
作用:
1.循環處理參數集合(list,數組)
1 <!-- 批量新增用戶--> 2 <insert id="batchAddUsers"parameterType="list"> 3 insert into `user`(username,birthday,sex,address) 4 values 5 <!-- foreach:循環處理參數集合 6 collection:參數集合,這里是list(固定寫法) 7 item:當前遍歷的對象 8 separator:指定分割符 9 --> 10 <foreach collection="list"item="u"separator=","> 11 (#{u.username},#{u.birthday},#{u.sex},#{u.address}) 12 </foreach> 13 <!-- ('用戶1','2018-07-08','1','地址1'),('用戶2','2018-07-08','1','地址2') --> 14 </insert>
四、mybatis關聯查詢
1.關聯關系分類:
一對一關聯關系:人和身份證關系,【雙向的】一對一關系
一對多關聯關系:用戶和訂單的關系
多對多關聯關系:用戶和角色
2.分析用戶訂單數據模型:
第一步:先確定單表有什么字段
第二步:找出關聯字段
第三步:結合業務需求確定表的關系
3.一對一關聯查詢:
實現思路:
第一步:編寫sql語句
第二步:聲明mapper接口方法
第三步:配置mapper映射文件
通過ResultType實現:
關鍵步驟:編寫一個實體類,包含sql語句中的字段對應屬性
通過ResultMap實現(<association/>):
關鍵步驟:在實體類之間建立關系,建立訂單到用戶的一對一關系
<!-- 配置訂單到用戶的一對一關聯關系,說明: type:要映射的類型 id:唯一標識名稱,通過id引用該resultMap --> <resultMap type="orders"id="ordersUsersResultMap"> <!-- 配置訂單主鍵字段對應關系 --> <id column="id"property="id"/> <!-- 配置訂單的普通字段對應關系 --> <result column="user_id"property="userId"/> <result column="number"property="number"/> <result column="createtime"property="createtime"/> <result column="note"property="note"/> <!-- association:配置一對一關聯關系,說明: property:要映射的屬性名稱 javaType:要映射的屬性類型(必須要指定) --> <association property="user"javaType="User"> <!-- 配置用戶的主鍵字段對應關系 --> <id column="user_id"property="id"/> <!-- 配置用戶的普通字段對應關系 --> <result column="username"property="username"/> <result column="address"property="address"/> </association> </resultMap> <!-- 查詢全部訂單數據,並且關聯查詢訂單所屬的用戶數據(resultMap)--> <select id="findAllOrdersAndUserResultMap"resultMap="ordersUsersResultMap"> SELECT o.id, o.user_id, o.number, o.createtime, o.note, u.username, u.address FROM orders o LEFT JOIN `user` u ON o.user_id = u.id </select>
4.一對多關聯查詢:
實現思路:
第一步:編寫sql語句
第二步:聲明mapper接口方法
第三步:配置mapper映射文件
思考題:一對多能不能使用ResultType實現? 不能使用ResultType實現
使用ResultMap實現(<collection/>):
關鍵步驟:在實體類之間建立關系,建立用戶到訂單的一對多關系
<!-- 配置用戶到訂單的一對多關聯關系,說明: type:要映射的類型 id:唯一標識名稱,通過id引用該resultMap --> <resultMap type="user"id="usersOrdersResultMap"> <!-- 配置用戶的主鍵字段對應關系 --> <id column="id"property="id"/> <!-- 配置用戶的普通字段對應關系 --> <result column="username"property="username"/> <result column="birthday"property="birthday"/> <result column="sex"property="sex"/> <result column="address"property="address"/> <!-- collection:配置一對多關聯關系,說明: property:要映射的屬性名稱 javaType:要映射的屬性類型(可以指定,可以不指定,建議都指定) ofType:指定集合中存放的類型(必須要指定) --> <collection property="ordersList"javaType="List"ofType="Orders"> <!-- 配置訂單的主鍵對應關系 --> <id column="oid"property="id"/> <!-- 配置訂單普通字段對應關系 --> <result column="number"property="number"/> <result column="createtime"property="createtime"/> </collection> </resultMap> <!-- 查詢全部用戶數據,並且關聯查詢出用戶的所有訂單數據 --> <select id="findAllUsersAndOrders"resultMap="usersOrdersResultMap"> SELECT u.id, u.username, u.birthday, u.sex, u.address, o.id oid, o.number, o.createtime FROM `user` u LEFT JOIN orders o ON u.id = o.user_id </select>
5.多對多關聯查詢:通過中間表看成兩個一對多關聯關系
需求:查詢用戶數據,並且關聯查詢出用戶的角色數據
實現思路:
第一步:編寫sql語句
第二步:聲明mapper接口方法
第三步:配置mapper映射文件
關鍵步驟:在實體類之間建立關系,建立用戶到角色的一對多關系
<!-- 配置用戶到角色的一對多關聯關系,說明: type:要映射的類型 id:唯一標識名稱,通過id引用該resultMap --> <resultMap type="user"id="usersRolesResultMap"> <!-- 配置用戶的主鍵字段對應關系 --> <id column="id"property="id"/> <!-- 配置用戶的普通字段對應關系 --> <result column="username"property="username"/> <result column="birthday"property="birthday"/> <result column="sex"property="sex"/> <result column="address"property="address"/> <!-- collection:配置一對多關聯關系,說明: property:要映射的屬性名稱 javaType:要映射的屬性類型(可以指定,可以不指定,建議都指定) ofType:指定集合中存放的類型(必須要指定) --> <collection property="roleList"javaType="List"ofType="Role"> <!-- 配置訂單的主鍵對應關系 --> <id column="role_id"property="roleId"/> <!-- 配置訂單普通字段對應關系 --> <result column="role_name"property="roleName"/> </collection> </resultMap> <!-- 查詢用戶數據,並且關聯查詢用戶的所有角色數據--> <select id="findUsersAndRoles"resultMap="usersRolesResultMap"> SELECT u.id, u.username, u.birthday, u.sex, u.address, r.role_id, r.role_name FROM `user` u INNER JOIN user_role ur ON u.id = ur.user_id INNER JOIN role r ON ur.role_id = r.role_id </select>
day4
一、mybatis延遲加載
1.什么是延遲加載?
延遲加載,叫做懶加載,按需加載。
它的特點關聯查詢中,分步驟實現查詢(每一步都是單表操作)
2.延遲加載案例演示:
查詢訂單數據,並且關聯查詢出訂單所屬的用戶數據。采用延遲加載的方式實現。
實現步驟:
第一步:只從訂單表查詢訂單數據
第二步:在需要的時候,在查詢用戶表的數據
第三步:配置mybatis框架,開啟延遲加載
延遲加載的注意事項:toString方法和debug調試模式看不到延遲加載的效果
3.一對多關聯查詢的延遲加載方式實現:
第一步:單表查詢用戶數據
第二步:在需要的時候,再查詢訂單表的數據
第三步:配置mybatis框架,開啟延遲加載
二、mybatis緩存
1.一級緩存:sqlSession范圍的緩存,一級緩存本身就已經存在,不需要關心
2.二級緩存:mapper級別級別,在多個sqlSession之間可以共享數據
第一步:需要配置sqlMapConfig.xml,開啟二級緩存
第二步:序列化Seriallizable,實體類對象需要實現序列化
第三步:在mapper映射文件,還需要明確是否使用緩存
說明:mybatis的二級緩存只做了解,在企業項目中不推薦使用。原因是mybatis的緩存
不能實現【細粒度】的控制。實際項目中我們會考慮使用像redis中間件
三、mybatis注解開發【了解】
1.注解基本操作(CRUD操作):
查詢:@Select
修改:@Update
刪除:@Delete
新增:@Insert
獲取數據庫維護的主鍵值:
@SelectKey
2.注解高級操作(關聯查詢):
@Results注解:相當於xml文件中的<ResultMap/>標簽
@Result注解:相當於<ResultMap/>的子標簽<id/>和<result/>
@One注解:配置一對一關聯關系,相當於xml中的<association/>,可以實現延遲加載
@Many注解:配置一對多關聯關系,相當於xml中的<collection/>標簽,可以實現延遲加載
延遲加載方式實現:一對一關聯查詢的方式:
實現步驟:
第一步:只從訂單表查詢數據
第二步:在需要的時候,查詢用戶表數據
第三步:在sqlMapConfig.xml中,配置延遲加載
延遲加載方式實現:一對多關聯查詢:
需求:查詢全部用戶數據,並且關聯查詢出用戶的全部訂單數據。采用延遲加載的方式實現
實現步驟:
第一步:只查詢用戶表數據
第二步:在需要的時候,查詢訂單表的數據
第三步:在sqlMapConfig.xml中,配置延遲加載