MyBatis知識點

一、MyBatis簡介

1.1 框架概念

框架,就是軟件的半成品,完成了軟件開發過程中的通用操作,程序員只需很少或者不用進行加工就能夠實現特定的功能,從而簡化開發人員在軟件開發中的步驟,提高開發效率。

1.2 常用框架

  • MVC框架:簡化了Servlet的開發步驟
    • Struts
    • Struts2
    • SpringMVC
  • 持久層框架:完成數據庫操作的框架
    • apache DBUtils
    • Hibernate
    • Spring JPA
    • MyBatis
    • EJB3.0
  • 膠水框架:Spring

SSM Spring SpringMVC MyBatis

SSH Spring Struts2 Hibernate

1.3 MyBatis介紹

MyBatis是一個半自動ORM框架

ORM(Object Relational Mapping)對象關系映射,將Java中的一個對象與數據表中一行記錄一一對應。

ORM框架提供了實體類與數據表的映射關系,通過映射文件的配置,實現對象的持久化。

  • MyBatis的前身是iBatis,iBatis是Apache軟件基金會提供的一個開源項目
  • 2010年iBatis遷移到Google code,正式更名為MyBatis
  • 2013年遷移到Github托管
  • MyBatis特點:
    • 支持自定義SQL、存儲過程
    • 對原有的JDBC進行了封裝,幾乎消除了所有JDBC代碼,讓開發者只需關注SQL本身
    • 支持XML和注解配置方式自定完成ORM操作,實現結果映射

二、MyBatis框架部署

框架部署,就是將框架引入到我們的項目中

2.1 創建Maven項目

  • Java工程
  • Web工程

2.2 在項目中添加MyBatis依賴

  • 在pom.xml中添加依賴

    • mybatis
    • mysql driver
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version>
    </dependency><!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version>
    </dependency>
    

2.3 創建MyBatis配置文件

  • 創建自定義模板:選擇resources----右鍵New----Edit File Templates

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-P4JExyWD-1639493777615)(imgs/1616144597211.png)]

  • 在resources中創建名為mybatis-config.xml的文件

  • mybatis-config.xml文件配置數據庫連接信息

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration><!-- 在environments配置數據庫連接信息 --><!-- 在environments標簽中可以定義多個environment標簽,每個environment標簽可以定義一套連接配置 --><!-- default屬性,用來指定使用哪個environment標簽 --><environments default="mysql"><environment id="mysql"><!--transactionManager標簽用于配置數據庫管理方式--><transactionManager type="JDBC"></transactionManager><!--dataSource標簽就是用來配置數據庫連接信息 --><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/db_2010_fmwy?characterEncoding=utf-8"/><property name="username" value="root"/><property name="password" value="admin123"/></dataSource></environment></environments></configuration>
    

三、MyBatis框架使用

案例:學生信息的數據庫操作

3.1 創建數據表

tb_students
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-FppE0G06-1639493777619)(imgs/1616145569298.png)]

3.2 創建實體類

Student.java
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-GSFZ4RV3-1639493777619)(imgs/1616145876310.png)]

3.3 創建DAO接口,定義操作方法

StudentDAO.java
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-H2R7Xmra-1639493777621)(imgs/1616147015300.png)]

3.4 創建DAO接口的映射文件

  • resources目錄下,新建名為mappers文件夾
  • mappers中新建名為StudentMapper.xml的映射文件(根據模板創建)
  • 在映射文件中對DAO中定義的方法進行實現:
<?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文件相當于DAO接口的‘實現類’,namespace屬性要指定`實現`DAO接口的全限定名-->
<mapper namespace="com.qfedu.dao.StudentDAO"><insert id="insertStudent">insert into tb_students(stu_num,stu_name,stu_gender,stu_age)values(#{stuNum},#{stuName},#{stuGender},#{stuAge})</insert><delete id="deleteStudent">delete from tb_students where stu_num=#{stuNum}</delete></mapper>

3.5 將映射文件添加到主配置文件

mybatis-config.xml
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Q0lf9JK0-1639493777621)(imgs/1616146926729.png)]

四、單元測試

4.1 添加單元測依賴

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version>
</dependency>

4.2 創建單元測試類

在被測試類名后alt+insert — 選擇Test
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VMGaSWhm-1639493777622)(imgs/1616147095936.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2uvbBYCd-1639493777623)(imgs/1616147180562.png)]

4.3 測試代碼

package com.qfedu.dao;import com.qfedu.pojo.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;import static org.junit.Assert.*;public class StudentDAOTest {@org.junit.Testpublic void insertStudent() {try {//加載mybatis配置文件InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//會話工廠SqlSessionFactory factory = builder.build(is);//會話(連接)SqlSession sqlSession = factory.openSession();//通過會話獲取DAO對象StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);//測試StudentDAO中的方法int i = studentDAO.insertStudent(new Student(0, "10001", "張三", "男", 21));//需要手動提交sqlSession.commit();System.out.println(i);} catch (IOException e) {e.printStackTrace();}}@org.junit.Testpublic void deleteStudent() {}
}

五、MyBatis的CRUD操作

案例:學生信息的增刪查改

5.1 添加操作

5.2 刪除操作

根據學號刪除一條學生信息

  • 在StudentDAO中定義刪除方法
StudentDAO
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HCObnCRl-1639493777624)(imgs/1616463209812.png)]
  • 在StudentMapper.xml中對接口方法進行“實現”
StudentMapper.xml
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-AbKpsHuZ-1639493777625)(imgs/1616463282187.png)]
  • 測試:在StudentDAO的測試類中添加測試方法
StudentDAOTest
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hUYCWgfM-1639493777626)(imgs/1616464771784.png)]

5.3 修改操作

根據學生學號,修改其他字段信息

  • 在StudentDAO接口中定義修改方法
