SSM框架整合(参考尚硅谷视频和文档
一、MyBatis
1、MyBatis簡介
1.1、MyBatis歷史?
MyBatis最初是Apache的一個開源項目iBatis, iBatis3.x正式更名為MyBatis。代碼于 2013年11月遷移到Github iBatis一詞來源于“internet”和“abatis”的組合,是一個基于Java的持久層框架。 iBatis提供的持久層框架包括SQL Maps和Data Access Objects(DAO)。1.2、MyBatis特性
1) MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的持久層框架 2) MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集 3) MyBatis可以使用簡單的XML或注解用于配置和原始映射,將接口和Java的POJO(Plain Old Java Objects,普通的Java對象)映射成數據庫中的記錄 4) MyBatis 是一個 半自動的ORM(Object Relation Mapping)框架 Object Relation Mapping 對象 關系數據庫 映射1.3、MyBatis下載
MyBatis下載地址:https://github.com/mybatis/mybatis-3?
1.4、和其它持久化層技術對比
- JDBC? ? ? ?
- Hibernate 和 JPA
- MyBatis
2、搭建MyBatis
2.1、開發環境
IDE:idea 2021.1.3 構建工具:maven 3.5.4 MySQL版本:MySQL 8 MyBatis版本:MyBatis 3.5.7 MySQL不同版本的注意事項 1、驅動類driver-class-name MySQL 5版本使用jdbc5驅動,驅動類使用:com.mysql.jdbc.Driver MySQL 8版本使用jdbc8驅動,驅動類使用:com.mysql.cj.jdbc.Driver 2、連接地址url MySQL 5版本的url: jdbc:mysql://localhost:3306/ssm MySQL 8版本的url: jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC 否則運行測試用例報告如下錯誤: java.sql.SQLException: The server time zone value '?D1ú±ê×?ê±??' is unrecognized or represents more2.2、創建maven工程
①打包方式:jar ②引入依賴 <dependencies><!-- Mybatis核心 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency><!-- junit測試 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- MySQL驅動 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency> </dependencies>2.3、創建MyBatis的核心配置文件
習慣上命名為mybatis-config.xml,這個文件名僅僅只是建議,并非強制要求。將來整合Spring 之后,這個配置文件可以省略,所以大家操作時可以直接復制、粘貼。 核心配置文件主要用于配置連接數據庫的環境以及MyBatis的全局配置信息 核心配置文件存放的位置是src/main/resources目錄下 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><!--配置連接數據庫的環境--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC"/><property name="username" value="root"/><property name="password" value="XXXX"/></dataSource></environment></environments><!--引入mybatis的映射文件--><mappers><package name=""/></mappers> </configuration>2.4、創建mapper接口 ?
MyBatis中的mapper接口相當于以前的dao。但是區別在于,mapper僅僅是接口,我們不需要提供實現類。 public interface UserMapper {int insertUser();}2.5、創建MyBatis的映射文件
相關概念:ORM(Object Relationship Mapping)對象關系映射。- 對象:Java的實體類對象
- 關系:關系型數據庫
- 映射:二者之間的對應關系
?
?1、映射文件的命名規則:
表所對應的實體類的類名+Mapper.xml 例如:表t_user,映射的實體類為User,所對應的映射文件為UserMapper.xml 因此一個映射文件對應一個實體類,對應一張表的操作 MyBatis映射文件用于編寫SQL,訪問以及操作表中的數據 MyBatis映射文件存放的位置是src/main/resources/mappers目錄下 2、 MyBatis中可以面向接口操作數據,要保證兩個一致: a>mapper接口的全類名和映射文件的命名空間(namespace)保持一致 b>mapper接口中方法的方法名和映射文件中編寫SQL的標簽的id屬性保持一致 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.atguigu.mybatis.mapper.UserMapper"><!--mapper接口和映射文件要保證兩個一致:1、mapper接口的全類名和映射文件的namespace一致2、mapper接口中的方法的方法名要和映射文件中的sql的id保持一致--><!-- int insertUser();--><insert id="insertUser">insert into t_user values (null,'admin','123456',23,'男','12345@qq.com');</insert></mapper>?2.6、通過junit測試功能
@Testpublic void testInsert() throws IOException {//獲取核心配置文件的輸入流(讀的功能/輸出流(寫的功能))InputStream is = Resources.getResourceAsStream("mybatis-config.xml");//獲取SqlSessionFactoryBuilder對象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//獲取SqlSessionFactory對象SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);//獲取sql的會話對象Sqlsession(不會自動提交事務),是Mybatis提供的操作數據庫的對象 // SqlSession sqlSession = sqlSessionFactory.openSession();//獲取sql的會話對象Sqlsession(會自動提交事務),是Mybatis提供的操作數據庫的對象SqlSession sqlSession = sqlSessionFactory.openSession(true);//獲取UserMapper的代理實現對象UserMapper mapper = sqlSession.getMapper(UserMapper.class);//調用mapper接口中的方法,實現添加用戶信息的功能int result = mapper.insertUser();System.out.println("結果:" + result);//提交事務 // sqlSession.commit();//關閉sqlsessionsqlSession.close();}測試遇到的報錯:
org.apache.ibatis.binding.BindingException: Type interface com.atguigu.mybatis.mapper.UserMapper is not known to the MapperRegistry.
錯誤原因:核心配置文件中沒有注冊mappers
解決方法1:在核心配置文件中注冊每個mapper
<!--引入mybatis的映射文件--><mappers><mapper resource="mappers/UserMapper.xml"/></mappers>解決方法2:以包的方式批量注冊mapper
<mappers><!--以包的方式引入映射文件,但是必須滿足兩個條件:1、mapper接口和映射文件所在的包必須一致2、mapper接口的名字和映射文件的名字必須一致--><package name="com.atguigu.mybatis.mapper"/></mappers> SqlSession:代表Java程序和數據庫之間的會話。(HttpSession是Java程序和瀏覽器之間的會話) SqlSessionFactory:是“生產”SqlSession的“工廠”。 工廠模式:如果創建某一個對象,使用的過程基本固定,那么我們就可以把創建這個對象的相關代碼封裝到一個“工廠類”中,以后都使用這個工廠類來“生產”我們需要的對象。?2.7、加入log4j日志功能
①加入依賴 <!-- log4j日志 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency>?②加入log4j的配置文件
log4j的配置文件名為log4j.xml,存放的位置是src/main/resources目錄下 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"><appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"><param name="Encoding" value="UTF-8" /><layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /></layout></appender><logger name="java.sql"><level value="debug" /></logger><logger name="org.apache.ibatis"><level value="info" /></logger><root><level value="debug" /><appender-ref ref="STDOUT" /></root> </log4j:configuration> 日志的級別 FATAL(致命)>ERROR(錯誤)>WARN(警告)>INFO(信息)>DEBUG(調試) 從左到右打印的內容越來越詳細3、核心配置文件詳解?
?核心配置文件中的標簽必須按照固定的順序:
properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,refl ectorFactory?,plugins?,environments?,databaseIdProvider?,mappers? <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><!--MyBatis核心配置文件中的標簽必須要按照指定的順序配置:The content of element type "configuration" must match"(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".--><!--引入properties文件,此后就可以在當前文件中使用${key}的方式訪問value--><properties resource="jdbc.properties"/><!--typeAliases:設置類型別名,即為某個具體的類型設置一個別名在MyBatis的范圍中,就可以使用別名表示一個具體的類型--><typeAliases><!--type:設置需要起別名的類型alias:設置某個類型的別名--> <!-- <typeAlias type="com.atguigu.mybatis.pojo.User" alias="abc"></typeAlias>--><!--若不設置alias,當前的類型擁有默認的別名,即類名且不區分大小寫--> <!-- <typeAlias type="com.atguigu.mybatis.pojo.User"></typeAlias>--><!--通過包設置類型別名,指定包下所有的類型將全部擁有默認的別名,即類名且不區分大小寫--><package name="com.atguigu.mybatis.pojo"/></typeAliases><!--environments:配置連接數據庫的環境屬性:default:設置默認使用的環境的id--><environments default="development"><!--environment:設置一個具體的連接數據庫的環境屬性:id:設置環境的唯一標識,不能重復--><environment id="development"><!--transactionManager:設置事務管理器屬性:type:設置事務管理的方式type:"JDBC|MANAGED"JDBC:表示使用JDBC中原生的事務管理方式MANAGED:被管理,例如Spring--><transactionManager type="JDBC"/><!--dataSource:設置數據源屬性:type:設置數據源的類型type="POOLED|UNPOOLED|JNDI"POOLED:表示使用數據庫連接池UNPOOLED:表示不使用數據庫連接池JNDI:表示使用上下文中的數據源--><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment><environment id="test"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC"/><property name="username" value="root"/><property name="password" value="XXXX"/></dataSource></environment></environments><!--引入mybatis的映射文件--><mappers> <!-- <mapper resource="mappers/UserMapper.xml"/>--><!--以包的方式引入映射文件,但是必須滿足兩個條件:1、mapper接口和映射文件所在的包必須一致2、mapper接口的名字和映射文件的名字必須一致--><package name="com.atguigu.mybatis.mapper"/></mappers> </configuration>4、MyBatis的增刪改查
4.1、新增
<!-- int insertUser();--><insert id="insertUser">insert into t_user values (null,'admin','123456',23,'男','12345@qq.com')</insert>4.2、刪除
<!--void deleteUser();--><delete id="deleteUser">delete from t_user where id = 3</delete>4.3、修改
<!--void updateUser();--><update id="updateUser">update t_user set username='root',password='123' where id = 3</update>?4.4、查詢一個實體類對象
<!--User getUserById();--><!--resultType:設置結果類型,即查詢的數據要轉換為的java類型resultMap:自定義映射,處理多對一或一對多的映射關系--><select id="getUserById" resultType="com.atguigu.mybatis.pojo.User">select * from t_user where id = 1</select>4.5、查詢list集合
<!--List<User> getAllUser();--><select id="getAllUser" resultType="User">select * from t_user</select> 注意: 查詢的標簽select必須設置屬性resultType或resultMap,用于設置實體類和數據庫表的映射關系 resultType:自動映射,用于屬性名和表中字段名一致的情況 resultMap:自定義映射,用于一對多或多對一或字段名和屬性名不一致的情況5、MyBatis獲取參數值的兩種方式 ?
MyBatis獲取參數值的兩種方式:${}和#{}
${}的本質就是字符串拼接,#{}的本質就是占位符賦值
${}使用字符串拼接的方式拼接sql,若為字符串類型或日期類型的字段進行賦值時,需要手動加單引號; #{}使用占位符賦值的方式拼接sql,此時為字符串類型或日期類型的字段進行賦值時,可以自動添加單引號5.1、單個字面量類型的參數 ?
若mapper接口方法的參數為單個的字面量類型
此時可以通過#{}和${}以任意的內容獲取參數值,一定要注意${}的單引號問題
5.2、多個字面量類型的參數
若mapper接口方法的參數為多個的字面量類型 此時MyBatis會將參數放在map集合中,以兩種方式存儲數據 a>以arg0,arg1...為鍵,以參數為值 b>以param1,param2...為鍵,以參數為值 因此,只需要通過#{}和${}訪問map集合的鍵,就可以獲取相對應的值,一定要注意${}的單引號問題5.3、map集合類型的參數
若mapper接口方法的參數為map集合類型的參數 只需要通過#{}和${}訪問map集合的鍵,就可以獲取相對應的值,一定要注意${}的單引號問題5.4、實體類類型的參數
若mapper接口方法的參數為實體類類型的參數 只需要通過#{}和${}訪問實體類中的屬性名(把方法里的get\set去掉剩余部分的首字母變為小寫的結果就是屬性名),就可以獲取相對應的屬性值,一定要注意${}的單引號問題 可以在mapper接口方法的參數上設置@Param注解此時MyBatis會將這些參數放在map中,以兩種方式進行存儲
a>以@Param注解的value屬性為鍵,以參數為值
b>以param1,param2...為鍵,以參數為值
只需要通過#{}和${}訪問map集合的鍵,就可以獲取相對應的值,一定要注意${}的單引號問題
5.5、使用@Param標識參數
可以在mapper接口方法的參數上設置@Param注解此時MyBatis會將這些參數放在map中,以兩種方式進行存儲
a>以@Param注解的value屬性為鍵,以參數為值
b>以param1,param2...為鍵,以參數為值
只需要通過#{}和${}訪問map集合的鍵,就可以獲取相對應的值,一定要注意${}的單引號問題
?6、MyBatis的各種查詢功能
6.1、查詢一個實體類對象
/*** 根據id查詢用戶信息* @param id* @return*/User getUserById(@Param("id") Integer id); <!--User getUserById(@Param("id") Integer id);--><select id="getUserById" resultType="com.atguigu.mybatis.pojo.User">select * from t_user where id = #{id}</select>6.2、查詢一個list集合
/*** 查詢所有的用戶信息* @return*/List<User> getAllUser(); <!--User getUserById(@Param("id") Integer id);--><select id="getAllUser" resultType="com.atguigu.mybatis.pojo.User">select * from t_user</select> 若sql語句查詢的結果為多條時,一定不能以實體類類型作為方法的返回值,否則會拋出異常TooManyResultsException 若sql語句查詢的結果為1條時,此時可以使用實體類類型或list集合類型作為方法的返回值6.3、查詢單個數據
/*** 查詢用戶的總數量* @return*/Integer getCount(); <!--Integer getCount();--><!--MyBatis中為Java中常用的類型設置了類型別名Integer:Integer,intint:_int,_integerMap:mapString:string--><select id="getCount" resultType="java.lang.Integer">select count(*) from t_user</select>?MyBatis中為Java中常用的類型設置了類型別名
?6.4、查詢一條數據為map集合
/*** 根據id查詢用戶信息為map集合* @param id* @return*/Map<String,Object> getUserByIdToMap(@Param("id") Integer id); <!--Map<String,Object> getUserByIdToMap(@Param("id") Integer id);--> <!--結果:{password=123456, gender=男, enail=12345@qq.com, id=1, age=23, username=admin}--><select id="getUserByIdToMap" resultType="java.util.Map">select * from t_user where id = #{id}</select>6.5、查詢多條數據為map集合
①方式一 /*** 查詢所有的用戶信息為map集合* 若查詢的數據有多條時,并且要將每條數據轉換為map集合* 此時有兩種解決方案:* 1、將mapper接口方法的返回值設置為泛型時map的list集合* List<Map<String,Object>> getAllUserToMap();* 結果: [* {password=123456, gender=男, enail=12345@qq.com, id=1, age=23, username=admin},* {password=123456, gender=女, enail=123@qq.com, id=2, age=33, username=root}* ]** @return*/List<Map<String,Object>> getAllUserToMap(); <!--List<Map<String,Object>> getAllUserToMap();--><select id="getAllUserToMap" resultType="java.util.Map">select * From t_user</select> ②方式二 /*** 查詢所有的用戶信息為map集合* 若查詢的數據有多條時,并且要將每條數據轉換為map集合* 此時有兩種解決方案:* 2、可以將每條數據轉的map集合放在一個大的map中,但是必須要通過@MapKey注解* 將查詢的某個字段的值作為大的map的鍵* @MapKey("id")* Map<String, Object> getAllUserToMap();* 結果: {* 1={password=123456, gender=男, enail=12345@qq.com, id=1, age=23, username=admin},* 2={password=123456, gender=女, enail=123@qq.com, id=2, age=33, username=root}* }** @return*/@MapKey("id")Map<String,Object> getAllUserToMap(); <!--Map<String,Object> getAllUserToMap();--><select id="getAllUserToMap" resultType="java.util.Map">select * From t_user</select>7、特殊SQL的執行
7.1、模糊查詢
/*** 通過用戶名模糊查詢用戶信息* @param mohu* @return*/List<User> getUserByLike(@Param("mohu") String mohu); <!--List<User> getUserByLike(@Param("mohu") String mohu);--><select id="getUserByLike" resultType="com.atguigu.mybatis.pojo.User"><!--第一種方式:select * from t_user where username like '%${mohu}%'--><!--第二種方式:select * from t_user where username like concat('%',#{mohu},'%')--><!--最常用第三種方式:select * from t_user where username like "%"#{mohu}"%"-->select * from t_user where username like "%"#{mohu}"%"</select>mysql中模糊查詢語句:
select * from t_user where username like '%a%';?7.2、批量刪除
/*** 批量刪除* @param ids*/void deleteMoreUser(@Param("ids") String ids); <!--void deleteMoreUser(@Param("ids") String ids);//ids:9,10--><delete id="deleteMoreUser">delete from t_user where id in(${ids})</delete>7.3、動態設置表名
/*** 動態設置表名,查詢用戶信息* @param tableName* @return*/List<User> getUserList(@Param("tableName") String tableName); <!--List<User> getUserList(@Param("tableName") String tableName);--><select id="getUserList" resultType="com.atguigu.mybatis.pojo.User">select * from ${tableName}</select>7.4、添加功能獲取自增的主鍵
/*** 添加用戶信息并獲取自增的主鍵* @param user*/void insertUser(User user); <!--void insertUser(User user);--><!--重要:useGeneratedKeys:表示當前添加功能使用自增的主鍵keyProperty:因為增刪改有統一的返回值是受影響的行數,因此只能將添加的自增主鍵為實體類類型的參數的屬性賦值--><insert id="insertUser" useGeneratedKeys="true" keyProperty="id">insert into t_user values(null,#{username},#{password},#{age},#{gender},#{email})</insert>8、自定義映射resultMap
8.1、resultMap處理字段和屬性的映射關系
若字段名和實體類中的屬性名不一致,則可以通過resultMap設置自定義映射 /*** 根據id查詢員工信息* @param empId* @return*/Emp getEmpByEmpId(@Param("empId") Integer empId); <!--resultMap:設置自定義的映射關系id:唯一標識type:處理映射關系的實體類類型常用的標簽:id:處理主鍵和實體類中屬性的映射關系result:處理普通字段和實體類中屬性的映射關系column:設置映射關系中的字段名,必須時sql查詢出的某個字段property:設置映射關系中的屬性的屬性名,必須時處理的實體類類型中的屬性名--><resultMap id="empResultMap" type="emp"><id column="emp_id" property="empId"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="gender" property="gender"></result></resultMap><!--Emp getEmpByEmpId(@Param("empId") Integer empId);--><select id="getEmpByEmpId" resultMap="empResultMap">select * from t_emp where emp_id = #{empId}</select>字段名和屬性名不一致的情況,如何處理映射關系
1、為查詢的字段設置別名,和屬性名保持一致
2、當字段符合MySQL的要求使用_,而屬性符合java的要求使用駝峰
此時可以在MyBatis的核心配置文件中設置一個全局配置,可以自動將下劃線映射為駝峰
例如:字段名user_name,設置了mapUnderscoreToCamelCase,此時字段名就會轉換為userName
3、使用resultMap自定義映射處理
處理多對一的映射關系:
1、級聯方式處理
2、association
3、分步查詢
處理一對多的映射關系:
1、collection
2、分步查詢
?8.2、多對一映射處理
對一對應對象,對多對應集合 場景模擬: 查詢員工信息以及員工所對應的部門信息 MySQL中多表查詢: SELECT t_emp.*,t_dept.* FROM t_emp LEFT JOIN t_dept ON t_emp.dept_id = t_dept.dept_id WHERE t_emp.emp_id = 1?8.2.1、級聯方式處理映射關系
<resultMap id="empAndDeptResultMap" type="emp"><id column="emp_id" property="empId"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="gender" property="gender"></result><result column="dept_id" property="dept.deptId"></result><result column="dept_name" property="dept.deptName"></result></resultMap><!--Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);--><select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">selectt_emp.*,t_dept.*from t_empleft join t_depton t_emp.dept_id = t_dept.dept_idwhere t_emp.emp_id = #{empId}</select> 8.2.2、使用association處理映射關系 <resultMap id="empAndDeptResultMap" type="emp"><id column="emp_id" property="empId"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="gender" property="gender"></result><!--association:處理多對一的映射關系(處理實體類類型的屬性)property:設置需要處理映射關系的屬性的屬性名javaType:設置要處理的屬性的類型--><association property="dept" javaType="Dept"><id column="dept_id" property="deptId"></id><result column="dept_name" property="deptName"></result></association></resultMap><!--Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);--><select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">selectt_emp.*,t_dept.*from t_empleft join t_depton t_emp.dept_id = t_dept.dept_idwhere t_emp.emp_id = #{empId}</select> 8.2.3、分步查詢 ①查詢員工信息 /*** 通過分步查詢員工以及所對應的部門信息的第一步* @param empId* @return*/Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId); <resultMap id="empAndDeptByStepResultMap" type="emp"><id column="emp_id" property="empId"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="gender" property="gender"></result><!--property:設置需要處理映射關系的屬性的屬性名select:設置分布查詢的sql的唯一標識column:將查詢出的某個字段作為分布查詢的sql的條件fetchType:在開啟了延遲加載的環境中,通過該屬性設置當前的分步查詢是否使用延遲加載fetchType="eager(立即加載)|lazy(延遲加載)"--><association property="dept" fetchType="eager"select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"column="dept_id"></association></resultMap><!--Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);--><select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">select * from t_emp where emp_id =#{empId}</select> ②根據員工所對應的部門id查詢部門信息 /*** 通過分步查詢員工以及所對應的部門信息的第二步* @return*/Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId); <!--Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId);--><select id="getEmpAndDeptByStepTwo" resultType="com.atguigu.mybatis.pojo.Dept">select * from t_dept where dept_id = #{deptId}</select>8.3、一對多映射處理
8.3.1、collection /*** 查詢部門以及部門中的員工信息* @param deptId* @return*/Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId); <resultMap id="deptAndEmpResultMap" type="dept"><id column="dept_id" property="deptId"></id><result column="dept_name" property="deptName"></result><!--ofType:設置集合類型的屬性中存儲的數據的類型--><collection property="emps" ofType="emp"><id column="emp_id" property="empId"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="gender" property="gender"></result></collection></resultMap><!--Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);--><select id="getDeptAndEmpByDeptId" resultMap="deptAndEmpResultMap">select *from t_deptleft join t_empon t_dept.dept_id= t_emp.dept_idwhere t_dept.dept_id = #{deptId}</select> 8.3.2、分步查詢 ①查詢部門信息 /*** 通過分步查詢查詢部門以及部門中的員工信息的第一步* @param deptId* @return*/Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId); <resultMap id="deptAndEmpResultMapByStep" type="Dept"><id column="dept_id" property="deptId"></id><result column="dept_name" property="deptName"></result><collection property="emps"select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"column="dept_id"></collection></resultMap><!--Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);--><select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpResultMapByStep">select * from t_dept where dept_id = #{deptId}</select> ②根據部門id查詢部門中的所有員工 /*** 通過分步查詢查詢部門以及部門中的員工信息的第二步* @param deptId* @return*/List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId); <!--List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);--><select id="getDeptAndEmpByStepTwo" resultType="com.atguigu.mybatis.pojo.Emp">select * from t_emp where dept_id = #{deptId}</select> 分步查詢的優點:可以實現延遲加載 但是必須在核心配置文件中設置全局配置信息: lazyLoadingEnabled:延遲加載的全局開關。當開啟時,所有關聯對象都會延遲加載 aggressiveLazyLoading:當開啟時,任何方法的調用都會加載該對象的所有屬性。否則,每個屬性會按需加載 此時就可以實現按需加載,獲取的數據是什么,就只會執行相應的sql。此時可通過association和collection中的fetchType屬性設置當前的分步查詢是否使用延遲加載, fetchType="lazy(延遲加載)|eager(立即加載)"9、動態SQL?
Mybatis框架的動態SQL技術是一種根據特定條件動態拼裝SQL語句的功能,它存在的意義是為了解決拼接SQL語句字符串時的痛點問題。
?9.1、if
if:通過test屬性中的表達式判斷標簽中的內容是否有效(是否會拼到sql中)
<!--List<Emp> getEmpByCondition(Emp emp);--><select id="getEmpByCondition" resultType="com.atguigu.mybatis.pojo.Emp">select * from t_emp where 1=1<if test="empName != null and empName != ''">and emp_name = #{empName}</if><if test="age != null and age != ''">and age = #{age}</if><if test="gender != null and gender != ''">and gender = #{gender}</if></select>?9.2、where
where和if結合使用:
????a.若where標簽中有條件成立,會自動生成where關鍵字
????b.會自動將where標簽中內容前多余的and去掉,但是其中內容后多余的and無法去掉
????c.若where中沒有任何一個條件成立,則where沒有任何功能
?9.3、trim
trim:
prefix、suffix:在標簽中內容前面或后面添加指定內容
prefixOverrides、suffixOverrides:在標簽中內容前面或后面去掉指定內容
?9.4、choose、when、otherwise
相當于java中的if...else if...else
when至少設置一個,otherwise最多設置一個
?9.5、foreach
foreach:
collection:設置要循環的數組或集合
item:用員工字符串標識數組或集合中的每一個數據
separator:設置每次循環的數據之間的分隔符
open:循環的所有內容以什么開始
close:循環的所有內容以什么結束
9.6、SQL片段
SQL片段:可以記錄一段sql,在需要用的地方使用include標簽進行引用 <sql id="empColumns">emp_id,emp_name,age,gender,dept_id</sql><!-- select * from t_emp-->select <include refid="empColumns"></include> from t_emp?10、MyBatis的緩存
10.1、MyBatis的一級緩存
?MyBatis的一級緩存是SqlSession級別,即通過同一個SqlSession查詢的數據會被緩存
?再次使用同一個SqlSession查詢同一條數據,會從緩存中獲取
?使一級緩存失效的四種情況:
?1) 不同的SqlSession對應不同的一級緩存
?2) 同一個SqlSession但是查詢條件不同
?3) 同一個SqlSession兩次查詢期間執行了任何一次增刪改操作
?4) 同一個SqlSession兩次查詢期間手動清空了緩存?
10.2、MyBatis的二級緩存
MyBatis的二級緩存是SqlSessionFactory級別的,即通過同一個SqlSessionFactory所獲取的SqlSession對象
查詢的數據會被緩存,在通過同一個SqlSessionFactory所獲取的SqlSession查詢相同的數據會從緩存中獲取
MyBatis二級緩存開啟的條件:
a>在核心配置文件中,設置全局配置屬性cacheEnabled="true",默認為true,不需要設置
b>在映射文件中設置標簽<cache/>
c>二級緩存必須在SqlSession關閉或提交之后有效
d>查詢的數據所轉換的實體類類型必須實現序列化的接口
使二級緩存失效的情況:
兩次查詢之間執行了任意的增刪改,會使一級和二級緩存同時失效
?10.3、二級緩存的相關配置(了解)
在mapper配置文件中添加的cache標簽可以設置一些屬性:
①eviction屬性:緩存回收策略,默認的是?LRU。
LRU(Least Recently Used)?– 最近最少使用的:移除最長時間不被使用的對象。
FIFO(First in First out)?– 先進先出:按對象進入緩存的順序來移除它們。
SOFT – 軟引用:移除基于垃圾回收器狀態和軟引用規則的對象。
WEAK – 弱引用:更積極地移除基于垃圾收集器狀態和弱引用規則的對象。
②flushInterval屬性:刷新間隔,單位毫秒
默認情況是不設置,也就是沒有刷新間隔,緩存僅僅調用語句時刷新
③size屬性:引用數目,正整數
代表緩存最多可以存儲多少個對象,太大容易導致內存溢出
④readOnly屬性:只讀,?true/false
true:只讀緩存;會給所有調用者返回緩存對象的相同實例。因此這些對象不能被修改。這提供了很重 要的性能優勢。
false:讀寫緩存;會返回緩存對象的拷貝(通過序列化)。這會慢一些,但是安全,因此默認是false。
10.4、MyBatis緩存查詢的順序
?先查詢二級緩存,因為二級緩存中可能會有其他程序已經查出來的數據,可以拿來直接使用。
如果二級緩存沒有命中,再查詢一級緩存
如果一級緩存也沒有命中,則查詢數據庫
SqlSession關閉之后,一級緩存中的數據會寫入二級緩存
?10.5、整合第三方緩存EHCache
10.5.1、添加依賴 <!-- Mybatis EHCache整合包 --> <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.2.1</version> </dependency> <!-- slf4j日志門面的一個具體實現 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> 10.5.2、各jar包功能10.5.3、創建EHCache的配置文件ehcache.xml
<?xml version="1.0" encoding="utf-8" ?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"><!-- 磁盤保存路徑 --><diskStore path="D:\atguigu\ehcache"/><defaultCachemaxElementsInMemory="1000"maxElementsOnDisk="10000000"eternal="false"overflowToDisk="true"timeToIdleSeconds="120"timeToLiveSeconds="120"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"></defaultCache> </ehcache> 10.5.4、設置二級緩存的類型 <cache type="org.mybatis.caches.ehcache.EhcacheCache"/> 10.5.5、加入logback日志 存在SLF4J時,作為簡易日志的log4j將失效,此時我們需要借助SLF4J的具體實現logback來打印日志。 創建logback的配置文件logback.xml <?xml version="1.0" encoding="UTF-8"?> <configuration debug="true"><!-- 指定日志輸出的位置 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><!-- 日志輸出的格式 --><!-- 按照順序分別是: 時間、日志級別、線程名稱、打印日志的類、日志主體內容、換行--><pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger][%msg]%n</pattern></encoder></appender><!-- 設置全局日志級別。日志級別按順序分別是: DEBUG、INFO、WARN、ERROR --><!-- 指定任何一個日志級別都只打印當前級別和后面級別的日志。 --><root level="DEBUG"><!-- 指定打印日志的appender,這里通過“STDOUT”引用了前面配置的appender --><appender-ref ref="STDOUT" /></root><!-- 根據特殊需求指定局部日志級別 --><logger name="com.atguigu.mybatis.mapper" level="DEBUG"/> </configuration>?10.5.6、EHCache配置文件說明
?11、MyBatis的逆向工程
正向工程:先創建Java實體類,由框架負責根據實體類生成數據庫表。 Hibernate是支持正向工程的。 逆向工程:先創建數據庫表,由框架負責根據數據庫表,反向生成如下資源:
- Java實體類
- Mapper接口
- Mapper映射文件
?11.1、創建逆向工程的步驟
①添加依賴和插件 <!-- 依賴MyBatis核心包 --><dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency><!-- junit測試 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- log4j日志 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency></dependencies><!-- 控制Maven在構建過程中相關配置 --><build><!-- 構建過程中用到的插件 --><plugins><!-- 具體插件,逆向工程的操作是以構建過程中插件形式出現的 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.0</version><!-- 插件的依賴 --><dependencies><!-- 逆向工程的核心依賴 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.2</version></dependency><!-- MySQL驅動 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency></dependencies></plugin></plugins></build> ②創建MyBatis的核心配置文件 ③創建逆向工程的配置文件 文件名必須是:generatorConfig.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration><!--targetRuntime: 執行生成的逆向工程的版本MyBatis3Simple: 生成基本的CRUD(清新簡潔版)MyBatis3: 生成帶條件的CRUD(奢華尊享版)--><context id="DB2Tables" targetRuntime="MyBatis3"><!-- 數據庫的連接信息 --><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC"userId="root"password="XXXX"><property name="nullCatalogMeansCurrent" value="true"/></jdbcConnection><!-- javaBean的生成策略--><javaModelGenerator targetPackage="com.atguigu.mybatis.pojo"targetProject=".\src\main\java"><property name="enableSubPackages" value="true" /><property name="trimStrings" value="true" /></javaModelGenerator><!-- SQL映射文件的生成策略 --><sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper"targetProject=".\src\main\resources"><property name="enableSubPackages" value="true" /></sqlMapGenerator><!-- Mapper接口的生成策略 --><javaClientGenerator type="XMLMAPPER"targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\java"><property name="enableSubPackages" value="true" /></javaClientGenerator><!-- 逆向分析的表 --><!-- tableName設置為*號,可以對應所有表,此時不寫domainObjectName --><!-- domainObjectName屬性指定生成出來的實體類的類名 --><table tableName="t_emp" domainObjectName="Emp"/><table tableName="t_dept" domainObjectName="Dept"/></context> </generatorConfiguration> ④執行MBG插件的generate目標 ⑤效果?11.2、QBC查詢
@Testpublic void testMBG(){SqlSession sqlSession = SqlSessionUtil.getSqlSession();EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);//根據id查詢數據 // Emp emp = mapper.selectByPrimaryKey(1); // System.out.println(emp);//查詢所有數據 // List<Emp> list = mapper.selectByExample(null); // list.forEach(System.out::println);//根據條件查詢數據 // EmpExample example = new EmpExample(); // example.createCriteria().andEmpNameEqualTo("張三").andAgeGreaterThanOrEqualTo(20); // example.or().andGenderEqualTo("男"); // List<Emp> list = mapper.selectByExample(example); // list.forEach(System.out::println);Emp emp = new Emp(1,"小黑",null,"女");//測試普通修改功能 // mapper.updateByPrimaryKey(emp);//測試選擇性修改mapper.updateByPrimaryKeySelective(emp);}使用逆行工程產生的問題
①idea中逆向工程生成文件,出現很多重復文件
②解決重復文件
在逆向工程文件里的數據庫連接的信息jdbcConnection標簽中加入:
<property name="nullCatalogMeansCurrent" value="true"/>?12、分頁插件
?limit index,pageSize
pageSize:每頁顯示的條數
pageNum:當前頁的頁碼
index:當前頁的起始索引,index=(pageNum-1)*pageSize
count:總記錄數
totalPage:總頁數
totalPage = count / pageSize;
if(count % pageSize != 0){
totalPage += 1;
}
pageSize=4,pageNum=1,index=0 limit 0,4
pageSize=4,pageNum=3,index=8 limit 8,4
pageSize=4,pageNum=6,index=20 limit 8,4
首頁 上一頁 2 3 4 5 6 下一頁 末頁
12.1、分頁插件的使用步驟
①添加依賴
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.2.0</version></dependency> ②配置分頁插件 在MyBatis的核心配置文件中配置插件 <plugins><!--設置分頁插件--><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin></plugins>12.2、分頁插件的使用
@Testpublic void testPage(){SqlSession sqlSession = SqlSessionUtil.getSqlSession();EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);//查詢功能之前開啟分頁功能Page<Object> page = PageHelper.startPage(5, 4);List<Emp> list = mapper.selectByExample(null);//查詢功能之后可以獲取分頁相關的所有數據PageInfo<Emp> pageInfo = new PageInfo<>(list,5);list.forEach(System.out::println);System.out.println(pageInfo);} a>在查詢功能之前使用PageHelper.startPage(int pageNum, int pageSize)開啟分頁功能 pageNum:當前頁的頁碼 pageSize:每頁顯示的條數?b>在查詢獲取list集合之后,使用PageInfo<T> pageInfo = new PageInfo<>(List<T> list, int navigatePages)獲取分頁相關數據
list:分頁之后的數據 navigatePages:導航分頁的頁碼數?c>分頁相關數據
PageInfo{ pageNum=8, pageSize=4, size=2, startRow=29, endRow=30, total=30, pages=8, list=Page{count=true, pageNum=8, pageSize=4, startRow=28, endRow=32, total=30, pages=8, reasonable=false, pageSizeZero=false}, prePage=7, nextPage=0, isFirstPage=false, isLastPage=true, hasPreviousPage=true, hasNextPage=false, navigatePages=5, navigateFirstPage4, navigateLastPage8, navigatepageNums=[4, 5, 6, 7, 8] } pageNum:當前頁的頁碼 pageSize:每頁顯示的條數 size:當前頁顯示的真實條數 total:總記錄數 pages:總頁數 prePage:上一頁的頁碼 nextPage:下一頁的頁碼 isFirstPage/isLastPage:是否為第一頁/最后一頁 hasPreviousPage/hasNextPage:是否存在上一頁/下一頁 navigatePages:導航分頁的頁碼數 navigatepageNums:導航分頁的頁碼,[1,2,3,4,5]?二、Spring
1、Spring簡介
1.1、Spring概述
總結
以上是生活随笔為你收集整理的SSM框架整合(参考尚硅谷视频和文档的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: comsol初学经验分享
- 下一篇: wget下载卡住