藁城專業(yè)網(wǎng)站建設(shè)百度商城購物
01-mybatis傳統(tǒng)dao開發(fā)模式
-
概述
- mybatis有兩種使用模式: ①傳統(tǒng)dao開發(fā)模式, ②dao接口代理開發(fā)模式
-
①傳統(tǒng)dao開發(fā)模式
- dao接口 + dao實(shí)現(xiàn)子類 + mapper映射文件
- dao實(shí)現(xiàn)子類來決定了
dao接口的方法
和mapper映射文件的statement
的關(guān)系
-
代碼實(shí)現(xiàn)
public class StudentDaoImpl implements StudentDao {private SqlSessionFactory sqlSessionFactory;public StudentDaoImpl(SqlSessionFactory sqlSessionFactory) {//外界(Spring容器)傳遞過來的是一個(gè)單例對象即可.this.sqlSessionFactory = sqlSessionFactory;}@Overridepublic Student getById(Integer id) throws Exception {//1,獲取SqlSessionFactory對象//1.1, 獲取mybatis核心配置文件的路徑//String resource = "mybatis-config.xml";//1.2, 獲取mybatis核心配置文件對應(yīng)的輸入流//InputStream inputStream = Resources.getResourceAsStream(resource);//1.3, 編譯獲取SqlSessionFactory工廠對象//SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2, 獲取SqlSession會話對象SqlSession sqlSession = sqlSessionFactory.openSession();//3, 使用SqlSession會話對象執(zhí)行已配置的statementStudent student = sqlSession.selectOne("getById", id);//4, 操作完畢, 關(guān)閉會話sqlSession.close();return student;}@Overridepublic int insert(Student student) throws Exception {//1, 獲取SqlSessionFactory工廠對象//SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));//2, 獲取SqlSession會話對象SqlSession sqlSession = sqlSessionFactory.openSession();//3, 執(zhí)行已配置的statement,并返回影響的行數(shù)int insert = sqlSession.insert("insert", student);//4, 手動(dòng)提交sqlSession.commit();//5, 釋放資源sqlSession.close();return insert;}@Overridepublic int delete(Integer id) throws Exception {//1, 獲取SqlSessionFactory工廠對象//SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));//2, 獲取SqlSession會話對象SqlSession sqlSession = sqlSessionFactory.openSession();//3, 執(zhí)行statementint delete = sqlSession.delete("delete", id);//4, 手動(dòng)提交sqlSession.commit();//5, 釋放資源sqlSession.close();return delete;}@Overridepublic int update(Student student) throws Exception {//1, 獲取SqlSessionFactory工廠對象//SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));//2, 獲取SqlSession會話對象SqlSession sqlSession = sqlSessionFactory.openSession();//3, 執(zhí)行statementint update = sqlSession.update("update", student);//4, 手動(dòng)提交sqlSession.commit();//5, 釋放資源sqlSession.close();return update;} }
public class StudentDaoTest {private SqlSessionFactory sqlSessionFactory;@Before//在單元測試方法之前執(zhí)行public void init() throws IOException {sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));}@Testpublic void getById() throws Exception {StudentDao studentDao = new StudentDaoImpl(sqlSessionFactory);Student student = studentDao.getById(8);System.out.println("student = " + student);}@Testpublic void insert() throws Exception {StudentDao studentDao = new StudentDaoImpl(sqlSessionFactory);int insert = studentDao.insert(new Student(null,"鵬鵬","男"));System.out.println("insert = " + insert);}@Testpublic void delete() throws Exception {StudentDao studentDao = new StudentDaoImpl(sqlSessionFactory);int delete = studentDao.delete(6);System.out.println("delete = " + delete);}@Testpublic void update() throws Exception {StudentDao studentDao = new StudentDaoImpl(sqlSessionFactory);int update = studentDao.update(new Student(8,"黃鄭","妖怪"));System.out.println("update = " + update);} }
-
存在的問題
dao實(shí)現(xiàn)子類
和mapper映射文件
之間存在高耦合.
02-mybatis接口代理開發(fā)模式
-
概述
- 由
dao接口
和mapper映射文件
組成, 此時(shí)由一套規(guī)則
來確定dao接口方法
和映射文件statement
的關(guān)系
- 由
-
一套規(guī)則
- ①dao接口和mapper映射文件必須在同一個(gè)目錄中
- 可以不放在同一個(gè)目錄, 只要保證能夠加載到即可, 建議放在同一個(gè)目錄
- ②dao接口和mapper映射文件必須名稱一樣
- 可以不一樣, 只要保證能夠加載到即可, 建議名稱一樣
- ③mapper映射文件的namespace必須等于dao接口的全限定類名
- 必須遵守
- ④statement的id必須等于dao接口的方法名稱
- 必須遵守
- ⑤statement的parameterType必須等于dao接口方法的形參類型
- 必須遵守
- ⑥statement的resultType必須等于dao接口方法的返回值類型
- 必須遵守
- ①dao接口和mapper映射文件必須在同一個(gè)目錄中
-
代碼實(shí)現(xiàn)
public interface StudentDao {Student getById(Integer id) throws Exception;int insert(Student student) throws Exception;int delete(Integer id) throws Exception;int update(Student student) throws Exception; }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""https://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.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mydb?useSSL=false"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><mappers><mapper resource="com/qh/dao/StudentDao.xml"/></mappers> </configuration>
public class StudentDaoTest {private SqlSessionFactory sqlSessionFactory;@Beforepublic void init() throws IOException {sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));}@Testpublic void getById() throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();//獲取dao接口代理對象StudentDao studentDao = sqlSession.getMapper(StudentDao.class);Student student = studentDao.getById(8);System.out.println("student = " + student);sqlSession.close();}@Testpublic void insert() throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();//獲取dao接口代理對象StudentDao studentDao = sqlSession.getMapper(StudentDao.class);int insert = studentDao.insert(new Student(null, "武帆", "男"));System.out.println("insert = " + insert);sqlSession.commit();sqlSession.close();}@Testpublic void delete() {}@Testpublic void update() {} }
03-lombok插件
-
開發(fā)步驟
-
①在idea安裝lombok插件
- 安裝完成重啟idea
-
②勾選Annotation Processors
-
③引入lombok依賴
-
④修改java實(shí)體類
- 使用lombok相關(guān)注解
-
-
①在idea安裝lombok插件
- [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-aUn7xueA-1676283014283)(null)]
-
②勾選Annotation Processors
- [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-gi5b9xxx-1676283012446)(null)]
-
③引入lombok依賴
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version> </dependency>
-
④修改java實(shí)體類
@NoArgsConstructor//生成無參構(gòu)造器 @RequiredArgsConstructor//生成有參構(gòu)造器 @AllArgsConstructor//生成全參構(gòu)造器 @Data public class Student {private Integer id;@NonNullprivate String name;@NonNullprivate String gender; }
04-核心配置文件解釋
-
核心配置文件
- [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-wet0mkl0-1676283012623)(null)]
- properties,
- settings
- cacheEnabled(緩存開關(guān)), lazyLoadingEnabled(懶加載開關(guān)), mapUnderscoreToCamelCase(駝峰標(biāo)識), logImpl(日志實(shí)現(xiàn))
- typeAliases
- plugins
- enviroments
- mappers
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""https://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- Mybatis核心配置文件中標(biāo)簽的順序: properties?,settings?,typeAliases?,typeHandlersobjectFactory?,objectWrapperFactory?,reflectorFactoryplugins?,environments?,databaseIdProvider?,mappers--><!-- 引入數(shù)據(jù)源文件properties --><properties resource="jdbc.properties"/><!-- 設(shè)置 --><settings><!-- 配置log4j日志文件 --><setting name="logImpl" value="LOG4J"/><!-- 忽略駝峰大小寫 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings><!-- 類型別名 --><typeAliases><!-- type:類型全類名alias:當(dāng)前類型的別名,可不寫,默認(rèn)為類名<typeAlias [alias="User"] type="com.qh.pojo.Users"/>!!!不推薦使用 typeAlias--><typeAlias alias="User" type="com.qh.pojo.Users"/><!-- 給包下所有的類分別起別名name:全限定類名!!!推薦使用--><package name="com.qh.pojo"/></typeAliases<!-- environments:配置多個(gè)連接數(shù)據(jù)庫的環(huán)境default:切換默認(rèn)數(shù)據(jù)庫環(huán)境的id--><environments default="development"><!-- environment:配置單個(gè)連接數(shù)據(jù)庫的環(huán)境id:配置連接數(shù)據(jù)庫環(huán)境的唯一標(biāo)識--><environment id="development"><!--transactionManager:設(shè)置事務(wù)管理的方式屬性:type:"JDBC|MANAGED"JDBC:表示當(dāng)前環(huán)境中執(zhí)行sql時(shí)使用JDBC中原生的事務(wù)管理方式,事務(wù)的提交或回滾需要手動(dòng)處理MANAGED:被管理,例如spring--><transactionManager type="JDBC"/><!--dataSource:配置數(shù)據(jù)源屬性:type:"POOLED|UNPOOLED|JNDI"POOLED:表示使用數(shù)據(jù)庫連接池緩存數(shù)據(jù)庫連接UNPOOLED:表示不使用數(shù)據(jù)庫連接池JNDI:表示使用上下文中的數(shù)據(jù)源--><dataSource type="POOLED"><!-- 設(shè)置連接數(shù)據(jù)庫的驅(qū)動(dòng) --><property name="driver" value="${jdbc.driver}"/><!-- 設(shè)置連接數(shù)據(jù)庫的鏈接地址 --><property name="url" value="${jdbc.url}"/><!-- 設(shè)置連接數(shù)據(jù)庫的用戶名 --><property name="username" value="${jdbc.username}"/><!-- 設(shè)置連接數(shù)據(jù)庫的密碼 --><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><!-- 引入映射文件 --><mappers><!-- 引入少量映射文件時(shí)使用,直接加載xml --><mapper resource="mappers/UserMapper.xml"/><!-- 引入多個(gè)映射文件時(shí)[接口代理模式使用] --><mapper class="com.qh.dao.UserDao"/><!-- 引入多個(gè)映射文件時(shí)[接口代理模式使用]!!!推薦使用 --><package name="com.qh.dao"/></mappers></configuration>
05-mybatis內(nèi)置的數(shù)據(jù)源技術(shù)
-
概述
-
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-KzUqPBMj-1676283013426)(null)]
-
PooledDataSouce參數(shù)值為: POOLED; UnpooledDataSource參數(shù)值為: UNPOOLED
-
06-enviroments標(biāo)簽
-
概述
- 用于配置mybatis的運(yùn)行環(huán)境(事務(wù), 數(shù)據(jù)源), 而且可以配置多個(gè)不同的運(yùn)行環(huán)境.
-
事務(wù)管理器(transactionManager)
- JDBC : 這個(gè)配置直接使用了 JDBC 的提交和回滾功能,它依賴從數(shù)據(jù)源獲得的連接來管理事務(wù)作用域。
- MANAGED: 這個(gè)配置幾乎沒做什么。它從不提交或回滾一個(gè)連接,而是讓容器來管理事務(wù)的整個(gè)生命周期(比如 JEE 應(yīng)用服務(wù)器的上下文)。
-
數(shù)據(jù)源(dataSource)
- UNPOOLED– 這個(gè)數(shù)據(jù)源的實(shí)現(xiàn)會每次請求時(shí)打開和關(guān)閉連接。
- POOLED– 這種數(shù)據(jù)源的實(shí)現(xiàn)利用“池”的概念將 JDBC 連接對象組織起來,避免了創(chuàng)建新的連接實(shí)例時(shí)所必需的初始化和認(rèn)證時(shí)間。
- JNDI – 這個(gè)數(shù)據(jù)源實(shí)現(xiàn)是為了能在如 EJB 或應(yīng)用服務(wù)器這類容器中使用,容器可以集中或在外部配置數(shù)據(jù)源,然后放置一個(gè) JNDI 上下文的數(shù)據(jù)源引用。
-
代碼實(shí)現(xiàn)
<!--default: 啟用指定運(yùn)行環(huán)境 --> <environments default="development"><environment id="development"><!--transactionManager:JDBC: 有合理的事務(wù)管理, 推薦MANAGED: 什么都沒做--><transactionManager type="JDBC"/><!--type: 啟用數(shù)據(jù)源你的類型JNDI: 使用jndi技術(shù)實(shí)現(xiàn)的數(shù)據(jù)源POOLED: 帶鏈接池的數(shù)據(jù)源, PooledDataSource, 推薦UNPOOLED: 不帶鏈接池的數(shù)據(jù)源, UnPooledDataSource--><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mydb?useSSL=false"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment><environment id="development2"><transactionManager type="JDBC"/><dataSource type="UNPOOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mydb?useSSL=false"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment> </environments>
-
總結(jié)
- mybatis內(nèi)置的數(shù)據(jù)源技術(shù)功能太過單一, 僅在學(xué)習(xí)mybatis框架時(shí)使用, 后續(xù)修改為第三方數(shù)據(jù)源技術(shù): DruidDataSource, C3P0, DBCP…
07-propertie標(biāo)簽
-
概述
- 用于聲明變量, 在mybatis中使用.
-
方式一
<properties><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="jdbdUrl" value="jdbc:mysql://localhost:3306/mydb?useSSL=false"/><property name="username" value="root"/><property name="password" value="root"/> </properties><!--default: 啟用指定運(yùn)行環(huán)境 --> <environments default="development"><environment id="development"><!--transactionManager:JDBC: 有合理的事務(wù)管理, 推薦MANAGED: 什么都沒做--><transactionManager type="JDBC"/><!--type: 啟用數(shù)據(jù)源你的類型JNDI: 使用jndi技術(shù)實(shí)現(xiàn)的數(shù)據(jù)源POOLED: 帶鏈接池的數(shù)據(jù)源, PooledDataSource, 推薦UNPOOLED: 不帶鏈接池的數(shù)據(jù)源, UnPooledDataSource--><dataSource type="POOLED"><property name="driver" value="${driverClassName}"/><property name="url" value="${jdbcUrl}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment><environment id="development2"><transactionManager type="JDBC"/><dataSource type="UNPOOLED"><property name="driver" value="${driverClassName}"/><property name="url" value="${jdbcUrl}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment> </environments>
-
方式二
<!--加載jdbc.properties文件--> <properties resource="jdbc.properties"></properties> <!--default: 啟用指定運(yùn)行環(huán)境 --> <environments default="development"><environment id="development"><!--transactionManager:JDBC: 有合理的事務(wù)管理, 推薦MANAGED: 什么都沒做--><transactionManager type="JDBC"/><!--type: 啟用數(shù)據(jù)源你的類型JNDI: 使用jndi技術(shù)實(shí)現(xiàn)的數(shù)據(jù)源POOLED: 帶鏈接池的數(shù)據(jù)源, PooledDataSource, 推薦UNPOOLED: 不帶鏈接池的數(shù)據(jù)源, UnPooledDataSource--><dataSource type="POOLED"><property name="driver" value="${driverClass}"/><property name="url" value="${jdbcUrl}"/><property name="username" value="${user}"/><property name="password" value="${password}"/></dataSource></environment><environment id="development2"><transactionManager type="JDBC"/><dataSource type="UNPOOLED"><property name="driver" value="${driverClass}"/><property name="url" value="${jdbcUrl}"/><property name="username" value="${user}"/><property name="password" value="${password}"/></dataSource></environment> </environments>
08-settings標(biāo)簽之log4j
-
概述
- mybatis程序運(yùn)行時(shí)在控制臺打印輸出
sql語句
,輸入?yún)?shù)
,結(jié)果數(shù)量
等等
- mybatis程序運(yùn)行時(shí)在控制臺打印輸出
-
開發(fā)步驟
- ①引入依賴
- log4j
- ②修改mybatis-config.xml
- 配置settings標(biāo)簽中的logImpl參數(shù)
- ③編寫log4j.xml
- ④代碼測試
- ①引入依賴
-
①引入依賴
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version> </dependency>
-
②修改mybatis-config.xml
<settings><!--指定日志框架--><setting name="logImpl" value="LOG4J"/> </settings>
-
③編寫log4j.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"><!--規(guī)定打印到console中的日志的格式--><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>
09-typeAliases標(biāo)簽
-
概述
- 設(shè)置別名
-
方式一: 挨個(gè)設(shè)置每個(gè)類的別名
<typeAlias type="com.qh.pojo.Student" alias="Student"></typeAlias>
-
方式二: 根據(jù)包給每個(gè)類自動(dòng)取別名, 默認(rèn)為類名
<typeAliases><package name="com.qh.pojo"/> </typeAliases>
10-mappers標(biāo)簽
-
概述
- 用于加載mapper映射文件.
-
方式一: 直接加載mapper映射文件, 傳統(tǒng)dao模式可以使用, 接口代理模式也可以使用, 不能使用通配符
*
<mappers><mapper resource="com/qh/dao/StudentDao.xml"/> </mappers>
-
方式二: 先加載dao接口, 再加載mapper映射文件, 接口代理模式可以使用, 不能使用通配符
*
<mappers><mapper class="com.qh.dao.StudentDao"></mapper> </mappers>
-
方式三: 先加載所有dao接口, 再加載所有mapper映射文件, 接口代理模式可以使用
<mappers><package name="com.qh.dao"/> </mappers>
11-核心配置文件之plugins分頁插件
-
概述
- 插件pagehelper封裝了復(fù)雜的分頁操作.
-
工作流程
- [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-ne0DJdXq-1676283014477)(null)]****
-
開發(fā)步驟
- ①引入依賴
- pagehelper
- ②修改service接口及其實(shí)現(xiàn)
- ③修改mybatis-config.xml, 配置PageInterceptor分頁攔截器
- ①引入依賴
-
①引入依賴
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.3.2</version> </dependency>
-
②修改service接口及其實(shí)現(xiàn)
public class StudentServiceImpl implements StudentService {@Overridepublic List<Student> findAll() throws Exception {SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));SqlSession sqlSession = sqlSessionFactory.openSession();StudentDao studentDao = sqlSession.getMapper(StudentDao.class);List<Student> studentList = studentDao.findAll();sqlSession.close();return studentList;}@Overridepublic PageInfo<Student> findByPage(Integer currentPage, Integer pageSize) throws Exception {//開始分頁查詢PageHelper.startPage(currentPage, pageSize);//執(zhí)行分頁查詢(查詢所有 -> 分頁查詢)List<Student> studentList = findAll();return new PageInfo<>(studentList);} }
-
③修改mybatis-config.xml, 配置PageInterceptor分頁攔截器
<plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"><!--合理化--><property name="reasonable" value="true"/><!--方言--><property name="helperDialect" value="mysql"/></plugin> </plugins>
-
④代碼測試
@Test public void findByPage() throws Exception {StudentService studentService = new StudentServiceImpl();PageInfo<Student> pageInfo = studentService.findByPage(4, 3);System.out.println("當(dāng)前頁數(shù) = " + pageInfo.getPageNum());System.out.println("每頁記錄數(shù) = " + pageInfo.getPageSize());System.out.println("當(dāng)前頁實(shí)際記錄數(shù) = " + pageInfo.getSize());System.out.println("上一頁 = " + pageInfo.getPrePage());System.out.println("當(dāng)前頁數(shù)據(jù) = " + pageInfo.getList());System.out.println("下一頁 = " + pageInfo.getNextPage());System.out.println("總記錄數(shù) = " + pageInfo.getTotal());System.out.println("總頁數(shù) = " + pageInfo.getPages());System.out.println("是否第一頁 = " + pageInfo.isIsFirstPage());System.out.println("是否最后一頁 = " + pageInfo.isIsLastPage());System.out.println("頁碼 = " + Arrays.toString(pageInfo.getNavigatepageNums()));}
12-給SQL語句傳參
-
概述
- 在mybatis中,使用兩種占位符
#{}
和${}
給sql語句中的?
賦值.
- 在mybatis中,使用兩種占位符
-
需求
- 根據(jù)姓名模糊查詢
-
代碼實(shí)現(xiàn)
List<Teacher> findLikeName1(String name) throws Exception;List<Teacher> findLikeName2(String name) throws Exception;
<select id="findLikeName1" parameterType="String" resultType="Teacher">select * from t_teacher where name like "%"#{name}"%" </select><select id="findLikeName2" parameterType="String" resultType="Teacher">select * from t_teacher where name like "%${name}%" </select>
-
#{} VS ${}
- #{}:
- 會轉(zhuǎn)換為?占位符, 傳入的數(shù)據(jù)可以有類型
- 防止SQL注入漏洞
- 不可以傳入表名
- ${}
- 不會轉(zhuǎn)換為?占位符, 傳入的數(shù)據(jù)直接可以理解為關(guān)鍵字
- 不能防止SQL注入漏洞
- 可以傳入表名
- #{}:
13-輸入映射概述
- 概述
- 輸入映射,是在映射文件中通過parameterType指定輸入?yún)?shù)的類型。類型可以是①簡單類型、②復(fù)雜類型
- ①簡單類型: 只有一個(gè)值
- 基本數(shù)據(jù)類型: 四類八種
- 包裝類
- String
- ②復(fù)雜類型: 有多個(gè)值
- 對象
- 集合(list, set, map)
- 數(shù)組
14-輸入映射之簡單類型
-
需求
- 根據(jù)id查詢用戶
-
代碼實(shí)現(xiàn)
<select id="getById1" parameterType="Integer" resultType="Teacher">select * from t_teacher where id = #{id} </select><!--#{}中的名稱從語法上可以隨意寫, 但是最好和形參名稱一樣 --> <select id="getById2" parameterType="Integer" resultType="Teacher">select * from t_teacher where id = #{a} </select><!--parameterType="Integer"可以省略--> <select id="getById3" resultType="Teacher">select * from t_teacher where id = #{a} </select>
-
注意事項(xiàng)
- ①占位符
#{名稱}
中的名稱從語法上可以隨意寫, 但是最好和接口方法的形參名稱一樣; - ②
pamaterType
可以省略.
- ①占位符
15-輸入映射之零散簡單類型
-
概述
- 零散簡單類型: 在dao接口方法上有多個(gè)分開的簡單類型的形參.
-
需求
- 根據(jù)賬戶和密碼查詢用戶記錄
-
代碼實(shí)現(xiàn)
Teacher getByNameAndPwd1(String name , String password) throws Exception; Teacher getByNameAndPwd2(String name , String password) throws Exception;Teacher getByNameAndPwd3(@Param("name") String name ,@Param("password") String password) throws Exception;
<!--使用內(nèi)置名稱arg0,arg1--> <select id="getByNameAndPwd1" resultType="Teacher">select * from t_teacher where name = #{arg0} and password = #{arg1} </select><!--使用內(nèi)置名稱param1,param2--> <select id="getByNameAndPwd2" resultType="Teacher">select * from t_teacher where name = #{param1} and password = #{param2} </select><!--使用自定義名稱--> <select id="getByNameAndPwd3" resultType="Teacher">select * from t_teacher where name = #{name} and password = #{password} </select>
16-輸入映射之實(shí)體類型
-
概述
- Mybatis會根據(jù)#{}中傳入的數(shù)據(jù),加工成getXxx()方法,通過反射在實(shí)體類對象中調(diào)用這個(gè)方法,從 而獲取到對應(yīng)的數(shù)據(jù)。填充到#{}這個(gè)位置。
-
需求
- 根據(jù)賬戶和密碼查詢用戶記錄
-
工作流程
- [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-eUle6N7v-1676283013075)(null)]
-
代碼實(shí)現(xiàn)
Teacher getByInstance1(Teacher teacher) throws Exception; Teacher getByInstance2(Teacher teacher) throws Exception;
<select id="getByInstance1" parameterType="Teacher" resultType="Teacher">select * from t_teacher where name = #{name} and password = #{password} </select><!--省略parameterType="Teacher"--> <select id="getByInstance2" resultType="Teacher">select * from t_teacher where name = #{name} and password = #{password} </select>
-
注意事項(xiàng)
- ①
parameterType
可以省略; - ②占位符名稱應(yīng)該和
get方法名稱
保持一致!!! - ③如果有
get方法
直接調(diào)用, 如果沒有get方法
直接暴力反射操作成員變量. - ④按照規(guī)則, 占位符名稱應(yīng)該和實(shí)體類的屬性名稱一樣.
- ①
-
總結(jié)
- 輸入映射中使用反射動(dòng)態(tài)執(zhí)行
get方法
!!!
- 輸入映射中使用反射動(dòng)態(tài)執(zhí)行
17-輸入映射之Map
-
概述
- 如果要輸入多個(gè)參數(shù)值, 如果使用零散簡單類型比較麻煩, 又沒有對應(yīng)的實(shí)體類, 這個(gè)時(shí)候就可以使用Map.
-
需求
- 根據(jù)賬戶和密碼查詢用戶記錄
-
代碼實(shí)現(xiàn)
Teacher getByMap1(Map map) throws Exception; Teacher getByMap2(Map map) throws Exception;
<select id="getByMap1" parameterType="Map" resultType="Teacher">select * from t_teacher where name = #{name} and password = #{password} </select><select id="getByMap2" resultType="Teacher">select * from t_teacher where name = #{name} and password = #{password} </select>
-
注意事項(xiàng)
- ①
parameterType
可以省略; - ②#{}占位符名稱應(yīng)該和map的鍵名稱一樣.
- ①
18-輸出映射概述
- 概述
- 輸出映射,是在映射文件中通過resultType指定輸出結(jié)果的類型。類型可以是簡單類型、復(fù)雜類型
- ①簡單類型: 只有一個(gè)值
- 基本數(shù)據(jù)類型: 四類八種
- 包裝類
- String
- ②復(fù)雜類型: 有多個(gè)值
- 對象
- 集合(list, set, map)
- 數(shù)組
19-輸出映射之簡單類型
-
需求
- 統(tǒng)計(jì)總記錄數(shù)
-
代碼實(shí)現(xiàn)
Integer getTotalSize() throws Exception;
<select id="getTotalSize" resultType="Integer">select count(*) from t_customer </select>
20-輸出映射之實(shí)體類型
-
需求
- 根據(jù)姓名查詢記錄
-
工作流程
- [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-TPFwu9qI-1676283013204)(null)]
- Mybatis會根據(jù)
結(jié)果集中的字段名稱
,加工成setXxx()方法,通過反射在實(shí)體類對象中調(diào)用這個(gè)方法,從 而將結(jié)果集中的數(shù)據(jù)賦值到實(shí)體類對象中。
-
代碼實(shí)現(xiàn)
Customer getByName(String name) throws Exception;
<select id="getByName" resultType="Customer">select * from t_customer where name = #{name} </select>
-
注意事項(xiàng)
- ①結(jié)果集字段名稱和
setXxx方法名稱
一致!!! - ②如果沒有對應(yīng)的set方法, 直接暴力反射賦值給成員變量.
- ①結(jié)果集字段名稱和
select查詢無需添加
parameterType
,只需要resultType
即可增刪改需要添加
parameterType
,一個(gè)參數(shù)隨便填寫占位符名稱,resultType=具體數(shù)據(jù)類型
多個(gè)用
@param
指定,@param(值)
中的值與sql
語句中占位符的值應(yīng)相同, resultType=全限定類名
21-輸出映射之Map
-
概述
- 適用于SQL查詢返回的各個(gè)字段綜合起來并不和任何一個(gè)現(xiàn)有的實(shí)體類對應(yīng),沒法封裝到實(shí)體類對象 中。能夠封裝成實(shí)體類類型的,就不使用Map類型。
- 字段名是map的鍵,字段值是map的值
-
需求
- 根據(jù)id查詢記錄, 并返回Map
-
代碼實(shí)現(xiàn)
Map getByIdWithMap(Integer id) throws Exception;
<select id="getByIdWithMap" resultType="Map">select * from t_user where userId = #{userId} </select>
22-輸出映射之List
-
需求
- 查詢所有記錄
-
代碼實(shí)現(xiàn)
List<User> findAll() throws Exception;
<select id="findAll" resultType="User">select * from t_user </select>
23-settings標(biāo)簽之mapUnderscoreToCamelCase
-
概述
- mapUnderscoreToCamelCase: map underscore to camelcase, 將下劃線映射給駝峰.
- 下劃線: 在數(shù)據(jù)庫中, 字段名稱規(guī)范是a_b
- 駝峰: 在實(shí)體類中, 屬性名稱規(guī)范是aB
- 按照默認(rèn)的輸出映射規(guī)則, 要求字段名稱和
set方法名稱
一致, 所以無法直接輸出映射成功!!!
-
解決方案
- ①修改屬性名稱或字段名稱
- ②查詢記錄操作中給結(jié)果集中的字段名稱取別名
- ③自動(dòng)將
下劃線
輸出映射給駝峰標(biāo)識
.
-
②查詢記錄操作中給結(jié)果集中的字段名稱取別名
User2 getById1(Integer id) throws Exception;
<select id="getById1" resultType="User2">select user_id userId , user_name userName ,user_pwd userPwd from t_user2 where user_id = #{userId} </select>
-
③自動(dòng)將
下劃線
輸出映射給駝峰標(biāo)識
.<settings><!--日志實(shí)現(xiàn)--><setting name="logImpl" value="LOG4J"/><!--自動(dòng)駝峰標(biāo)識--><setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
User2 getById2(Integer id) throws Exception;
<select id="getById2" resultType="User2">select * from t_user2 where user_id = #{userId} </select>
24-輸出映射之ResultMap
-
概述
- ResultMap: 自定義輸出映射規(guī)則, 自定義將指定的字段名稱映射給指定的屬性名稱.
-
代碼實(shí)現(xiàn)
User2 getByName(String name) throws Exception;
<select id="getByName" resultMap="User2Map">select * from t_user2 where user_name = #{userName} </select>
25-insert實(shí)現(xiàn)主鍵返回
-
概述
- insert記錄,并獲取已經(jīng)添加的記錄的id。
-
解決方案
- ①使用
Statement.RETURN_GENERATED_KEYS
- ②使用
select last_insert_id()
- ①使用
-
①使用
Statement.RETURN_GENERATED_KEYS
int insert1(User user) throws Exception;
<insert id="insert1" parameterType="User" useGeneratedKeys="true" keyColumn="userId" keyProperty="userId" >insert into t_user values(null,#{userName},#{userPwd},#{money}) </insert>
-
②使用
select last_insert_id()
int insert2(User user) throws Exception;
<insert id="insert2" >insert into t_user values(null,#{userName},#{userPwd},#{money})<!--keyColumn: 字段名稱keyProperty: 屬性名稱resultType: 類型order: AFTER(主鍵在添加記錄之后生成)--><selectKey keyColumn="userId" keyProperty="userId" resultType="Integer" order="AFTER">select last_insert_id()</selectKey> </insert>
26-動(dòng)態(tài)sql之sql片段
-
概述
- sql片段: 將重復(fù)的sql語句獨(dú)立抽取出來進(jìn)行單獨(dú)維護(hù).
-
代碼實(shí)現(xiàn)
<sql id="query_of_columns">name, password </sql><select id="getById" resultType="Teacher">select<include refid="query_of_columns"></include>from t_teacher where id = #{id} </select><select id="getByName" resultType="Teacher">select<include refid="query_of_columns"></include>from t_teacher where name = #{name} </select>
27-動(dòng)態(tài)sql之if標(biāo)簽
-
概述
- 根據(jù)條件動(dòng)態(tài)生成指定的sql語句.
-
需求
- 如果賬戶和密碼都沒有就查詢所有用戶記錄;
- 如果只有賬戶,就根據(jù)賬戶查詢用戶記錄;
- 如果只有密碼,就根據(jù)密碼查詢用戶記錄;
- 如果賬戶和密碼都有,就根據(jù)賬戶和密碼查詢用戶記錄。
-
代碼實(shí)現(xiàn)
<select id="getByIf1" resultType="Teacher">select * from t_teacher where name = #{name} and password = #{password} </select><select id="getByIf2" resultType="Teacher">select * from t_teacher where<if test="name!=null and name!=''">name = #{name}</if><if test="password!=null and password!=''">and password = #{password}</if> </select><select id="getByIf3" resultType="Teacher">select * from t_teacher where 1 = 1<if test="name!=null and name!=''">and name = #{name}</if><if test="password!=null and password!=''">and password = #{password}</if> </select>
-
存在的問題
where 1 = 1
不夠優(yōu)雅~~~
-
總結(jié)
- 沒有條件生成多
where關(guān)鍵字
; 只有password成立多and關(guān)鍵字
- 沒有條件生成多
28-動(dòng)態(tài)sql之where標(biāo)簽
-
概述
- 根據(jù)條件動(dòng)態(tài)生成
where關(guān)鍵字
, 去掉前面多余的and/or關(guān)鍵字
- 根據(jù)條件動(dòng)態(tài)生成
-
代碼實(shí)現(xiàn)
List<Teacher> getByWhere(@Param("name") String name,@Param("password") String password) throws Exception;
<select id="getByWhere" resultType="Teacher">select * from t_teacher<where><if test="name!=null and name!=''">and name = #{name}</if><if test="password!=null and password!=''">and password = #{password}</if></where> </select>
29-動(dòng)態(tài)sql之trim標(biāo)簽
-
概述
- 可以通過prefix、prefixOverrides、suffix、suffixOverrides設(shè)置sql語句的前綴和后綴
-
參數(shù)說明
- [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-KoxWj0xf-1676283012987)(null)]
-
需求
- 使用
trim標(biāo)簽
達(dá)到where標(biāo)簽
的效果,- where標(biāo)簽: 如果條件成立生成where關(guān)鍵字, 去除前面多余的
and|or
- where標(biāo)簽: 如果條件成立生成where關(guān)鍵字, 去除前面多余的
- 使用
-
代碼實(shí)現(xiàn)
List<User> getByTrim(@Param("userName") String userName,@Param("userPwd") String userPwd ) throws Exception;
<select id="getByTrim" resultType="User">select * from t_user<trim prefix="where" prefixOverrides="and|or"><if test="userName!=null and userName!=''">and user_name = #{userName}</if><if test="userPwd!=null and userPwd!=''">and user_pwd = #{userPwd}</if></trim> </select>
30-動(dòng)態(tài)sql之set標(biāo)簽
-
概述
- 根據(jù)條件動(dòng)態(tài)生成
set關(guān)鍵字
, 去掉后面多余的逗號
- 根據(jù)條件動(dòng)態(tài)生成
-
需求
- 根據(jù)id修改用戶信息
-
代碼實(shí)現(xiàn)
int update1(Teacher teacher) throws Exception; int update2(Teacher teacher) throws Exception; int update3(Teacher teacher) throws Exception;
<update id="update1" parameterType="Teacher">update t_teacher set name = #{name} , password = #{password} where id = #{id} </update><update id="update2" parameterType="Teacher">update t_teacher set<if test="name!=null and name!=''">name = #{name} ,</if><if test="password!=null and password!=''">password = #{password}</if><where>id = #{id}</where> </update><update id="update3" parameterType="Teacher">update t_teacher<set><if test="name!=null and name!=''">name = #{name} ,</if><if test="password!=null and password!=''">password = #{password} ,</if></set><where>id = #{id}</where> </update>
31-動(dòng)態(tài)sql之choose標(biāo)簽
-
概述
- 在多個(gè)分支條件中,僅執(zhí)行一個(gè),而后面的條件匹配都會被忽略
-
代碼實(shí)現(xiàn)
List<Teacher> getByChoose(@Param("name") String name,@Param("password") String password) throws Exception;
<select id="getByChoose" resultType="Teacher">select * from t_teacher<where><choose><when test="name!=null and name!=''">name = #{name}</when><when test="password!=null and password!=''">password = #{password}</when><otherwise>1=1</otherwise></choose></where> </select>
32-動(dòng)態(tài)sql之foreach標(biāo)簽
-
概述
- foreach標(biāo)簽主要用于批量操作.
-
語法
<!--collection: 數(shù)組=array, 集合=listopen: sql語句的開頭seperator: sql語句的分隔符close: sql語句的結(jié)尾item: 元素名稱 --> <foreach collection="" open="" separator="" close="" item=""> </foreach>
-
①批量查詢: 操作一條sql語句
select * from t_teacher where id in (1,2,3); select * from t_teacher where id = 1 or id = 2 or id = 3;
List<Teacher> findByIds1(List<Integer> idList) throws Exception; List<Teacher> findByIds2(List<Integer> idList) throws Exception;
<!--11.1, 批量查詢--> <!--select * from t_teacher where id in (1,2,3)--> <select id="findByIds1" resultType="Teacher">select * from t_teacher<where>id in<!--(1,2,3)--><foreach collection="list" open="(" separator="," close=")" item="id">#{id}</foreach></where> </select> <!--select * from t_teacher where id = 1 or id = 2 or id = 3--> <select id="findByIds2" resultType="Teacher">select * from t_teacher<where><!--id = 1 or id = 2 or id = 3--><foreach collection="list" separator="or" item="id">id = #{id}</foreach></where> </select>
-
②批量添加: 操作一條sql語句
insert into t_teacher values(null,'劉備','beibei'), (null,'張飛','feifei');
void inserts(List<Teacher> teacherList) throws Exception;
<insert id="inserts">insert into t_teacher values<foreach collection="list" separator="," item="teacher">(null,#{teacher.name},#{teacher.password})</foreach> </insert>
-
③批量刪除: 參考
批量查詢
, 操作一條sql語句delete from t_teacher where id in(1,2,3) delete from t_teacher where id = 1 or id = 2 or id = 3;
-
④批量修改: 操作多條sql語句
update t_teacher set name = 'liubeibei', password = 'babyliu' where id = 1 ; update t_teacher set name = 'zhangfeifei', password = 'feifeifei' where id = 2 ;
void updates(List<Teacher> teacherList) throws Exception;
<update id="updates"><foreach collection="list" separator=";" item="teacher">update t_teacher set name = #{teacher.name}, password = #{teacher.password} where id = #{teacher.id}</foreach></update>
- 注意: mybatis默認(rèn)一次只能執(zhí)行一條sql語句, 如果要支持執(zhí)行多條sql語句, 需要設(shè)置
allowMultiQueries=true
- 注意: mybatis默認(rèn)一次只能執(zhí)行一條sql語句, 如果要支持執(zhí)行多條sql語句, 需要設(shè)置
33-多表關(guān)系設(shè)計(jì)
- 一對一
- 表A中的一條記錄可以確定表B中的一條記錄; 表B中的一條記錄可以確定表A中的一條記錄.
- 比如: 公司和注冊地址
- 一對一查詢
- 一對多
- 表A中的一條記錄可以確定表B中的多條記錄, 表B中的一條記錄可以確定表A中的一條記錄
- 比如: 部門和員工
- 一對一查詢, 一對多查詢
- 多對多
- 表A中的一條記錄可以確定表B中的多條記錄, 表B中的一條記錄可以確定表A中的多條記錄
- 比如: 老師和學(xué)生
- 一對一查詢, 一對多查詢
34-關(guān)聯(lián)查詢環(huán)境搭建
-
數(shù)據(jù)庫代碼
CREATE TABLE t_order (order_id int PRIMARY KEY AUTO_INCREMENT,order_name varchar(30),order_state VARCHAR(40),customer_id BIGINT ); CREATE TABLE t_customer (customer_id int PRIMARY KEY AUTO_INCREMENT,customer_name VARCHAR(60),address VARCHAR(60) );insert into t_order values (null, '訂單一', '已完成', 1),(null, '訂單二', '未完成', 1),(null, '訂單三', '已完成', 2);insert into t_customer values (1, '楊世康', '武漢市洪山區(qū)'),(2, '黃鄭', '武漢市武昌區(qū)'),(3, '崔新凱', '武漢市青山區(qū)'),(4, '李鑫鵬', '武漢市青山區(qū)'),(5, '武一帆', '武漢市青山區(qū)');
-
實(shí)體類代碼
public class Customer {private Integer customerId;private String customerName;private String address;private List<Order> orderList; }
public class Order {private Integer orderId;private String orderName;private String orderState;private Customer customer;}
35-關(guān)聯(lián)查詢之一對一查詢
-
需求
- 根據(jù)id查詢訂單信息, 關(guān)聯(lián)查詢用戶信息.
-
代碼實(shí)現(xiàn)
Order getOrderAndCustomerById(Integer id) throws Exception;
<resultMap id="OrderMap" type="Order"><id column="order_id" property="orderId" javaType="Integer"></id><result column="order_name" property="orderName" javaType="String"></result><result column="order_state" property="orderState" javaType="String"></result><association property="customer" javaType="Customer"><id column="customer_id" property="customerId" javaType="Integer"></id><result column="customer_name" property="customerName" javaType="String"></result><result column="address" property="address" javaType="String"></result></association> </resultMap><select id="getOrderAndCustomerById" resultMap="OrderMap">select *from t_orderleft outer join t_customer on t_order.customer_id = t_customer.customer_idwhere t_order.order_id = #{orderId} </select>
-
注意事項(xiàng)
- 使用
resultMap
自定義輸出映射規(guī)則, 將3個(gè)用戶字段的值
輸出映射給1個(gè)用戶對象屬性
- 使用
36-關(guān)聯(lián)查詢之一對多查詢
-
需求
- 根據(jù)id查詢用戶信息, 關(guān)聯(lián)查詢訂單信息
-
代碼實(shí)現(xiàn)
Customer getCustomerAndOrderById(Integer id) throws Exception;
<resultMap id="CustomerMap" type="Customer"><id column="customer_id" property="customerId" javaType="Integer"></id><result column="customer_name" property="customerName" javaType="String"></result><result column="address" property="address" javaType="String"></result><collection property="orderList" ofType="Order"><id column="order_id" property="orderId" javaType="Integer"></id><result column="order_name" property="orderName" javaType="String"></result><result column="order_state" property="orderState" javaType="String"></result></collection> </resultMap><select id="getCustomerAndOrderById" resultMap="CustomerMap">select *from t_customerleft outer join t_order on t_customer.customer_id = t_order.customer_idwhere t_customer.customer_id = #{customerId} </select>
37-分步查詢之一對一
-
概述
- 分步查詢: 將一次多表查詢拆分成多次單表查詢.
-
一對一
#多表查詢 select * from t_orderleft outer join t_customer on t_order.customer_id = t_customer.customer_id where order_id = 1;#①查詢訂單信息(`customer_id=1`) select * from t_order where order_id = 1;#②根據(jù)`customer_id=1`查詢用戶信息 select * from t_customer where customer_id = 1;
-
需求
- 根據(jù)id查詢訂單信息, 再分步查詢用戶信息
-
開發(fā)步驟
- ①第一次單表查詢
- ②第二次單表查詢
-
①第一次單表查詢
//01-分步查詢之一對一 //1.1,第一次單表查詢 Order getById(Integer id) throws Exception;
<!--01-分步查詢之一對一--> <resultMap id="OrderMap" type="Order"><id column="order_id" property="orderId" javaType="Integer"></id><result column="order_name" property="orderName" javaType="String"></result><result column="order_state" property="orderState" javaType="String"></result><!--1.2,調(diào)用第二次單表查詢--><association property="customer"javaType="Customer"select="com.atguigu.mapper.CustomerMapper.getById"column="customer_id"></association> </resultMap><!--1.1,第一次單表查詢--> <select id="getById" resultMap="OrderMap">select * from t_order where order_id = #{orderId} </select>
-
②第二次單表查詢
//01-分步查詢之一對一 //1.3,第二次單表查詢 Customer getById(Integer id) throws Exception;
<!--01-分步查詢之一對一--> <!--1.3,第二次單表查詢--> <select id="getById" resultType="Customer">select * from t_customer where customer_id = #{customerId} </select>
38-分步查詢之一對多
-
一對多
#多表查詢 select * from t_customerleft join t_order t on t_customer.customer_id = t.customer_id where t.customer_id = 2;#①第一次單表查詢(customer_id = 2) select * from t_customer where customer_id = 2;#②第二次單表查詢(customer_id = 2) select * from t_order where customer_id = 2;
39-mybatis延遲加載
- 概述
- 延遲加載: 也叫懶加載, 在用到時(shí)才查詢.
- 好處
- 能夠大幅度節(jié)約內(nèi)存空間 ,提高查詢效率
- 應(yīng)用場景
- 一對一不推薦使用懶加載, 一對多需要使用懶加載.
40-mybatis延遲加載之一對一
-
概述
lazyLoadingEnabled
: 延遲加載的全局開關(guān)。當(dāng)開啟時(shí),所有關(guān)聯(lián)對象都會延遲加載。 特定關(guān)聯(lián)關(guān)系中可通過設(shè)置fetchType
屬性來覆蓋該項(xiàng)的開關(guān)狀態(tài)。
-
開發(fā)步驟
- ①修改mybatis-config.xml
- lazuLoadingEnabled=true
- ②修改OrderMapper.xml
- fetchType=lazy|eager
- ①修改mybatis-config.xml
-
①修改mybatis-config.xml
<settings><!--懶加載--><setting name="lazyLoadingEnable" value="true"/> </settings>
-
②修改OrderMapper.xml
<resultMap id="OrderMap" type="Order"><id column="order_id" property="orderId" javaType="Integer"></id><result column="order_name" property="orderName" javaType="String"></result><result column="order_state" property="orderState" javaType="String"></result><!--1.2,調(diào)用第二次單表查詢--><association property="customer"javaType="Customer"select="com.atguigu.mapper.CustomerMapper.getById"column="customer_id"fetchType="lazy"></association> </resultMap><select id="getById" resultMap="OrderMap">select * from t_order where order_id = #{orderId} </select>
41-mybatis延遲加載之一對多
-
開發(fā)步驟
- ①修改mybatis-config.xml
- lazuLoadingEnabled=true
- ②修改CustomerMapper.xml
- fetchType=lazy|eager
- ①修改mybatis-config.xml
-
①修改mybatis-config.xml
-
②修改CustomerMapper.xml
<resultMap id="CustomerMap" type="Customer"><id column="customer_id" property="customerId" javaType="Integer"></id><result column="customer_name" property="customerName" javaType="String"></result><result column="address" property="address" javaType="String"></result><!--2.2, 調(diào)用第二次單表查詢--><collection property="orderList"ofType="Order"select="com.atguigu.mapper.OrderMapper.findByCustomerId"column="customer_id" fetchType="lazy"></collection> </resultMap><!--2.1,第一次單表查詢--> <select id="getByName" resultMap="CustomerMap">select * from t_customer where customer_name = #{customerName} </select>
42-mybatis緩存概述
-
概述
-
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-8qhdsZv4-1676283012864)(null)]
-
直接操作數(shù)據(jù)庫, 比較耗費(fèi)時(shí)間, 為了減少程序運(yùn)行的時(shí)長, 可以將之前查詢得到的數(shù)據(jù)保存到
緩存
, 后續(xù)直接使用緩存中的數(shù)據(jù).
-
-
作用
- 減少和數(shù)據(jù)庫的交互次數(shù),提高執(zhí)行效率
-
壞處
- 數(shù)據(jù)的時(shí)效性存在問題
-
分類
-
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-U8X0AJzq-1676283014782)(null)]
-
一級緩存: 數(shù)據(jù)共享范圍在當(dāng)前SqlSession有效, 等價(jià)于請求域;
-
二級緩存: 數(shù)據(jù)共享范圍在整個(gè)應(yīng)用, 等價(jià)于應(yīng)用域.
-
-
流程
- ①mybatis程序查詢記錄, 在二級緩存中查找數(shù)據(jù), 如果有直接使用, 如果沒有查詢一級緩存;
- ②查詢一級緩存, 如果有直接使用, 如果沒有查詢數(shù)據(jù)庫;
- ③查詢數(shù)據(jù)庫, 查詢出來的結(jié)果直接一級緩存, 一級緩存的數(shù)據(jù)在當(dāng)前SqlSession有效;
- ④當(dāng)前SqlSession關(guān)閉時(shí), 會將一級緩存中的數(shù)據(jù)銷毀并存儲到二級緩存.
43-一級緩存的驗(yàn)證
-
概述
- 一級緩存在當(dāng)前SqlSession有效, 也就是當(dāng)前方法有效.
-
開發(fā)步驟
- ①修改mybatis-config.xml, 開啟緩存
- cacheEnabled=true
- ②代碼測試
- ①修改mybatis-config.xml, 開啟緩存
-
①修改mybatis-config.xml, 開啟緩存
<settings><!--緩存--><setting name="cacheEnabled" value="true"/> </settings>
-
②代碼測試
@Test public void getById() throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//操作數(shù)據(jù)庫, 并將結(jié)果保存到一級緩存User user = userMapper.getById(1);System.out.println("user = " + user);//直接使用一級緩存user = userMapper.getById(1);System.out.println("user = " + user);sqlSession.close(); }
44-一級緩存的清空
-
概述
- 為了保證緩存數(shù)據(jù)的時(shí)效性, 需要及時(shí)地(
添加
,刪除
,修改
)清空一級緩存, 存入新的數(shù)據(jù). - 當(dāng)然, 程序員也可以通過SqlSession.clearCache方法來清空一級緩存.
- 為了保證緩存數(shù)據(jù)的時(shí)效性, 需要及時(shí)地(
-
代碼實(shí)現(xiàn)
@Test public void getById2() throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//操作數(shù)據(jù)庫, 并將結(jié)果保存到一級緩存User user = userMapper.getById(1);System.out.println("user = " + user);//增刪改清空一級緩存//userMapper.insert(new User(null , "阿怡","ayi"));//手動(dòng)清空一級緩存sqlSession.clearCache();//操作數(shù)據(jù)庫, 并將結(jié)果保存到一級緩存user = userMapper.getById(1);System.out.println("user = " + user);//使用一級緩存user = userMapper.getById(1);System.out.println("user = " + user);sqlSession.close(); }
45-二級緩存的驗(yàn)證
-
開發(fā)步驟
- ①修改mybatis-config.xml, 開啟緩存全局開關(guān)
- cacheEnabled=true
- ②修改mapper映射文件, 開啟緩存局部開關(guān)
- 添加
cache標(biāo)簽
- 在指定的statement上使用
useCache=true|false
- 添加
- ③實(shí)體類實(shí)現(xiàn)Serializable接口
- ③代碼測試
- ①修改mybatis-config.xml, 開啟緩存全局開關(guān)
-
①修改mybatis-config.xml, 開啟緩存全局開關(guān)
- 參考
07-一級緩存的驗(yàn)證
- 參考
-
②修改mapper映射文件, 開啟緩存局部開關(guān)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.qh.mapper.UserMapper"><cache></cache><select id="getById" resultType="User" useCache="true">select * from t_user where user_id = #{userId}</select><insert id="insert">insert into t_user values(null,#{userName},#{userPwd})</insert></mapper>
-
③實(shí)體類實(shí)現(xiàn)Serializable接口
public class User implements Serializable {private Integer userId;private String userName;private String userPwd;}
-
④代碼測試
//09-二級緩存的驗(yàn)證 @Test public void getById3() throws Exception {//①第一個(gè)SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//操作數(shù)據(jù)庫, 并將數(shù)據(jù)存儲到一級緩存User user = userMapper.getById(1);System.out.println("user = " + user);//使用一級緩存user = userMapper.getById(1);System.out.println("user = " + user);//將一級緩存清空并存儲到二級緩存sqlSession.close();//②第二個(gè)SqlSessionsqlSession = sqlSessionFactory.openSession();userMapper = sqlSession.getMapper(UserMapper.class);//使用二級緩存user = userMapper.getById(1);System.out.println("user = " + user);sqlSession.close();//③第三個(gè)SqlSessionsqlSession = sqlSessionFactory.openSession();userMapper = sqlSession.getMapper(UserMapper.class);//使用二級緩存user = userMapper.getById(1);System.out.println("user = " + user);sqlSession.close(); }
-
二級緩存命中率
- [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-tVsPvCV4-1676283014372)(null)]
46-EHCache二級緩存
-
概述
- Ehcache是一種開源的、基于標(biāo)準(zhǔn)的緩存,可以提高性能、減輕數(shù)據(jù)庫負(fù)擔(dān),并簡化可擴(kuò)展性。它是 使用最廣泛的基于Java的緩存,因?yàn)樗?、?jīng)過驗(yàn)證、功能齊全,并且與其他流行的庫和框架集 成。
-
開發(fā)步驟
- ①引入依賴
- ②編寫ehcache.xml配置文件
- ③修改mapper映射文件, 指定使用ehcache
- ④代碼測試
-
①引入依賴
<dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.2.3</version> </dependency>
-
②編寫ehcache.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"><!-- 磁盤保存路徑 --><diskStore path="D:\mybatis-ehcache"/><defaultCachemaxElementsInMemory="1000"maxElementsOnDisk="10000000"eternal="false"overflowToDisk="true"timeToIdleSeconds="120"timeToLiveSeconds="120"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"></defaultCache> </ehcache>
-
③修改mapper映射文件, 指定使用ehcache
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.qh.mapper.UserMapper"><cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache><select id="getById" resultType="User" useCache="true">select * from t_user where user_id = #{userId}</select></mapper>
-
④代碼測試
- 參考
44-二級緩存的驗(yàn)證
- 參考
47-EHCache配置參數(shù)
- 配置參數(shù)
- [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-4EvnD2ba-1676283012289)(null)]
48-mybatis逆向工程概述
- 概述
- 正向工程: 實(shí)體類 -> 表, dao接口, mapper映射文件
- 逆向工程: 表-> 實(shí)體類, dao接口, mapper映射文件
49-mybatis逆向工程操作
-
開發(fā)步驟
- ①新建逆向工程項(xiàng)目: mybatis-generator-project
- ②配置pom.xml
- ③配置generatorConfig.xml, 逆向工程核心配置文件
- ④執(zhí)行逆向操作
- ⑤查看效果
-
①新建逆向工程項(xiàng)目: mybatis-generator-project
-
②配置pom.xml
<dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.11</version></dependency> </dependencies> <!-- 控制Maven在構(gòu)建過程中相關(guān)配置 --> <build><!-- 構(gòu)建過程中用到的插件 --><plugins><!-- 具體插件,逆向工程的操作是以構(gòu)建過程中插件形式出現(xiàn)的 --><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><!-- 數(shù)據(jù)庫連接池 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.2</version></dependency><!-- MySQL驅(qū)動(dòng) --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.32</version></dependency></dependencies></plugin></plugins> </build>
-
③配置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: 執(zhí)行生成的逆向工程的版本MyBatis3Simple: 生成基本的CRUD(清新簡潔版)MyBatis3: 生成帶條件的CRUD(奢華尊享版)--><context id="DB2Tables" targetRuntime="MyBatis3"><!-- 數(shù)據(jù)庫的連接信息 --><jdbcConnection driverClass="com.mysql.jdbc.Driver"connectionURL="jdbc:mysql://127.0.0.1:3306/mydb1"userId="root"password="root"></jdbcConnection><!-- javaBean的生成策略--><javaModelGenerator targetPackage="com.atguigu.pojo" targetProject=".\src\main\java"><property name="enableSubPackages" value="true"/><property name="trimStrings" value="true"/></javaModelGenerator><!-- SQL映射文件的生成策略 --><sqlMapGenerator targetPackage="com.atguigu.mapper" targetProject=".\src\main\java"><property name="enableSubPackages" value="true"/></sqlMapGenerator><!-- Mapper接口的生成策略 --><javaClientGenerator type="XMLMAPPER" targetPackage="com.atguigu.mapper"targetProject=".\src\main\java"><property name="enableSubPackages" value="true"/></javaClientGenerator><!-- 逆向分析的表 --><!-- tableName設(shè)置為*號,可以對應(yīng)所有表,此時(shí)不寫domainObjectName --><!-- domainObjectName屬性指定生成出來的實(shí)體類的類名 --><table tableName="t_user" domainObjectName="User"/></context> </generatorConfiguration>
-
④執(zhí)行逆向操作
- [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-vcs1Tp6w-1676283012724)(null)]
-
雙擊運(yùn)行生成
50-QBC查詢
-
[外鏈圖片轉(zhuǎn)存中…(img-jDgDHKOb-1676283111659)]
-
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-paEpJpla-1676283014630)(null)]
-
概述
- QBC: Query By Criteria
- QBC查詢最大的特點(diǎn)就是將SQL語句中的WHERE子句進(jìn)行了組件化的封裝,讓我們可以通過調(diào)用Criteria 對象的方法自由的拼裝查詢條件
-
開發(fā)步驟
- ①將
mybatis-generator-project
項(xiàng)目生成的資料拷貝到項(xiàng)目 - ②代碼測試
- ①將
-
①將
mybatis-generator-project
項(xiàng)目生成的資料拷貝到項(xiàng)目 -
②代碼測試
public class UserMapperTest {private SqlSessionFactory sqlSessionFactory;@Beforepublic void init() throws IOException {sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));}//添加記錄, 固定SQL@Testpublic void insert() {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User inputUser = new User(null, "劉宇豪", "haohao");userMapper.insert(inputUser);sqlSession.commit();sqlSession.close();}//添加記錄, 動(dòng)態(tài)SQL@Testpublic void insertSelective() {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User inputUser = new User(null, "劉宇豪", "haohao");userMapper.insertSelective(inputUser);sqlSession.commit();sqlSession.close();}/*** 刪除記錄, 根據(jù)主鍵. 固定SQL*/@Testpublic void deleteByPrimaryKey() {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);userMapper.deleteByPrimaryKey(8);sqlSession.commit();sqlSession.close();}/*** 刪除記錄, 根據(jù)criteria刪除, where動(dòng)態(tài)SQL*/@Testpublic void deleteByExample() {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);UserExample example = new UserExample();UserExample.Criteria criteria1 = example.createCriteria();criteria1.andUserIdEqualTo(1);criteria1.andUserNameEqualTo("好好");UserExample.Criteria criteria2 = example.or();criteria2.andUserIdEqualTo(2);userMapper.deleteByExample(example);//sqlSession.commit();sqlSession.close();}/*** 查詢記錄, 根據(jù)主鍵查詢, 固定SQL*/@Testpublic void selectByPrimaryKey() {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User user = userMapper.selectByPrimaryKey(1);System.out.println("user = " + user);sqlSession.close();}/*** 查詢記錄, 根據(jù)Criteria查詢, where動(dòng)態(tài)SQL*/@Testpublic void selectByExample() {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);UserExample example = new UserExample();UserExample.Criteria criteria = example.createCriteria();criteria.andUserIdBetween(1, 10);List<User> userList = userMapper.selectByExample(example);System.out.println("userList = " + userList);sqlSession.close();}/*** 統(tǒng)計(jì)記錄, 根據(jù)Criteria查詢, where動(dòng)態(tài)SQL*/@Testpublic void countByExample() {}/*** 修改記錄, 根據(jù)主鍵, 固定SQL*/@Testpublic void updateByPrimaryKey() {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);userMapper.updateByPrimaryKey(new User(1, "a", "a"));//sqlSession.commit();sqlSession.close();}/*** 修改記錄, 根據(jù)主鍵, set動(dòng)態(tài)SQL*/@Testpublic void updateByPrimaryKeySelective() {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);userMapper.updateByPrimaryKeySelective(new User(1, null, "a"));//sqlSession.commit();sqlSession.close();}/*** 修改記錄, 根據(jù)Criteria, set固定SQL, where動(dòng)態(tài)SQL*/@Testpublic void updateByExample() {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User inputUser = new User(1, null, "a");UserExample example = new UserExample();UserExample.Criteria criteria = example.createCriteria();criteria.andUserIdEqualTo(1);userMapper.updateByExample(inputUser, example);//sqlSession.commit();sqlSession.close();}/*** 修改記錄, 根據(jù)Criteria, set動(dòng)態(tài)SQL, where動(dòng)態(tài)SQL*/@Testpublic void updateByExampleSelective() {SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User inputUser = new User(1, null, "a");UserExample example = new UserExample();UserExample.Criteria criteria = example.createCriteria();criteria.andUserIdEqualTo(1);userMapper.updateByExampleSelective(inputUser, example);//sqlSession.commit();sqlSession.close();}}
-
注意事項(xiàng)
- 多個(gè)Cretiria對象之間用
or
分割, Criteria對象內(nèi)部條件用and
分割.
- 多個(gè)Cretiria對象之間用
51-mybatis注解開發(fā)概述
- 概述
- 使用注解配置替代xml配置(映射配置文件)
- 常用注解
- @Insert, @Delete, @Update, @Select, @Results, @Many, @One, @Result
52-mybatis注解操作CRUD
-
代碼實(shí)現(xiàn)
public interface TeacherMapper {@Insert("insert into t_teacher values(null,#{name},#{password})")int insert(Teacher teacher) throws Exception;@Delete("delete from t_teacher where id = #{id}")int delete(Integer id) throws Exception;@Update("update t_teacher set name=#{name}, password=#{password} where id = #{id}")int update(Teacher teacher) throws Exception;@Select("select * from t_teacher where id = #{id}")Teacher getById(Integer id) throws Exception;}
53-mybatis復(fù)雜關(guān)系映射注解說明(掌握)
-
回顧
<resultMap><id></id><result></result><association></association><collection></collection> </resultMap>
-
①@Results
- 等價(jià)于
<resultMap>標(biāo)簽
- 有多個(gè)
@Result注解
- 等價(jià)于
-
②@Result
- @Result(id = true) 等價(jià)于
<id>標(biāo)簽
- @Result(id = false) 等價(jià)于
<result>標(biāo)簽
- @Result(id = false,one=@One ) 等價(jià)于
<association>標(biāo)簽
, 一對一查詢 - @Result(id = false,many=@Many ) 等價(jià)于
<collection>標(biāo)簽
, 一對多查詢
- @Result(id = true) 等價(jià)于
-
③@One
- 一對一查詢
-
④@Many
- 一對多查詢
54-mybatis注解實(shí)現(xiàn)一對一查詢
-
需求
- 根據(jù)訂單信息查詢用戶信息
-
①第一次單表查詢
//01-分步查詢之一對一 @Results({@Result(id = true, column = "order_id", property = "orderId", javaType = Integer.class),@Result(column = "order_name", property = "orderName", javaType = String.class),@Result(column = "order_state", property = "orderState", javaType = String.class),@Result(property = "customer",javaType = Customer.class,column = "customer_id",//1.2,調(diào)用第二次單表查詢one = @One(select = "com.atguigu.mapper.CustomerMapper.getById", fetchType = FetchType.LAZY)) }) //1.1,第一次單表查詢 @Select("select * from t_order where order_id = #{orderId}") Order getById(Integer id) throws Exception;
-
②第二次單表查詢
//01-分步查詢之一對一 //1.3,第二次單表查詢@Select("select * from t_customer where customer_id = #{customerId}") Customer getById(Integer id) throws Exception;
55-mybatis注解實(shí)現(xiàn)一對多查詢
-
需求
- 根據(jù)用戶信息查詢訂單信息
-
①第一次單表查詢
//02-分步查詢之一對多 //2.2,調(diào)用第二次單表查詢 @Results({@Result(id = true, column = "customer_id", property = "customerId", javaType = Integer.class),@Result(column = "customer_name", property = "customerName", javaType = String.class),@Result(column = "address", property = "address", javaType = String.class),@Result(property = "orderList",many = @Many(select = "com.atguigu.mapper.OrderMapper.findByCustomerId",fetchType = FetchType.LAZY),column = "customer_id"),}) //2.1, 第一次單表查詢 @Select("select * from t_customer where customer_name = #{customerName}") Customer getByName(String name) throws Exception;
-
②第二次單表查詢
//02-分步查詢之一對多 //2.3,第二次單表查詢 @Select("select * from t_order where customer_id = #{customerId}") List<Order> findByCustomerId(Integer customerId) throws Exception;
-
思考: mybatis注解如何實(shí)現(xiàn)動(dòng)態(tài)SQL?
- 構(gòu)建SQL , 使用mybatis內(nèi)置API ; SQL , values(), …