StudentDAO
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-McpeRIEg-1639493777626)(imgs/1616465607290.png)]
  • 在StudentMapper.xml中“實現”接口中定義的修改方法
StudentMapper.xml
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-14p5zRZL-1639493777627)(imgs/1616465639080.png)]
  • 單元測試
StudentDAOTest
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xYIcjRfO-1639493777628)(imgs/1616465667657.png)]

5.4 查詢操作-查詢所有

  • 在StudentDAO接口定義操作方法
StudentDAO
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-1oDFXZF6-1639493777629)(imgs/1616467216382.png)]
  • 在StudentMapper.xml中“實現”DAO中定義的方法
StudentMapper.xml
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gGwmF4HX-1639493777629)(imgs/1616467314082.png)]
  • 單元測試
StudentDAOTest
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xci0oBM2-1639493777630)(imgs/1616467336432.png)]

5.5 查詢操作-查詢一條記錄

根據學號查詢一個學生信息

  • 在StudentDAO接口中定義方法
StudentDAO
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZfqOcjhG-1639493777631)(imgs/1616469113754.png)]
  • 在StudentDAOMapper.xml中配置StudentDAO接口的方法實現——SQL
StudentDAOMapper.xml
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-fwMetDD6-1639493777631)(imgs/1616469142604.png)]
  • 單元測試
StudentDAOTest
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VBclfidK-1639493777638)(imgs/1616469154258.png)]

5.6 查詢操作-多參數查詢

分頁查詢(參數 start , pageSize)

  • 在StudentDAO中定義操作方法,如果方法有多個參數,使用@Param注解聲明參數的別名
StudentDAO
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-yIXlmzgc-1639493777638)(imgs/1616470534343.png)]
  • 在StudentMapper.xml配置sql時,使用#{別名}獲取到指定的參數
StudentMapper.xml
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HI4IVPTg-1639493777639)(imgs/1616470612608.png)]

注意 如果DAO操作方法沒有通過@Param指定參數別名,在SQL中也可以通過arg0,arg1...或者param1,param2,...獲取參數

5.7 查詢操作-查詢總記錄數

  • 在StudentDAO接口中定義操作方法
StudentDAO
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-JWtfTDQ5-1639493777639)(imgs/1616471133486.png)]
  • 在StudentMapper.xml配置sql,通過resultType指定當前操作的返回類型為int
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-GIQtkvSD-1639493777640)(imgs/1616471056064.png)]

5.8 添加操作回填生成的主鍵

  • StduentMapper.xml的添加操作標簽——insert
<!-- useGeneratedKeys 設置添加操作是否需要回填生成的主鍵 -->
<!-- keyProperty 設置回填的主鍵值賦值到參數對象的哪個屬性 -->
<insert id="insertStudent" useGeneratedKeys="true" keyProperty="stuId">insert into tb_students(stu_num, stu_name, stu_gender, stu_age)values (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
</insert>

六、MyBatis工具類封裝

  • MyBatisUtil
public class MyBatisUtil {private static SqlSessionFactory factory;private static final ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();static{try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();factory = builder.build(is);} catch (IOException e) {e.printStackTrace();}}public static SqlSessionFactory getFactory(){return factory;}public static SqlSession getSqlSession(){SqlSession sqlSession = local.get();if(sqlSession == null ){sqlSession = factory.openSession();local.set(sqlSession);}return sqlSession;}public static <T extends Object> T getMapper(Class<T> c){SqlSession sqlSession = getSqlSession();return sqlSession.getMapper(c);}}

七、事務管理

SqlSession 對象

  • getMapper(DAO.class) : 獲取Mapper(DAO接口的實例)
  • 事務管理

7.1 手動提交事務

  • sqlSession.commit();提交事務
  • sqlSession.rollback();事務回滾

測試類中進行事務管理

@Test
public void insertStudent() {SqlSession sqlSession = MyBatisUtil.getSqlSession();//1.當我們獲取sqlSession對象時,就默認開啟了事務try{//通過會話獲取DAO對象StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);//測試StudentDAO中的方法Student student = new Student(0, "10005", "Lily", "女", 21);int i = studentDAO.insertStudent(student);//2.操作完成并成功之后,需要手動提交sqlSession.commit();}catch (Exception e){//3.當操作出現異常,調用rollback進行回滾sqlSession.rollback();}
}

業務邏輯層手動事務管理

public class StudentServiceImpl implements StudentService {public boolean addStudent(Student student) {boolean b = false;SqlSession sqlSession = MyBatisUtil.getSqlSession();try{StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);int i = studentDAO.insertStudent(student);b = i>0;sqlSession.commit();}catch (Exception e){sqlSession.rollback();}return b;}
}

7.2 自動提交事務

通過SqlSessionFactory調用openSession方法獲取SqlSession對象時,可以通過參數設置事務是否自動提交:

  • 如果參數設置為true,表示自定提交事務: factory.openSession(true);

  • 如果參數設置為false,或者不設置參數,表示手動提交:factory.openSession();/factory.openSession(false);

MyBatisUtil優化

public class MyBatisUtil {private static SqlSessionFactory factory;private static final ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();static{try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();factory = builder.build(is);} catch (IOException e) {e.printStackTrace();}}public static SqlSessionFactory getFactory(){return factory;}private static SqlSession getSqlSession(boolean isAutoCommit){SqlSession sqlSession = local.get();if(sqlSession == null ){sqlSession = factory.openSession(isAutoCommit);local.set(sqlSession);}return sqlSession;}//手動事務管理public static SqlSession getSqlSession(){return getSqlSession(false);}//自動事務提交public static <T extends Object>T getMapper(Class<T> c){SqlSession sqlSession = getSqlSession(true);return sqlSession.getMapper(c);}}

測試操作

@Test
public void testDeleteStudent() {StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class);int i = studentDAO.deleteStudent("10001");
}

業務邏輯層自動事務管理

