日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

后端学习 - MyBatis

發布時間:2023/12/4 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 后端学习 - MyBatis 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的 持久層框架

文章目錄

  • 一 基于配置文件的 MyBatis 搭建
    • 1 搭建過程(增刪改)
    • 2 查詢操作
    • 3 特殊操作
  • 二 MyBatis 獲取參數值的方式
    • 1 單個字面量類型的參數
    • 2 多個字面量類型的參數
    • 3 Map 類型的參數
    • 4 實體類類型的參數
    • 5 使用 @Param 注解的參數
  • 三 自定義查詢結果 resultMap
    • 1 處理表的字段和屬性的映射關系
    • 2 處理多對一關系
    • 3 處理一對多關系
  • 四 動態 SQL
    • 1 if 標簽
    • 2 where 標簽
    • 3 trim 標簽
    • 4 choose, when, otherwise 標簽
    • 5 foreach 標簽
    • 6 sql 標簽
  • 五 MyBatis 緩存
    • 1 一級緩存
    • 2 二級緩存
    • 3 查詢順序
  • 六 逆向工程


一 基于配置文件的 MyBatis 搭建

1 搭建過程(增刪改)

配置過程:核心配置文件通過配置 mappers 找到映射文件,映射文件通過全類名和方法名定位到具體的接口和方法

  • 創建 maven 工程,引入依賴
  • 在 src/main/resources 目錄下創建核心配置文件 mybatis-config.xml:核心配置文件主要用于配置連接數據庫的環境,以及 MyBatis 的全局配置信息(整合 Spring 之后,配置文件可以省略)
  • <?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.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/learn"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><!--引入UserMapper.xml的映射文件--><mappers><mapper resource="mappers/UserMapper.xml"/><!--其他映射文件...--></mappers> </configuration>
  • 創建實體類型,以及數據庫中對應的表
  • 創建 mapper 接口:mapper 接口相當于 dao,但是 mapper 僅僅是接口,不需要提供實現類,具體的 SQL 命令寫在 映射文件 xxxMapper.xml 中(xxx和類名保持一致)
  • 創建 MyBatis 映射文件,在對應的位置標注全類名和方法(兩個一致:mapper接口的全類名和映射文件的 namespace 保持一致 ,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的全類名--> <mapper namespace="hello.mapper.UserMapper"><!--對應的方法--><insert id="insertUser">insert into user values (null, "伍佰", "500", 50, "男", "500@gmail.com")</insert> </mapper>
  • 測試
  • @Testpublic void helloTest() throws IOException {//讀取MyBatis的核心配置文件InputStream is = Resources.getResourceAsStream("mybatis-config.xml");//創建SqlSessionFactoryBuilder對象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();//通過核心配置文件所對應的字節輸入流創建工廠類SqlSessionFactory,生產SqlSession對象SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);//創建SqlSession對象,此時通過SqlSession對象所操作的sql都必須手動提交或回滾事務//SqlSession sqlSession = sqlSessionFactory.openSession();//創建SqlSession對象,此時通過SqlSession對象所操作的sql都會自動提交SqlSession sqlSession = sqlSessionFactory.openSession(true);//通過代理模式創建UserMapper接口的代理實現類對象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//調用UserMapper接口中的方法,就可以根據UserMapper的全類名匹配元素文件,通過調用的方法名匹配映射文件中的SQL標簽,并執行標簽中的SQL語句int result = userMapper.insertUser();}

    2 查詢操作

    映射文件 UserMapper.xml 中,為了設置實體類和數據庫表的映射,查詢功能的標簽必須指定 resultType(自動映射,用于屬性名和表中字段名一致的情況) 或 resultMap(自定義映射,用于一對多 / 多對一 / 字段名和屬性名不一致 的情況) 屬性

    • 查詢單個對象(單個對象也可以使用 List)
    接口定義方法:User getUserById();映射文件:<select id="getUserById" resultType="hello.pojo.User">select * from user where id = 1</select>
    • 查詢多個對象
    接口定義方法:List<User> getAllUser();映射文件:<select id="getAllUser" resultType="hello.pojo.User">select * from user</select>

    3 特殊操作

    • 模糊查詢
    <select id="fuzzy" resultType="User">select * from user where username like "%"#{name}"%" </select>
    • 批量刪除:不能使用 #{ } 是因為它會自動添加單引號
    <!--int deleteMore(@Param("ids") String ids);--> <delete id="batchDelete">delete from user where id in (${ids}) <!--示例:delete from user where id in (1, 2, 3)--> </delete>

    二 MyBatis 獲取參數值的方式

    • #{ } 對應占位符賦值;${ } 對應字符串拼接,外側需要加單引號
    • 不關心接口中方法的形參命名

    1 單個字面量類型的參數

    • 可以以任意的名稱獲取參數的值,不在乎接口中的方法形參的名字,但最好見名知意
    接口方法: public interface ParamMapper {// 根據用戶名查詢用戶信息User getUserByName(String username); }映射文件: <select id="getUserByName" resultType="param.pojo.User">select * from user where username = #{notmatters}select * from user where username = '${notmatters}' <!--等價--> </select>

    2 多個字面量類型的參數

    • 接口中的方法參數為多個,MyBatis 會自動將這些參數放在一個 map 集合中(以arg0, arg1…為鍵,以參數為值 或 以 param1, param2…為鍵,以參數為值),通過鍵訪問參數
    接口方法: public interface ParamMapper {// 驗證登錄User checkLogin(String username, String password); }映射文件: <select id="checkLogin" resultType="param.pojo.User">select * from user where username = #{arg0} and password = #{arg1}select * from user where username = #{param1} and password = #{param2} <!--等價--> </select>

    3 Map 類型的參數

    • 方法參數為一個 Map 時,使用自定義的 key 訪問 value
    接口方法: public interface ParamMapper {// 驗證登錄 參數為MapUser checkLoginByMap(Map<String, Object> mapParam); }映射文件: <select id="checkLoginByMap" resultType="param.pojo.User">select * from user where username = #{usernameKey} and password = #{passwordKey} </select>測試: ... Map param = new HashMap<String, Object>(); param.put("usernameKey", "伍佰"); param.put("passwordKey", "500"); userMapper.checkLoginByMap(param);

    4 實體類類型的參數

    • 通過訪問實體類對象中的屬性名獲取屬性值
    接口方法: public interface ParamMapper {// 添加用戶int insertUser(User paramUser); }映射文件: <insert id="insertUser">insert into user values (#{id}, #{username}, #{password}, #{age}, #{sex}, #{email}) </insert>

    5 使用 @Param 注解的參數

    • 可以替代情況1和2
    • 作用是指定 map 的鍵:通過 @Param 注解標識接口中的方法參數,會將這些參數放在 map 集合中,以 @Param 注解的 value 屬性值為鍵,以參數為值,替換鍵 arg0, arg1…
    接口方法: public interface ParamMapper {// 驗證登錄 參數使用注解User checkLoginByAnnotation(@Param("u") String username, @Param("p") String password); }映射文件: <select id="checkLoginByAnnotation" resultType="param.pojo.User">select * from user where username = #{u} and password = #{p} </select>

    三 自定義查詢結果 resultMap

    • resultMap:設置自定義映射
      包含屬性:
      id:表示自定義映射的唯一標識
      type:查詢的數據要映射的實體類的類型

    • resultMap 的子標簽:
      id:設置主鍵的映射關系
      result:設置普通字段的映射關系
      association:設置多對一的映射關系
      collection:設置一對多的映射關系
      每個標簽包含屬性:
      property:設置映射關系中實體類中的屬性名
      column:設置映射關系中表中的字段名

    1 處理表的字段和屬性的映射關系

    • 若字段名和實體類中的屬性名不一致,則可以通過 resultMap 設置自定義映射
    • 所有映射需要全部設置
    • 略有臃腫,可以使用別名的方式,只對不一致的表字段起別名
      select id, user_name userName, password, age, sex from user where user_name like "%"#{mohu}"%"
    <resultMap id="userMap" type="param.pojo.User"><id property="id" column="id"></id><result property="userName" column="user_name"></result><result property="password" column="password"></result><result property="age" column="age"></result><result property="sex" column="sex"></result> </resultMap><select id="testFuzzy" resultMap="userMap">select * from user where user_name like "%"#{fuzzy}"%" </select>

    2 處理多對一關系

    示例:根據員工id,查詢員工信息和部門信息

    • POJO(省略 Lombok 注解)
    public class Employee {private Integer eid;private String ename;private Department department; }public class Department {private Integer did;private String dname; }
    • 接口方法
    public interface ResultMapMapper {Employee getEmpAndDept(@Param("eid") Integer eid);}
    • 映射文件:使用 association 子標簽后,左表 employee 可以訪問屬性 did;association 標簽需要指明屬性 javaType
    <mapper namespace="glad.mapper.ResultMapMapper"><resultMap id="myResultMap" type="glad.pojo.Employee"><id property="eid" column="eid"></id><result property="ename" column="ename"></result><association property="department" javaType="glad.pojo.Department"><id property="did" column="did"></id><result property="dname" column="dname"></result></association></resultMap><select id="getEmpAndDept" resultMap="myResultMap"><!--使用 association 后,employee 可以訪問屬性 did-->select * from employee left join department on employee.did = department.did where employee.eid = #{eid}</select> </mapper>
    • 查詢結果

    3 處理一對多關系

    示例:根據部門id,查詢其員工信息

    • POJO(省略 Lombok 注解)
    public class Employee {private Integer eid;private String ename;private Integer did; }public class Department {private Integer did;private String dname;List<Employee> emps; }
    • 接口方法
    public interface ResultMapMapper {Deptartment getDeptAndEmp(@Param("did") Integer did);}
    • 映射文件:使用 collection 標簽聲明類的 List 屬性,并設置標簽的 ofType 屬性(代表容器內元素的屬性)
    <mapper namespace="glad.mapper.ResultMapMapper"><resultMap id="myResultMap" type="glad.pojo.Department"><id property="did" column="did"></id><result property="dname" column="dname"></result><collection property="emps" ofType="glad.pojo.Employee"><id property="eid" column="eid"></id><result property="ename" column="ename"></result></collection></resultMap><select id="getDeptAndEmp" resultMap="myResultMap">select * from department left join employee on department.did = employee.did where department.did = #{did}</select> </mapper>

    四 動態 SQL

    1 if 標簽

    滿足指定條件時,才會將 if 標簽中的 SQL 加入

    • POJO:省略 Lombok 注解,和表中的屬性名以 X 區分,注意在映射文件的各處訪問的是表還是傳入的參數
    public class User {private Integer idX;private String usernameX;private String passwordX;private Integer ageX;private String sexX;private String emailX; }
    • 接口方法
    public interface DynamicMapper {// 根據任意信息查詢List<User> getInfo(User user);}
    • 映射文件:
      數據庫表的字段,和類的屬性名不一致時,使用 resultMap,否則查詢結果一直為 null
      為了保證格式正確,需要在 where 后加一個恒成立條件
    <mapper namespace="dynamic.mapper.DynamicMapper"><resultMap id="myResultMap" type="dynamic.pojo.User"><id property="idX" column="id"></id><result property="usernameX" column="username"></result><result property="passwordX" column="password"></result><result property="ageX" column="age"></result><result property="sexX" column="sex"></result><result property="emailX" column="email"></result></resultMap><select id="getInfo" resultMap="myResultMap">select * from user where 1 = 1<if test="idX != '' and idX != null">and id = #{idX}</if><if test="usernameX != '' and usernameX != null">and username = #{usernameX}</if><if test="passwordX != '' and passwordX != null">and password = #{passwordX}</if><if test="ageX != '' and ageX != null">and age = #{ageX}</if><if test="sexX != '' and sexX != null">and sex = #{sexX}</if><if test="emailX != null and emailX !=''">and email = #{emailX}</if></select> </mapper>

    2 where 標簽

    一般和 if 標簽結合使用:
    若 where 標簽中的 if 子標簽條件都不滿足,則 where 標簽沒有任何功能,即不會添加 where 關鍵字;
    若 where 標簽中的 if 子標簽條件滿足,則 where 標簽會自動添加 where 關鍵字,并將條件最前方多余的 and 去掉

    <select id="getEmpListByMoreTJ2" resultType="Emp">select * from t_emp<where><if test="ename != '' and ename != null">ename = #{ename}</if><if test="age != '' and age != null">and age = #{age}</if><if test="sex != '' and sex != null">and sex = #{sex}</if></where> </select>

    3 trim 標簽

    trim 用于去掉或添加標簽中的內容

    屬性作用
    prefix在 trim 標簽中的內容的前面添加某些內容
    prefixOverrides在 trim 標簽中的內容的前面去掉某些內容
    suffix在 trim 標簽中的內容的后面添加某些內容
    suffixOverrides在 trim 標簽中的內容的后面去掉某些內容
    • 映射文件
    <select id="getEmpListByMoreTJ" resultType="Emp">select * from t_emp<!--在以下部分的開頭添加where,末尾刪去and--><trim prefix="where" suffixOverrides="and"><if test="ename != '' and ename != null">ename = #{ename} and</if><if test="age != '' and age != null">age = #{age} and</if><if test="sex != '' and sex != null">sex = #{sex}</if></trim> </select>

    4 choose, when, otherwise 標簽

    choose 是 when 和 otherwise 的父標簽,組合使用的效果相當于 Java 的 if, else if, else

    • 映射文件
    <!--List<Emp> getEmpListByChoose(Emp emp);--> <select id="getEmpListByChoose" resultType="Emp">select * from t_emp<where><choose><when test="ename != '' and ename != null">ename = #{ename}</when><when test="age != '' and age != null">age = #{age}</when><when test="sex != '' and sex != null">sex = #{sex}</when><when test="email != '' and email != null">email = #{email}</when></choose></where> </select>

    5 foreach 標簽

    用于執行批量操作

    屬性作用
    collection設置要循環的數組或集合
    item表示集合或數組中的每一個數據
    separator設置元素之間的分隔符
    open設置 foreach 標簽中的內容的開始符
    close設置 foreach 標簽中的內容的結束符
    • 映射文件
    <!--int insertMoreEmp(@Param("emps") List<Emp> emps);--> <insert id="insertMoreEmp">insert into t_emp values<foreach collection="emps" item="emp" separator=",">(null,#{emp.ename},#{emp.age},#{emp.sex},#{emp.email},null)</foreach> </insert><!--int deleteMoreByArray(@Param("eids") int[] eids);--> <delete id="deleteMoreByArray">delete from t_emp where eid in<foreach collection="eids" item="eid" separator="," open="(" close=")">#{eid}</foreach> </delete>

    6 sql 標簽

    提取 SQL 語句的公共部分

    <sql id="empColumns">eid, ename, age, sex, did </sql>引用: select <include refid="empColumns"></include> from t_emp

    五 MyBatis 緩存

    1 一級緩存

    • 一級緩存是 SqlSession 級別的,通過同一個 SqlSession 查詢的數據會被緩存,下次查詢相同的數據,就會從緩存中直接獲取,不會從數據庫重新訪問
    • 使一級緩存失效的四種情況:
    • 不同的 SqlSession 對應不同的一級緩存
    • 同一個 SqlSession 但是查詢條件不同
    • 同一個 SqlSession 兩次查詢期間執行了任何一次增刪改操作
    • 同一個 SqlSession 兩次查詢期間手動清空了緩存

    2 二級緩存

    • 二級緩存是 SqlSessionFactory 級別,通過同一個 SqlSessionFactory 創建的 SqlSession 查詢的結果會被緩存;此后若再次執行相同的查詢語句,結果就會從緩存中獲取
    • 使二級緩存失效的情況:兩次查詢之間執行了任意的增刪改,會使一級和二級緩存同時失效
    • 開啟二級緩存的步驟:
    • 在核心配置文件中,設置全局配置屬性cacheEnabled=“true”,默認為true,不需要設置
    • 在映射文件中設置標簽 <cache>
    • 二級緩存必須在 SqlSession 關閉或提交之后有效:一個 SqlSession 寫入二級緩存,當第一個 SqlSession 關閉或提交后,供相同 SqlSessionFactory 創建的另一個 SqlSession 使用
    • 查詢的數據所轉換的實體類類型必須實現序列化的接口 Serializable

    3 查詢順序

    • 先查詢二級緩存,因為二級緩存中可能會有其他程序已經查出來的數據,可以拿來直接使用。
    • 如果二級緩存沒有命中,再查詢一級緩存
    • 如果一級緩存也沒有命中,則查詢數據庫
    • SqlSession 關閉之后,一級緩存中的數據會寫入二級緩存

    六 逆向工程

    逆向工程:先創建數據庫表,由框架負責根據數據庫表,反向生成 Java 實體類、Mapper 接口、Mapper 映射文件

  • 引入依賴、配置核心配置文件
  • <!-- 控制Maven在構建過程中相關配置 --><build><!-- 構建過程中用到的插件 --><plugins><!-- 具體插件,逆向工程的操作是以構建過程中插件形式出現的 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.0</version><!-- 插件的依賴 --><dependencies><!-- 逆向工程的核心依賴 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.4.0</version></dependency><!-- 數據庫連接池 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.2</version></dependency><!-- MySQL驅動 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.20</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: 執行生成的逆向工程的版本MyBatis3Simple: 生成基本的CRUDMyBatis3: 生成帶條件的CRUD--><context id="DB2Tables" targetRuntime="MyBatis3"><!-- 數據庫的連接信息 --><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/learn?serverTimezone=UTC"userId="root"password="123456"></jdbcConnection><!-- javaBean的生成策略--><javaModelGenerator targetPackage="mybatis.bean"targetProject=".\src\main\java"><property name="enableSubPackages" value="true" /><property name="trimStrings" value="true" /></javaModelGenerator><!-- SQL映射文件的生成策略 --><sqlMapGenerator targetPackage="mybatis.mapper"targetProject=".\src\main\resources"><property name="enableSubPackages" value="true" /></sqlMapGenerator><!-- Mapper接口的生成策略 --><javaClientGenerator type="XMLMAPPER"targetPackage="mybatis.mapper" targetProject=".\src\main\java"><property name="enableSubPackages" value="true" /></javaClientGenerator><!-- 逆向分析的表 --><!-- tableName設置為*號,可以對應所有表,此時不寫domainObjectName --><!-- domainObjectName屬性指定生成出來的實體類的類名 --><table tableName="employee" domainObjectName="Employee"/><table tableName="department" domainObjectName="Department"/></context> </generatorConfiguration>
  • 運行插件,生成的 xxExample 用于添加約束,具體使用方法見4

  • 執行 CRUD
  • public class MyTest {@Testpublic void reverseTest() throws IOException {// ...InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);SqlSession sqlSession = sqlSessionFactory.openSession(true);DepartmentMapper departmentMapper = sqlSession.getMapper(DepartmentMapper.class);// 使用QBC形式添加條件DepartmentExample departmentExample = new DepartmentExample();departmentExample.createCriteria().andDidEqualTo(1).andDnameEqualTo("保衛處");// 將之前添加的條件通過or拼接其他條件departmentExample.or().andDidIsNotNull();// 傳入條件,執行sqlSystem.out.println(departmentMapper.countByExample(departmentExample));} }

    總結

    以上是生活随笔為你收集整理的后端学习 - MyBatis的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。