public class StudentServiceImpl implements StudentService {private StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class);public boolean addStudent(Student student) {int i = studentDAO.insertStudent(student);boolean b = i>0;return b;}
}

八、MyBatis主配置文件

mybatis-config.xml 是MyBatis框架的主配置文件,只要用于配置MyBatis數據源及屬性信息

8.1 properties標簽

用于設置鍵值對,或者加載屬性文件

  • 在resources目錄下創建jdbc.properties文件,配置鍵值對如下:
mysql_driver=com.mysql.jdbc.Driver
mysql_url=jdbc:mysql://localhost:3306/db_2010_fmwy?characterEncoding=utf-8
mysql_username=root
mysql_password=admin123
  • 在mybatis-config.xml中通過properties標簽引用jdbc.properties文件;引入之后,在配置environment時可以直接使用jdbc.properties的key獲取對應的value
mybatis-config.xml
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DqVD8IaY-1639493777640)(imgs/1616482928813.png)]

8.2 settings標簽

<!--設置mybatis的屬性-->
<settings><!-- 啟動二級緩存--><setting name="cacheEnabled" value="true"/><!-- 啟動延遲加載 --><setting name="lazyLoadingEnabled" value="true"/>
</settings>

8.3 typeAliases標簽

<!--typeAliases標簽用于給實體類取別名,在映射文件中可以直接使用別名來替代實體類的全限定名-->
<typeAliases><typeAlias type="com.qfedu.pojo.Student" alias="Student"></typeAlias><typeAlias type="com.qfedu.pojo.Book" alias="Book"></typeAlias>
</typeAliases>

8.4 plugins標簽

<!--plugins標簽,用于配置MyBatis插件(分頁插件)-->
<plugins><plugin interceptor=""></plugin>
</plugins>

8.5 environments標簽

<!-- 在environments配置數據庫連接信息 -->
<!-- 在environments標簽中可以定義多個environment標簽,每個environment標簽可以定義一套連接配置 -->
<!-- default屬性,用來指定使用哪個environment標簽 -->
<environments default="mysql"><!--  environment 標簽用于配置數據庫連接信息  --><environment id="mysql"><!--transactionManager標簽用于配置數據庫管理方式type="JDBC"  可以進行事務的提交和回滾操作type="MANAGED" 依賴容器完成事務管理,本身不進行事務的提交和回滾操作 --><transactionManager type="JDBC"></transactionManager><!--dataSource標簽就是用來配置數據庫連接信息 POOLED|UNPOOLED --><dataSource type="POOLED"><property name="driver" value="${mysql_driver}"/><property name="url" value="${mysql_url}"/><property name="username" value="${mysql_username}"/><property name="password" value="${mysql_password}"/></dataSource></environment></environments>

8.6 mappers標簽

加載映射配置(映射文件、DAO注解)

<!--mappers標簽用于載入映射文件-->
<mappers><mapper resource="mappers/StudentMapper.xml"></mapper>
</mappers>

九、映射文件

9.1 MyBatis Mapper初始化

XML文件解析:讀取xml文件中的標簽配置封裝到Java對象中

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-eFmhNoJc-1639493777641)(imgs/1616487875112.png)]

9.2 mapper根標簽

mapper文件相當于DAO接口的‘實現類’,namespace屬性要指定實現DAO接口的全限定名

9.3 insert標簽

聲明添加操作(sql: insert …)

常用屬性

id屬性,綁定對應DAO接口中的方法

parameterType屬性,用以指定接口中對應方法的參數類型(可省略)

useGeneratedKeys屬性, 設置添加操作是否需要回填生成的主鍵

keyProperty屬性,指定回填的id設置到參數對象中的哪個屬性

timeout屬性,設置此操作的超時時間,如果不設置則一直等待

主鍵回填

<insert id="insertStudent" useGeneratedKeys="true" keyProperty="stuId">insert into tb_students(stu_num, stu_name, stu_gender, stu_age)values (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
</insert>
<insert id="insertStudent" ><selectKey keyProperty="stuId" resultType="java.lang.Integer">select last_insert_id()</selectKey>insert into tb_students(stu_num, stu_name, stu_gender, stu_age)values (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
</insert>

9.4 delete標簽

聲明刪除操作

9.5 update標簽

聲明修改操作

9.6 select標簽

聲明查詢操作

  • id屬性, 指定綁定方法的方法名

  • parameterType屬性,設置參數類型

  • resultType屬性,指定當前sql返回數據封裝的對象類型(實體類)

  • resultMap屬性,指定從數據表到實體類的字段和屬性的對應關系

  • useCache屬性,指定此查詢操作是否需要緩存

  • timeout屬性,設置超時時間

9.7 resultMap標簽

<!-- resultMap標簽用于定義實體類與數據表的映射關系(ORM) -->
<resultMap id="studentMap" type="Student"><id column="sid" property="stuId"/><result column="stu_num" property="stuNum"/><result column="stu_name" property="stuName"/><result column="stu_gender" property="stuGender"/><result column="stu_age" property="stuAge"/>
</resultMap>

9.8 cache標簽

設置當前DAO進行數據庫操作時的緩存屬性設置

<cache type="" size="" readOnly="false"/>

9.9 sql和include

SQL片段

<sql id="wanglaoji">sid , stu_num , stu_name , stu_gender , stu_age</sql><select id="listStudents" resultMap="studentMap">select <include refid="wanglaoji"/> from tb_students
</select>

十、分頁插件

分頁插件是一個獨立于MyBatis框架之外的第三方插件;

10.1 添加分頁插件的依賴

PageHelper

 <!-- pagehelper分頁插件 -->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.10</version>
</dependency>

10.2 配置插件

在mybatis的主配置文件mybatis-config.xml中通過plugins標簽進行配置

<!--plugins標簽,用于配置MyBatis插件(分頁插件)-->
<plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

10.3 分頁實例

對學生信息進行分頁查詢

@Test
public void testListStudentsByPage() {StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class); //sqlSessionPageHelper.startPage(2,4);List<Student> students = studentDAO.listStudents();PageInfo<Student> pageInfo = new PageInfo<Student>(students);//pageInfo中就包含了數據及分頁信息
}

帶條件分頁

@Test
public void testListStudentsByPage() {StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class); //sqlSessionPageHelper.startPage(2,4);//List<Student> students = studentDAO.listStudents();List<Student> list = studentDAO.listStudentsByGender("女");PageInfo<Student> pageInfo = new PageInfo<Student>(list);//pageInfo中就包含了數據及分頁信息
}

十一、關聯映射

11.1 實體關系

實體——數據實體,實體關系指的就是數據與數據之間的關系

例如:用戶和角色、房屋和樓棟、訂單和商品

實體關系分為以下四種:

一對一關聯

實例:人和身份證、學生和學生證、用戶基本信息和詳情

數據表關系:

  • 主鍵關聯(用戶表主鍵 和詳情主鍵相同時,表示是匹配的數據)

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lF3JppTg-1639493777641)(imgs/1616550990633.png)]

  • 唯一外鍵關聯

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9kQgWLt5-1639493777642)(imgs/1616551159843.png)]

一對多關聯多對一關聯

實例:

  • 一對多: 班級和學生 、 類別和商品、樓棟和房屋
  • 多對一:學生和班級 、 商品和類別

數據表關系:

  • 在多的一端添加外鍵和一的一段進行關聯

多對多關聯

實例:用戶和角色、角色和權限、房屋和業主、學生和社團、訂單和商品

數據表關系:建立第三張關系表添加兩個外鍵分別與兩張表主鍵進行關聯

用戶(user_id) 用戶角色表(uid,rid) 角色(role_id)

11.2 創建項目,部署MyBatis框架

  • 創建web項目(maven)

    <!-- 添加web依賴 -->
    <dependency><groupId>javax.servlet</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope>
    </dependency>
    <dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope>
    </dependency>
    
  • 部署MyBatis框架

    • 添加依賴
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version>
    </dependency>
    
    • 配置文件
    • 幫助類
    public class MyBatisUtil {private static SqlSessionFactory factory;private static final ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();static{try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");factory = new SqlSessionFactoryBuilder().build(is);} catch (IOException e) {e.printStackTrace();}}public static SqlSessionFactory getSqlSessionFactory(){return factory;}public static SqlSession getSqlSession(boolean isAutoCommit){SqlSession sqlSession = local.get();if(sqlSession == null){sqlSession = factory.openSession(isAutoCommit);local.set(sqlSession);}return sqlSession;}public static SqlSession getSqlSession(){return getSqlSession(false);}public static <T extends  Object>T getMapper(Class<T> c){SqlSession sqlSession = getSqlSession(true);return sqlSession.getMapper(c);}}
    

11.3 一對一關聯

實例:用戶—詳情

11.3.1 創建數據表
-- 用戶信息表
create table users(user_id int primary key auto_increment,user_name varchar(20) not null unique,user_pwd varchar(20) not null,user_realname varchar(20) not null,user_img varchar(100) not null
);-- 用戶詳情表
create table details(detail_id int primary key auto_increment,user_addr varchar(50) not null,user_tel char(11) not null,user_desc varchar(200),uid int not null unique-- constraint FK_USER foreign key(uid) references users(user_id)
);
11.3.2 創建實體類
  • User

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ToString
    public class User {private int userId;private String userName;private String userPwd;private String userRealname;private String userImg;
    }
    
  • Detail

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ToString
    public class Detail {private int detailId;private String userAddr;private String userTel;private String userDesc;private int userId;
    }
    
11.3.3 添加操作(事務)
測試代碼
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EQ0GrcR5-1639493777642)(imgs/1616558872585.png)]
11.3.4 一對一關聯查詢

在查詢用戶的同時關聯查詢出與之對應的詳情

實體

UserDetail
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7O8YTeN4-1639493777643)(imgs/1616557527886.png)][外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-4guaBShg-1639493777644)(imgs/1616557509389.png)]

映射文件

連接查詢
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VLVqCWzx-1639493777644)(imgs/1616558061073.png)]
子查詢
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rp27lso2-1639493777645)(imgs/1616558696902.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-JcX1ZueX-1639493777645)(imgs/1616558739190.png)]

11.4 一對多關聯

案例:班級(1)—學生(n)

11.4.1 創建數據表
-- 創建班級信息表
create table classes(cid int primary key auto_increment,cname varchar(30) not null unique,cdesc varchar(100)
);-- 創建學生信息表
create table students(sid char(5) primary key,sname varchar(20) not null,sage int not null,scid int not null
);
11.4.2 創建實體類
ClazzStudent
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9UKos2PN-1639493777646)(imgs/1616566868757.png)][外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-bubopJKg-1639493777646)(imgs/1616566709567.png)]
11.4.3 關聯查詢

當查詢一個班級的時候, 要關聯查詢出這個班級下的所有學生

連接查詢

連接查詢映射配置
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-IX7Z9twQ-1639493777647)(imgs/1616567949549.png)]

子查詢

子查詢映射配置
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rXvcuBMD-1639493777648)(imgs/1616568410749.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-TNAheVr2-1639493777648)(imgs/1616568443022.png)]

11.5 多對一關聯

實例:學生(n)—班級(1)

當查詢一個學生的時候,關聯查詢這個學生所在的班級信息

11.5.1 創建實體類
StudentClazz
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pHLhsn1S-1639493777649)(imgs/1616568763050.png)][外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CWjmY7v3-1639493777649)(imgs/1616568809974.png)]
11.5.2 關聯查詢

連接查詢

連接查詢映射配置
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-bLeWPLcu-1639493777650)(imgs/1616569488794.png)]

子查詢

子查詢映射配置
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ro5YETEW-1639493777650)(imgs/1616569897430.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-AdruQhxF-1639493777651)(imgs/1616569932235.png)]

11.6 多對多關聯

案例:學生(m)—課程(n)

11.6.1 創建數據表
-- 學生信息表(如上)
-- 課程信息表
create table courses(course_id int primary key auto_increment,course_name varchar(50) not null
);
-- 選課信息表/成績表(學號、課程號、成績)
create table grades(sid char(5) not null,cid int not null,score int not null
);
11.6.2 關聯查詢

查詢學生時,同時查詢學生選擇的課程

StudentCourse
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ziu9JqnZ-1639493777651)(imgs/1616577612042.png)][外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jAn7ebCi-1639493777652)(imgs/1616577631853.png)]

根據課程編號查詢課程時,同時查詢選擇了這門課程的學生

StudentCourse
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DIVBZMjd-1639493777652)(imgs/1616577675018.png)][外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9Y5IQBNu-1639493777653)(imgs/1616577785188.png)]
連接查詢映射配置
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZEw21kXy-1639493777653)(imgs/1616578573302.png)]
子查詢映射配置
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-cJXyjnVq-1639493777654)(imgs/1616579097777.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZO9RVUrd-1639493777654)(imgs/1616579157655.png)]

十二、動態SQL

交友網:珍愛網、百合網 篩選心儀對象 性別 年齡 城市 身高

電商:淘寶、京東 篩選商品 羽毛球拍 品牌 價格

? 方江鵬 性別 女 select * from members where gender=‘女’

? 羅彪 性別 女 年齡 18-23 select * from members where gender=‘女’ and age >=18 and age <=23

? 張三 年齡 城市 select * from members where age >=18 and age <=23 and city=’’

用戶的篩選條件不同,我們完成篩選執行的SQL也不一樣;我們可以通過窮舉來一一的完成不同條件的篩選,但是這種實現思路過于繁瑣和復雜,MyBatis就提供了動態SQL的配置方式來實現多條件查詢。

12.1 什么是動態SQL?

根據查詢條件動態完成SQL的拼接

12.2 動態SQL使用案例

案例:心儀對象搜索

12.2.1 創建數據表
create table members(member_id int primary key auto_increment,member_nick varchar(20) not null unique,member_gender char(2) not null,member_age int not null,member_city varchar(30) not null
);
12.2.2 創建實體類
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Member {private int memberId;private String memberNick;private String memberGender;private int memberAge;private String memberCity;
}
12.2.3 創建DAO接口

在DAO接口中定義一個多條件查詢的方法

public interface MemberDAO {//在多條件查詢中,如果查詢條件不確定,可以直接使用HashMap作為參數//優點:無需單獨定義傳遞查詢條件的類//缺點:當向Map中存放參數時,key必須與動態sql保持一致()//public List<Member> searchMember(HashMap<String,Object> params);// 也可以定義專門用于存放查詢條件的實體類存放參數//優點:設置參數時無需關注屬性名//缺點:需要單獨定義一個類來封裝參數public List<Member> searchMember(MemberSearchCondition params);
}

12.3 if

<resultMap id="memberMap" type="Member"><id column="member_id" property="memberId"/><result column="member_nick" property="memberNick"/><result column="member_gender" property="memberGender"/><result column="member_age" property="memberAge"/><result column="member_city" property="memberCity"/>
</resultMap><select id="searchMember" resultMap="memberMap">select member_id,member_nick,member_gender,member_age,member_cityfrom memberswhere 1=1<if test="gender != null">  <!--gender 就是參數對象的屬性/參數Map的key-->and member_gender=#{gender}</if><if test="minAge != null">and member_age &gt;= #{minAge}   <!-- &gt; --></if><if test="maxAge != null">and member_age &lt;= #{maxAge}  <!-- &lt; --></if><if test="city != null">and member_city = #{city}</if>
</select>

測試

 @Test
public void testSearchMember() {HashMap<String,Object> params = new HashMap<String, Object>();params.put("gender","女");params.put("minAge",18);//params.put("maxAge",23);params.put("city","武漢");//-----------------------------------------------------------------------MemberSearchCondition params2 = new MemberSearchCondition();params2.setGender("女");//params2.setMinAge(21);//params2.setMaxAge(30);//params2.setCity("武漢");//==========================================================================MemberDAO memberDAO = MyBatisUtil.getMapper(MemberDAO.class);List<Member> members = memberDAO.searchMember(params2);for (Member m: members) {System.out.println(m);}
}

12.4 where

<select id="searchMember" resultMap="memberMap">select member_id,member_nick,member_gender,member_age,member_cityfrom members<where><if test="gender != null">  <!--gender 就是參數對象的屬性/參數Map的key-->and member_gender=#{gender}</if><if test="minAge != null">and member_age &gt;= #{minAge}   <!-- &gt; --></if><if test="maxAge != null">and member_age &lt;= #{maxAge}  <!-- &lt; --></if><if test="city != null">and member_city = #{city}</if></where>order by member_age
</select>

12.5 trim

<select id="searchMember" resultMap="memberMap">select member_id,member_nick,member_gender,member_age,member_cityfrom members<trim prefix="where" prefixOverrides="and | or" suffix="order by member_age"><if test="gender != null">  <!--gender 就是參數對象的屬性/參數Map的key-->and member_gender=#{gender}</if><if test="minAge != null">and member_age &gt;= #{minAge}   <!-- &gt; --></if><if test="maxAge != null">and member_age &lt;= #{maxAge}  <!-- &lt; --></if><if test="city != null">and member_city = #{city}</if></trim>
</select>

12.6 foreach

public interface MemberDAO {//查詢指定城市的會員public List<Member> searchMemberByCity(List<String> cities);
}
<select id="searchMemberByCity" resultMap="memberMap">select member_id,member_nick,member_gender,member_age,member_cityfrom members where member_city in<foreach collection="list" item="cityName" separator="," open="(" close=")">#{cityName}</foreach>
</select>

測試

 @Test
public void searchMemberByCity() {List<String> cities = new ArrayList<String>();cities.add("廈門");cities.add("宜昌");MemberDAO memberDAO = MyBatisUtil.getMapper(MemberDAO.class);List<Member> members = memberDAO.searchMemberByCity(cities);for (Member m: members) {System.out.println(m);}
}

十三、模糊查詢

案例:根據昵稱查詢會員信息(模糊匹配 like)

13.1 模糊查詢實現

13.1.1 DAO
public interface MemberDAO {//根據昵稱查詢用戶信息——模糊查詢// 模糊查詢需要使用${}取值,與sql進行拼接// 在使用${}時,即使只有一個參數也需要使用@Param注解聲明參數的key(非String對象參數可以不用聲明)public List<Member> searchMemberByNick(@Param("keyWord") String keyWord);}
13.1.2 映射文件
<!--如果參數時String類型,需要parameterType聲明參數類型-->
<select id="searchMemberByNick" parameterType="java.lang.String" resultMap="memberMap">select member_id,member_nick,member_gender,member_age,member_cityfrom memberswhere member_nick like '%${keyWord}%'
</select>
13.1.3 測試
@Test
public void testSearchMemberByNick(){MemberDAO memberDAO = MyBatisUtil.getMapper(MemberDAO.class);List<Member> members = memberDAO.searchMemberByNick("花");for (Member m: members) {System.out.println(m);}
}

13.2 #{}和${}的區別

  • ${key} 表示獲取參數,先獲取參數的值拼接到SQL語句中,再編譯執行SQL語句;可能引起SQL注入問題
  • #{key} 表示獲取參數,先完成SQL編譯(預編譯),預編譯之后再將獲取的參數設置到SQL與中 ,可以避免SQL注入問題

十四、MyBatis日志配置

MyBatis做為一個封裝好的ORM框架,其運行過程我們沒辦法跟蹤,為了讓開發者了解MyBatis執行流程及每個執行步驟所完成的工作,MyBatis框架本身支持log4j日志框架,對運行的過程進行跟蹤記錄。我們只需對MyBatis進行相關的日志配置,就可以看到MyBatis運行過程中的日志信息。

14.1 添加日志框架依賴

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>

14.2 添加日志配置文件

  • 在resources目錄下創建名為 log4j.properties文件
  • log4j.properties文件配置日志輸出的方式
# 聲明日志的輸出級別及輸出方式
log4j.rootLogger=DEBUG,stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# 定義日志的打印格式  %t 表示線程名稱  %5p 日志級別 %msg日志信息
log4j.appender.stdout.layout.ConversionPattern=[%t] %5p - %msg \:%m%n

14.3 日志信息的級別

在使用日志框架輸出日志信息的時候,會根據輸出的日志信息的重要程度分為5個級別

級別說明
DEBUG輸出調試信息
INFO輸出提示信息
WARN輸出警告信息
ERROR一般性錯誤信息
FATAL致命性錯誤信息

十五、配置數據庫連接池-整合Druid

MyBatis做為一個ORM框架,在進行數據庫操作時是需要和數據庫連接連接的,MyBatis支持基于數據庫連接池的連接創建方式。

當我們配置MyBatis數據源時,只要配置了dataSource標簽的type屬性值為POOLED時,就可以使用MyBatis內置的連接池管理連接。

如果我們想要使用第三方的數據庫連接池,則需進行自定義配置。

15.1 常見的連接池

  • DBCP
  • C3P0
  • Druid 性能也比較好,提供了比較便捷的監控系統
  • Hikari 性能最好
功能dbcpdruidc3p0HikariCP
是否支持PSCache
監控jmxjmx/log/httpjmx,logjmx
擴展性
sql攔截及解析支持
代碼簡單中等復雜簡單
更新時間2015.8.62015.10.102015.12.092015.12.3
特點依賴于common-pool阿里開源,功能全面歷史久遠,代碼邏輯復雜,且不易維護優化力度大,功能簡單,起源于boneCP
連接池管理LinkedBlockingDeque數組threadlocal+CopyOnWriteArrayList

15.2 添加Druid依賴

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.5</version>
</dependency>

15.3 創建Druid連接池工廠

public class DruidDataSourceFactory extends PooledDataSourceFactory {public DruidDataSourceFactory() {this.dataSource = new DruidDataSource();}
}

15.4 將DruidDataSourceFactory配置給MyBatis數據源

<environments default="mysql"><environment id="mysql"><transactionManager type="JDBC"></transactionManager><!--   POOLED 使用MyBatis內置的連接池實現   --><!--  mybatis需要一個連接池工廠,這個工廠可以產生數據庫連接池  PooledDataSourceFactory --><dataSource type="com.qfedu.utils.DruidDataSourceFactory"><property name="driverClass" value="${driver}"/><property name="jdbcUrl" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment>
</environments>

十六、MyBatis緩存

MyBatis是基于JDBC的封裝,使數據庫操作更加便捷;MyBatis除了對JDBC操作步驟進行封裝之外也對其性能進行了優化:

  • 在MyBatis引入緩存機制,用于提升MyBatis的檢索效率
  • 在MyBatis引入延遲加載機制,用于減少對數據庫不必要的訪問

16.1 緩存的工作原理

緩存,就是存儲數據的內存

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ANrr7onU-1639493777655)(imgs/1616654926110.png)]

16.2 MyBatis緩存

MyBatis緩存分為一級緩存和二級緩存

16.2.1 一級緩存

一級緩存也叫做SqlSession級緩存,為每個SqlSession單獨分配的緩存內存,無需手動開啟可直接使用;多個SqlSession的緩存是不共享的。

特性:

1.如果多次查詢使用的是同一個SqlSession對象,則第一次查詢之后數據會存放到緩存,后續的查詢則直接訪問緩存中存儲的數據;

2.如果第一次查詢完成之后,對查詢出的對象進行修改(此修改會影響到緩存),第二次查詢會直接訪問緩存,造成第二次查詢的結果與數據庫不一致;

3.當我們進行在查詢時想要跳過緩存直接查詢數據庫,則可以通過sqlSession.clearCache();來清除當前SqlSession的緩存;

4.如果第一次查詢之后第二查詢之前,使用當前的sqlsession執行了修改操作,此修改操作會使第一次查詢并緩存的數據失效,因此第二次查詢會再次訪問數據庫。

測試代碼:

@Test
public void testQueryMemberById(){SqlSession sqlSession1 = MyBatisUtil.getSqlSessionFactory().openSession();SqlSession sqlSession2 = MyBatisUtil.getSqlSessionFactory().openSession();MemberDAO memberDAO1 = sqlSession1.getMapper(MemberDAO.class);Member member1 = memberDAO1.queryMemberById(1);System.out.println(member1);member1.setMemberAge(99);sqlSession1.clearCache();System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");MemberDAO memberDAO2 = sqlSession1.getMapper(MemberDAO.class);Member member2 =memberDAO2.queryMemberById(1);System.out.println(member2);
}
16.2.2 兩次查詢與數據庫數據不一致問題

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-D5lZ6Fzq-1639493777655)(imgs/1616660132980.png)]

16.2.3 二級緩存

二級緩存也稱為SqlSessionFactory級緩存,通過同一個factory對象獲取的Sqlsession可以共享二級緩存;在應用服務器中SqlSessionFactory是單例的,因此我們二級緩存可以實現全局共享。

特性:

1.二級緩存默認沒有開啟,需要在mybatis-config.xml中的settings標簽開啟

2.二級緩存只能緩存實現序列化接口的對象

  • 在mybatis-config.xml開啟使用二級緩存
<settings><setting name="cacheEnabled" value="true"/>
</settings>
  • 在需要使用二級緩存的Mapper文件中配置cache標簽使用功能二級緩存
<cache/>
  • 被緩存的實體類實現序列化接口
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Member implements Serializable {private int memberId;private String memberNick;private String memberGender;private int memberAge;private String memberCity;
}
  • 測試
@Test
public void testQueryMemberById(){SqlSessionFactory factory =MyBatisUtil.getSqlSessionFactory();// 1.多個SqlSession對象必須來自于同一個SqlSessionFactorySqlSession sqlSession1 = factory.openSession(true);SqlSession sqlSession2 = factory.openSession(true);System.out.println(sqlSession1 == sqlSession2);MemberDAO memberDAO1 = sqlSession1.getMapper(MemberDAO.class);Member member1 = memberDAO1.queryMemberById(1);System.out.println(member1);sqlSession1.commit();  //2.第一次查詢之后執行sqlSession1.commit(),會將當前sqlsession的查詢結果緩存到二級緩存System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");MemberDAO memberDAO2 = sqlSession2.getMapper(MemberDAO.class);Member member2 =memberDAO2.queryMemberById(1);System.out.println(member2);
}

16.3 查詢操作的緩存開關

<select id="queryMemberById" resultMap="memberMap" useCache="false">select member_id,member_nick,member_gender,member_age,member_cityfrom memberswhere member_id=#{mid}
</select>

十七、延遲加載

延遲加載——如果在MyBatis開啟了延遲加載,在執行了子查詢(至少查詢兩次及以上)時,默認只執行第一次查詢,當用到子查詢的查詢結果時,才會觸發子查詢的執行;如果無需使用子查詢結果,則子查詢不會執行.

開啟延遲加載:

<resultMap id="classMap" type="Clazz"><id column="cid" property="classId"/><result column="cname" property="className"/><result column="cdesc" property="classDesc"/><collection property="stus" select="com.qfedu.dao.StudentDAO.queryStudentsByCid" column="cid" fetchType="lazy"/>
</resultMap><select id="queryClassByCid" resultMap="classMap">select cid,cname,cdescfrom classeswhere cid=#{cid}
</select>

測試代碼:

@Test
public void queryClassByCid() {ClassDAO classDAO = MyBatisUtil.getMapper(ClassDAO.class);Clazz clazz = classDAO.queryClassByCid(1);System.out.println(clazz.getClassName());System.out.println("-----------------------------------");System.out.println(clazz.getStus());
}

運行日志:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2B6mC1Gv-1639493777656)(imgs/1616663783657.png)]

練習任務

jsp+servlet+mybatis

商品信息的CRUD

  • 添加商品
  • 商品列表+分頁
  • 刪除商品
  • 修改商品
  • 商品詳情

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/450439.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450439.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450439.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

android studio : clang++.exe: error: invalid linker name in argument '-fuse-ld=bfd

公司jenkins上的C編譯器最近換成了clang&#xff0c;今天更新了代碼發現本地的C/C代碼用NDK編譯不過了&#xff0c;提示&#xff1a; “clang.exe: error: invalid linker name in argument -fuse-ldbfd” 解決辦法&#xff1a; 將Android.mk文件中的“LOCAL_LDFLAGS -fuse-ld…

Git知識點

一、Git簡介 1.1 項目的版本管理 在項目開發過程中&#xff0c;項目沒開發到一個節點就會對當前項目進行備份&#xff0c;這個備份就是項目的一個版本&#xff1b;當我們繼續開發一個階段后&#xff0c;再次進行備份&#xff0c;就生成新的版本——多個版本的集合就是項目的版…

(1)初始化項目

2019獨角獸企業重金招聘Python工程師標準>>> &#xff08;1&#xff09;初始化項目 1 使用vue-cli初始化項目 vue init webpack my-renren得到以下輸出&#xff1a; ? Project name my-renren ? Project description A Vue.js project ? Author neumeng <4048…

C語言變量

C語言二進制、八進制、十六進制詳解 什么是二制制? 在數學計算中&#xff0c;二進制計數系統的公分母是最小的&#xff0c;它以2為基數。你還記得在小學或中學時所學的不同的計數系統嗎?筆者在上小學時&#xff0c;曾在一堂數學課中學過以6為基數的計數系統&#xff1b;你先…

Spring Data JPA - 參考文檔 地址

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Spring Data JPA - 參考文檔 文檔地址

JS內置方法(Array)

concat() 用于連接兩個或多個數組&#xff0c;該方法不會改變現有的數組&#xff0c;而是返回被連接數組的一個副本。join() 把數組中的所有元素放入一個字符串&#xff0c;元素是通過指定的分隔符進行分隔的。若省略了分隔符參數&#xff0c;則使用逗號作為分隔符。push() 向…

模切ERP和免費OA系統是互相結合提高效率

模切ERP和免費OA系統是互相結合提高效率在模切行業中&#xff0c;模切ERP在管理上的作用占了很大的比重&#xff0c;但是免費OA在管理上的地位都不容忽視的。點晴OA的核心問題是如何提高日常的辦公效率問題。因此點晴OA系統里包含的功能是非常全面&#xff0c;如&#xff1a;辦…

maven知識點

一、Maven簡介 1.1 在項目中如何導入jar包&#xff1f; 下載jar包 &#xff08;mvn&#xff09;將下載的jar包拷貝到項目中&#xff08;WEB-INF/lib&#xff09;選擇jar文件–右鍵–Add as Library 1.2 傳統導入jar包的方式存在什么問題&#xff1f; 步驟多&#xff08;相對…

使用SpringBoot yml配置文件

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.上一次我們已經使用SpringBoot實現了一個簡單的HelloWord程序&#xff0c;辣么接下來我們簡單的使用一下他的yml格式的配置文件。 2.在…

軟件行業資訊

為什么只有設計師才能發明流行的新語言 先回顧一下知名編程語言的作者和創造時間&#xff1a;Fortran 語言&#xff0c;50年代&#xff0c;IBM 研究員&#xff1b;Lisp 語言&#xff0c;50年代&#xff0c;MIT 的教授和學生&#xff1b;C語言&#xff0c;70年代&#xff0c;貝爾…

spring知識點

一、Spring概述 1.1 web項目開發中的耦合度問題 在Servlet中需要調用service中的方法&#xff0c;則需要在Servlet類中通過new關鍵字創建Service的實例 public interface ProductService{public List<Product> listProducts(); }public class ProductServiceImpl1 imple…

Linux系統下的權限試題測試

不會做的留言&#xff0c;到時在發布答案&#xff01;一、 有兩個參賽團隊team1、team2&#xff0c;兩個團隊各3人, 這兩個團隊互相競爭&#xff0c;各需提交一份報告&#xff0c;每組成員可以修改自己團隊內的所有文件&#xff0c;且不能讓其他團隊的人修改自己的文件內容&…

電子科大軟件系統架構設計——軟件建模詳細設計

文章目錄 軟件建模詳細設計概述軟件建模詳細設計目標軟件建模詳細設計原則開閉原則里氏 (Liskov) 替換原則依賴倒置原則接口分離原則單一職責原則最少知識原則&#xff08;迪米特法則&#xff09;高內聚原則松耦合原則可重用原則 軟件建模詳細設計內容 UML 軟件靜態結構視圖建模…

YAML文件解析

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 YAML是“另一種標記語言”的外語縮寫,YAML 是一種比JSON&#xff08;json多層次{ 與 [ 會被搞暈的&#xff09;更直觀的表現形式&#xf…

120分鐘React快速掃盲教程

在教程開端先說些題外話&#xff0c;我喜歡在學習一門新技術或讀過一本書后&#xff0c;寫一篇教程或總結&#xff0c;既能幫助消化&#xff0c;也能加深印象和發現自己未注意的細節&#xff0c;寫的過程其實仍然是一個學習的過程。有個記錄的話&#xff0c;在未來需要用到相關…

springmvc知識點

一、SpringMVC概述 Spring MVC 是由Spring官方提供的基于MVC設計理念的web框架。 SpringMVC是基于Servlet封裝的用于實現MVC控制的框架&#xff0c;實現前端和服務端的交互。 1.1 SpringMVC優勢 嚴格遵守了MVC分層思想 采用了松耦合、插件式結構&#xff1b;相比較于我們封裝的…

spring @component的作用

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1、controller 控制器&#xff08;注入服務&#xff09; 2、service 服務&#xff08;注入dao&#xff09; 3、repository dao&#xff…

微信小程序 懸浮按鈕

2019獨角獸企業重金招聘Python工程師標準>>> 效果視頻 https://pan.baidu.com/s/1yfrDaG9YAX0--v0EA3awZA 布局需要按照圓形排列&#xff0c;所以我們需要計算每個點的坐標 代碼部分 <view styleposition:fixed; wx:for"{{list}}" wx:for-index"i…

C語言const關鍵字—也許該被替換為readolny

const 是constant 的縮寫&#xff0c;是恒定不變的意思&#xff0c;也翻譯為常量、常數等。很不幸&#xff0c;正是因為這一點&#xff0c;很多人都認為被const 修飾的值是常量。這是不精確的&#xff0c;精確的說應該是只讀的變量&#xff0c;其值在編譯時不能被使用&#xff…

dbus服務自啟動方法

Linux 一般發行版上 "/usr/share/dbus-1/services/"目錄就是dbus放service文件的地方。 需要自動啟動的服務器 就在這個目錄放一個 service文件&#xff0c;內容如下&#xff1a; $ cat /usr/share/dbus-1/services/dhcdbd.service [D-BUS Service] Namecom.redhat.…