MyBatis的緩存、逆向工程、使用PageHelper、使用PageHelper

一、MyBatis的緩存

緩存:cache

緩存的作用:通過減少IO的方式,來提高程序的執行效率。

mybatis的緩存:將select語句的查詢結果放到緩存(內存)當中,下一次還是這條select語句的話,直接從緩存中取,不再查數據庫。一方面是減少了IO。另一方面不再執行繁瑣的查找算法。效率大大提升。

mybatis緩存包括:

  • 一級緩存:將查詢到的數據存儲到SqlSession中。

  • 二級緩存:將查詢到的數據存儲到SqlSessionFactory中。

  • 或者集成其它第三方的緩存:比如EhCache【Java語言開發的】、Memcache【C語言開發的】等。

緩存只針對于DQL語句,也就是說緩存機制只對應select語句。

1.一級緩存

一級緩存默認是開啟的。不需要做任何配置。

原理:只要使用同一個SqlSession對象執行同一條SQL語句,就會走緩存。

模塊名:mybatis-010-cache

public interface CarMapper {/*** 根據id獲取Car信息。* @param id* @return*/Car selectById(Long id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="org.example1.mapper.CarMapper"><select id="selectById" resultType="Car">select * from t_car where id = #{id}</select></mapper>

Test

    @Testpublic void testSelectById(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);Car car1 = mapper1.selectById(33L);System.out.println(car1);CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);Car car2 = mapper2.selectById(33L);System.out.println(car2);sqlSession.commit();sqlSession.close();}

什么情況下不走緩存?

  • 第一種:不同的SqlSession對象。

  • 第二種:查詢條件變化了。

    @Testpublic void testSelectById() throws Exception{// 如果要獲取不同的SqlSession對象,不能使用以下代碼。//SqlSession sqlSession = SqlSessionUtil.openSession();SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);Car car1 = mapper1.selectById(33L);System.out.println(car1);CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);Car car2 = mapper2.selectById(33L);System.out.println(car2);sqlSession1.close();sqlSession2.close();}

一級緩存失效情況包括兩種:

  • 第一種:第一次查詢和第二次查詢之間,手動清空了一級緩存。

sqlSession.clearCache();
  • 第二種:第一次查詢和第二次查詢之間,執行了增刪改操作。【這個增刪改和哪張表沒有關系,只要有insert delete update操作,一級緩存就失效。】

    @Testpublic void testSelectById(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);Car car1 = mapper1.selectById(33L);System.out.println(car1);// 手動清空一級緩存sqlSession.clearCache();CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);Car car2 = mapper2.selectById(33L);System.out.println(car2);sqlSession.commit();sqlSession.close();}

CarMapper接口:寫的是在t_clazz表里插入數據

package org.example1.mapper;import org.apache.ibatis.annotations.Param;
import org.example1.pojo.Car;public interface CarMapper {/*** 保存班級信息* @param cid* @param cname* @return*/int insertClazz(@Param("cid") Integer cid, @Param("cname") String cname);}
 <insert id="insertClazz">insert into t_clazz values(#{cid},#{cname})</insert>

test

    @Testpublic void testSelectById(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);Car car1 = mapper1.selectById(33L);System.out.println(car1);// 在這里執行了INSERT DELETE UPDATE中的任意一個語句。并且和表沒有關系。CarMapper mapper = sqlSession.getMapper(CarMapper.class);mapper.insertClazz(2000, "高三三班");CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);Car car2 = mapper2.selectById(33L);System.out.println(car2);sqlSession.commit();sqlSession.close();}

2.二級緩存

二級緩存的范圍是SqlSessionFactory。 使用二級緩存需要具備以下幾個條件:

  1. <setting name="cacheEnabled" value="true"> 全局性地開啟或關閉所有映射器配置文件中已配置的任何緩存。默認就是true,無需設置。

  2. 在需要使用二級緩存的SqlMapper.xml文件中添加配置:<cache />

  3. 使用二級緩存的實體類對象必須是可序列化的,也就是必須實現java.io.Serializable接口

  4. SqlSession對象關閉或提交之后,一級緩存中的數據才會被寫入到二級緩存當中。此時二級緩存才可用。

測試二級緩存:

<cache/>
public class Car implements Serializable {
//......
}
    @Testpublic void testSelectById2() throws Exception{// 這里只有一個SqlSessionFactory對象。二級緩存對應的就是SqlSessionFactory。SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);// 這行代碼執行結束之后,實際上數據是緩存到一級緩存當中了。(sqlSession1是一級緩存。)Car car1 = mapper1.selectById2(33L);System.out.println(car1);// 如果這里不關閉SqlSession1對象的話,二級緩存中還是沒有數據的。// 這行代碼執行結束之后,實際上數據會緩存到一級緩存當中。(sqlSession2是一級緩存。)Car car2 = mapper2.selectById2(33L);System.out.println(car2);// 程序執行到這里的時候,會將sqlSession1這個一級緩存中的數據寫入到二級緩存當中。sqlSession1.close();// 程序執行到這里的時候,會將sqlSession2這個一級緩存中的數據寫入到二級緩存當中。sqlSession2.close();}

把sqlSession1的一級緩存中的數據會放到二級緩存當中

    @Testpublic void testSelectById2() throws Exception{// 這里只有一個SqlSessionFactory對象。二級緩存對應的就是SqlSessionFactory。SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);// 這行代碼執行結束之后,實際上數據是緩存到一級緩存當中了。(sqlSession1是一級緩存。)Car car1 = mapper1.selectById2(33L);System.out.println(car1);// 如果這里不關閉SqlSession1對象的話,二級緩存中還是沒有數據的。// 如果執行了這行代碼,sqlSession1的一級緩存中的數據會放到二級緩存當中。sqlSession1.close();// 這行代碼執行結束之后,實際上數據會緩存到一級緩存當中。(sqlSession2是一級緩存。)Car car2 = mapper2.selectById2(33L);System.out.println(car2);// 程序執行到這里的時候,會將sqlSession1這個一級緩存中的數據寫入到二級緩存當中。//sqlSession1.close();// 程序執行到這里的時候,會將sqlSession2這個一級緩存中的數據寫入到二級緩存當中。sqlSession2.close();}

二級緩存的失效:只要兩次查詢之間出現了增刪改操作。二級緩存就會失效。【一級緩存也會失效】

二級緩存的相關配置:

  1. eviction:指定從緩存中移除某個對象的淘汰算法。默認采用LRU策略。

    1. LRU:Least Recently Used。最近最少使用。優先淘汰在間隔時間內使用頻率最低的對象。(其實還有一種淘汰算法LFU,最不常用。)

    2. FIFO:First In First Out。一種先進先出的數據緩存器。先進入二級緩存的對象最先被淘汰。

    3. SOFT:軟引用。淘汰軟引用指向的對象。具體算法和JVM的垃圾回收算法有關。

    4. WEAK:弱引用。淘汰弱引用指向的對象。具體算法和JVM的垃圾回收算法有關。

  2. flushInterval:

    1. 二級緩存的刷新時間間隔。單位毫秒。如果沒有設置。就代表不刷新緩存,只要內存足夠大,一直會向二級緩存中緩存數據。除非執行了增刪改。

  3. readOnly:

    1. true:多條相同的sql語句執行之后返回的對象是共享的同一個。性能好。但是多線程并發可能會存在安全問題。

    2. false:多條相同的sql語句執行之后返回的對象是副本,調用了clone方法。性能一般。但安全。

  4. size:

    1. 設置二級緩存中最多可存儲的java對象數量。默認值1024。

3.MyBatis集成EhCache

集成EhCache是為了代替mybatis自帶的二級緩存。一級緩存是無法替代的。

mybatis對外提供了接口,也可以集成第三方的緩存組件。比如EhCache、Memcache等。都可以。

EhCache是Java寫的。Memcache是C語言寫的。所以mybatis集成EhCache較為常見,按照以下步驟操作,就可以完成集成:

第一步:引入mybatis整合ehcache的依賴。

<!--mybatis集成ehcache的組件-->
<dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.2.2</version>
</dependency>

第二步:在類的根路徑下新建echcache.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"updateCheck="false"><!--磁盤存儲:將緩存中暫時不使用的對象,轉移到硬盤,類似于Windows系統的虛擬內存--><diskStore path="e:/ehcache"/><!--defaultCache:默認的管理策略--><!--eternal:設定緩存的elements是否永遠不過期。如果為true,則緩存的數據始終有效,如果為false那么還要根據timeToIdleSeconds,timeToLiveSeconds判斷--><!--maxElementsInMemory:在內存中緩存的element的最大數目--><!--overflowToDisk:如果內存中數據超過內存限制,是否要緩存到磁盤上--><!--diskPersistent:是否在磁盤上持久化。指重啟jvm后,數據是否有效。默認為false--><!--timeToIdleSeconds:對象空閑時間(單位:秒),指對象在多長時間沒有被訪問就會失效。只對eternal為false的有效。默認值0,表示一直可以訪問--><!--timeToLiveSeconds:對象存活時間(單位:秒),指對象從創建到失效所需要的時間。只對eternal為false的有效。默認值0,表示一直可以訪問--><!--memoryStoreEvictionPolicy:緩存的3 種清空策略--><!--FIFO:first in first out (先進先出)--><!--LFU:Less Frequently Used (最少使用).意思是一直以來最少被使用的。緩存的元素有一個hit 屬性,hit 值最小的將會被清出緩存--><!--LRU:Least Recently Used(最近最少使用). (ehcache 默認值).緩存的元素有一個時間戳,當緩存容量滿了,而又需要騰出地方來緩存新的元素的時候,那么現有緩存元素中時間戳離當前時間最遠的元素將被清出緩存--><defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/></ehcache>

第三步:修改SqlMapper.xml文件中的<cache/>標簽,添加type屬性。

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
    @Testpublic void testSelectById2() throws Exception{// 這里只有一個SqlSessionFactory對象。二級緩存對應的就是SqlSessionFactory。SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);// 這行代碼執行結束之后,實際上數據是緩存到一級緩存當中了。(sqlSession1是一級緩存。)Car car1 = mapper1.selectById2(33L);System.out.println(car1);// 如果這里不關閉SqlSession1對象的話,二級緩存中還是沒有數據的。// 如果執行了這行代碼,sqlSession1的一級緩存中的數據會放到二級緩存當中。sqlSession1.close();// 這行代碼執行結束之后,實際上數據會緩存到一級緩存當中。(sqlSession2是一級緩存。)Car car2 = mapper2.selectById2(33L);System.out.println(car2);// 程序執行到這里的時候,會將sqlSession1這個一級緩存中的數據寫入到二級緩存當中。//sqlSession1.close();// 程序執行到這里的時候,會將sqlSession2這個一級緩存中的數據寫入到二級緩存當中。sqlSession2.close();}

二、MyBatis的逆向工程

所謂的逆向工程是:根據數據庫表逆向生成Java的pojo類,SqlMapper.xml文件,以及Mapper接口類等。

要完成這個工作,需要借助別人寫好的逆向工程插件。

思考:使用這個插件的話,需要給這個插件配置哪些信息?

  • pojo類名、包名以及生成位置。

  • SqlMapper.xml文件名以及生成位置。

  • Mapper接口名以及生成位置。

  • 連接數據庫的信息。

  • 指定哪些表參與逆向工程。

  • ......

1.逆向工程配置與生成

第一步:基礎環境準備

新建模塊:mybatis-011-generator 打包方式:jar

第二步:在pom中添加逆向工程插件

<!--定制構建過程-->
<build><!--可配置多個插件--><plugins><!--其中的一個插件:mybatis逆向工程插件--><plugin><!--插件的GAV坐標--><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.1</version><!--允許覆蓋--><configuration><overwrite>true</overwrite></configuration><!--插件的依賴--><dependencies><!--mysql驅動依賴--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency></dependencies></plugin></plugins>
</build>

第三步:配置generatorConfig.xml

該文件名必須叫做: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:生成的是基礎版,只有基本的增刪改查。MyBatis3:生成的是增強版,除了基本的增刪改查之外還有復雜的增刪改查。--><context id="DB2Tables" targetRuntime="MyBatis3Simple"><!--防止生成重復代碼--><plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/><commentGenerator><!--是否去掉生成日期--><property name="suppressDate" value="true"/><!--是否去除注釋--><property name="suppressAllComments" value="true"/></commentGenerator><!--連接數據庫信息--><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/jdbc"userId="root"password="abc123"></jdbcConnection><!-- 生成pojo包名和位置 --><javaModelGenerator targetPackage="org.example1.pojo" targetProject="src/main/java"><!--是否開啟子包--><property name="enableSubPackages" value="true"/><!--是否去除字段名的前后空白--><property name="trimStrings" value="true"/></javaModelGenerator><!-- 生成SQL映射文件的包名和位置 --><sqlMapGenerator targetPackage="org.example1.mapper" targetProject="src/main/resources"><!--是否開啟子包--><property name="enableSubPackages" value="true"/></sqlMapGenerator><!-- 生成Mapper接口的包名和位置 --><javaClientGeneratortype="xmlMapper"targetPackage="org.example1.mapper"targetProject="src/main/java"><property name="enableSubPackages" value="true"/></javaClientGenerator><!-- 表名和對應的實體類名--><table tableName="t_car" domainObjectName="Car"/></context>
</generatorConfiguration>

第四步:運行插件

2.測試逆向工程生成的是否好用

第一步:環境準備

  • 依賴:mybatis依賴、mysql驅動依賴、junit依賴、logback依賴

  • jdbc.properties

  • mybatis-config.xml

  • logback.xml

第二步:編寫測試程序

    @Testpublic void testSelectAll(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);List<Car> cars = mapper.selectAll();cars.forEach(car -> System.out.println(car));sqlSession.close();}@Testpublic void testDeleteByPrimaryKey(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);int count = mapper.deleteByPrimaryKey(33L);System.out.println(count);sqlSession.commit();sqlSession.close();}

    // CarExample類負責封裝查詢條件的。@Testpublic void testSelect(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);// 執行查詢// 1. 查詢一個Car car = mapper.selectByPrimaryKey(32L);System.out.println(car);// 2. 查詢所有(selectByExample,根據條件查詢,如果條件是null表示沒有條件。)List<Car> cars = mapper.selectByExample(null);cars.forEach(car1 -> System.out.println(car1));System.out.println("=========================================");// 3. 按照條件進行查詢// QBC 風格:Query By Criteria 一種查詢方式,比較面向對象,看不到sql語句。// 封裝條件,通過CarExample對象來封裝查詢條件//把where后面的條件封裝起來CarExample carExample = new CarExample();// 調用carExample.createCriteria()方法來創建查詢條件carExample.createCriteria().andBrandLike("帕薩特").andGuidePriceGreaterThan(new BigDecimal(20.0));// 添加orcarExample.or().andCarTypeEqualTo("燃油車");// 執行查詢List<Car> cars2 = mapper.selectByExample(carExample);cars2.forEach(car2 -> System.out.println(car2));sqlSession.close();}

三、MyBatis使用PageHelper

1.limit分頁

mysql的limit后面兩個數字:

  • 第一個數字:startIndex(起始下標。下標從0開始。)

  • 第二個數字:pageSize(每頁顯示的記錄條數)

假設已知頁碼pageNum,還有每頁顯示的記錄條數pageSize,第一個數字可以動態的獲取嗎?

  • startIndex = (pageNum - 1) * pageSize

所以,標準通用的mysql分頁SQL:

select * 
from tableName ...... 
limit (pageNum - 1) * pageSize, pageSize

使用mybatis應該怎么做?

模塊名:mybatis-012-page

package org.example1.mapper;import org.apache.ibatis.annotations.Param;
import org.example1.pojo.Car;import java.util.List;public interface CarMapper {/*** 分頁查詢* @param startIndex 起始下標。* @param pageSize 每頁顯示的記錄條數* @return*/List<Car> selectByPage(@Param("startIndex") int startIndex, @Param("pageSize") int pageSize);
}
    <select id="selectByPage" resultType="Car">select * from t_car limit #{startIndex},#{pageSize}</select>
    @Testpublic void testSelectByPage(){// 獲取每頁顯示的記錄條數int pageSize = 3;// 顯示第幾頁:頁碼int pageNum = 2;// 計算開始下標int startIndex = (pageNum - 1) * pageSize;SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);List<Car> cars = mapper.selectByPage(startIndex, pageSize);cars.forEach(car -> System.out.println(car));sqlSession.close();}

2.PageHelper插件

使用PageHelper插件進行分頁,更加的便捷。

第一步:引入依賴

<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.3.1</version>
</dependency>

第二步:在mybatis-config.xml文件中配置插件

typeAliases標簽下面進行配置:

<plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

第三步:編寫Java代碼

package org.example1.mapper;import org.apache.ibatis.annotations.Param;
import org.example1.pojo.Car;import java.util.List;public interface CarMapper {/*** 查詢所有的Car,通過分頁查詢插件PageHelper完成。* @return*/List<Car> selectAll();
    <select id="selectAll" resultType="Car">select * from t_car</select>
    @Testpublic void testSelectAll(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);// 一定一定一定要注意:在執行DQL語句之前。開啟分頁功能。int pageNum = 2;int pageSize = 3;PageHelper.startPage(pageNum, pageSize);List<Car> cars = mapper.selectAll();cars.forEach(car -> System.out.println(car));// 封裝分頁信息對象new PageInfo()// PageInfo對象是PageHelper插件提供的,用來封裝分頁相關的信息的對象。PageInfo<Car> carPageInfo = new PageInfo<>(cars, 3);System.out.println(carPageInfo);sqlSession.close();/*PageInfo{pageNum=2, pageSize=3, size=3, startRow=4, endRow=6, total=7, pages=3,list=Page{count=true, pageNum=2, pageSize=3, startRow=3, endRow=6, total=7, pages=3, reasonable=false, pageSizeZero=false}[Car{id=168, carNum='1204', brand='奧迪Q7', guidePrice=3.0, produceTime='2009-10-11', carType='燃油車'},Car{id=169, carNum='1205', brand='朗逸', guidePrice=4.0, produceTime='2001-10-11', carType='新能源'},Car{id=170, carNum='1206', brand='奔馳E300L', guidePrice=50.0, produceTime='2003-02-03', carType='新能源'}],prePage=1, nextPage=3, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true,navigatePages=3, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]}*/}

分頁信息

PageInfo{pageNum=2, pageSize=2, size=2, startRow=3, endRow=4, total=6, pages=3, list=Page{count=true, pageNum=2, pageSize=2, startRow=2, endRow=4, total=6, pages=3, reasonable=false, pageSizeZero=false}[Car{id=86, carNum='1234', brand='豐田霸道', guidePrice=50.5, produceTime='2020-10-11', carType='燃油車'}, Car{id=87, carNum='1234', brand='豐田霸道', guidePrice=50.5, produceTime='2020-10-11', carType='燃油車'}], prePage=1, nextPage=3, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true, navigatePages=5, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]
}

四、MyBatis的注解式開發

mybatis中也提供了注解式開發方式,采用注解可以減少Sql映射文件的配置。

當然,使用注解式開發的話,sql語句是寫在java程序中的,這種方式也會給sql語句的維護帶來成本。 官方是這么說的:

使用注解來映射簡單語句會使代碼顯得更加簡潔,但對于稍微復雜一點的語句,Java 注解不僅力不從心,還會讓你本就復雜的 SQL 語句更加混亂不堪。 因此,如果你需要做一些很復雜的操作,最好用 XML 來映射語句。

使用注解編寫復雜的SQL是這樣的:

原則:簡單sql可以注解。復雜sql使用xml。

模塊名:mybatis-013-annotation

打包方式:jar

依賴:mybatis,mysql驅動,junit,logback

配置文件:jdbc.properties、mybatis-config.xml、logback.xml

pojo:org.example1.pojo.Car

mapper接口:org.example1.mapper.CarMapper

1. @Insert

package org.example1.mapper;import org.apache.ibatis.annotations.*;
import org.example1.pojo.Car;public interface CarMapper {@Insert("insert into t_car values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})")int insert(Car car);}
    @Testpublic void testInsert(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Car car = new Car(null,"6666","豐田霸道",32.0,"2020-11-11","燃油車");int count = mapper.insert(car);System.out.println(count);sqlSession.commit();sqlSession.close();}

2.@Delete

package com.powernode.mybatis.mapper;import com.powernode.mybatis.pojo.Car;
import org.apache.ibatis.annotations.*;public interface CarMapper {@Delete("delete from t_car where id = #{id}")int deleteById(Long id);
}
   @Testpublic void testDeleteById(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);int count = mapper.deleteById(31L);System.out.println(count);sqlSession.commit();sqlSession.close();}

3.

3.@Update

package org.example1.mapper;import org.apache.ibatis.annotations.*;
import org.example1.pojo.Car;public interface CarMapper {@Update("update t_car set car_num=#{carNum},brand=#{brand},guide_price=#{guidePrice},produce_time=#{produceTime},car_type=#{carType} where id=#{id}")int update(Car car);
    @Testpublic void testUpdate(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Car car = new Car(17L,"6666","豐田霸道",32.0,"2020-11-11","燃油車");int count = mapper.update(car);System.out.println(count);sqlSession.commit();sqlSession.close();}

4.@Select

package org.example1.mapper;import org.apache.ibatis.annotations.*;
import org.example1.pojo.Car;public interface CarMapper {@Select("select * from t_car where id = #{id}")Car selectById(Long id);
    @Testpublic void testSelectById(){SqlSession sqlSession = SqlSessionUtil.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Car car = mapper.selectById(17L);System.out.println(car);sqlSession.close();}

    @Select("select * from t_car where id = #{id}")@Results({@Result(property = "id", column = "id"),@Result(property = "carNum", column = "car_num"),@Result(property = "brand", column = "brand"),@Result(property = "guidePrice", column = "guide_price"),@Result(property = "produceTime", column = "produce_time"),@Result(property = "carType", column = "car_type")})Car selectById(Long id);

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

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

相關文章

java中的JNI調用c庫

1. 簡單demo 如果是在某個項目中有包名就需要自己找ai問問去改寫下cmd命令去編譯執行等 java文件&#xff08;HelloJNI.java&#xff09; public class HelloJNI {// 聲明 native 方法public native void sayHello();// 加載本地庫static {System.loadLibrary("hello&quo…

人工智能:GPT技術應用與未來展望

GPT(Generative Pre-trained Transformer)作為自然語言處理領域的代表性技術,近年來在各行業的實際應用中展現出廣泛潛力。結合其技術特性與行業需求,以下是GPT的主要應用場景、案例分析及未來挑戰的總結: 一、核心應用領域與案例 文本生成與內容創作 自動化內容生產:GPT…

前端筆記-ECMAScript語法概覽

更多詳細可以查看1.1 ES6 教程 | 菜鳥教程 這里我將大概記錄ES與JS大概不一樣的部分&#xff0c;方便聯合記憶。 歷史與關系 ECMAScript&#xff1a;是一種由 Ecma 國際組織制定的腳本語言規范&#xff0c;它是 JavaScript 的標準化版本。ECMAScript 為 JavaScript 提供了語…

操作主機的管理

1.在AD林范圍內&#xff0c;有哪幾個操作主機角色 架構主機&#xff08;Schema Master&#xff09; 功能&#xff1a;負責整個AD林中所有對象和屬性的定義&#xff0c;是唯一可以更新目錄架構的DC。架構更新會從架構主機復制到目錄林中的所有其他域控制器。 作用范圍&#xf…

【Linux】網絡編程

目錄 端口號 網絡字節序 socket編程 接口 sockaddr結構 udp網絡程序 創建套接字 綁定 接收 發送 客戶端需要綁定嗎&#xff1f; 客戶端執行方法 本地環回地址 終端文件 代碼 tcp網絡程序 SOCK_STREAM 監聽 查詢網絡信息 獲取新連接 地址轉換函數 客戶端綁…

Go 語言中的select是做什么的

Go 語言中的 select 是做什么的 在 Go 語言中&#xff0c;select 語句是用于處理多個通道&#xff08;channel&#xff09;操作的一種控制結構。它類似于 switch 語句&#xff0c;但專門用于并發編程&#xff0c;允許 Goroutine 在多個通道上等待操作&#xff08;發送或接收&a…

智慧班牌系統解決方案,SaaS智慧電子班牌云平臺

智慧班牌系統解決方案 系統概述 智慧班牌是智慧校園建設不斷發展的產物&#xff0c;是教育信息化改革的載體。通過智慧班牌可以高效便捷傳遞各種知識信息和通知信息、及時反饋課堂信息、實現班級的透明化管理。智慧班牌將學生平安考勤、異常出勤情況及時反饋至家長、老師&…

利用大模型和聚類算法找出 Excel 文件中重復或相似度高的數據,并使用 FastAPI 進行封裝的詳細方案

以下是一個利用大模型和聚類算法找出 Excel 文件中重復或相似度高的數據,并使用 FastAPI 進行封裝的詳細方案: 方案流程 數據讀取:從 Excel 文件中讀取數據。文本向量化:使用大模型將文本數據轉換為向量表示。聚類分析:運用聚類算法對向量進行分組,將相似度高的數據歸為…

【Docker基礎】容器技術詳解:生命周期、命令與實戰案例

文章目錄 一、什么是容器&#xff1f;二、為什么需要容器三、容器的生命周期容器狀態容器OOM容器異常退出容器異常退出容器暫停 四、容器命令命令清單詳細介紹 五、容器操作案例容器的狀態遷移容器批量操作容器交互模式attached 模式detached 模式interactive 模式 容器 與 宿主…

Laravel 實現 隊列 發送郵件功能

一. 什么是隊列 在構建 Web 應用程序時&#xff0c;你可能需要執行一些任務&#xff0c;例如解析文件&#xff0c;發送郵件&#xff0c;大量的數據計算等等&#xff0c;這些任務在典型的 Web 請求期間需要很長時間才能執行。 慶幸的是&#xff0c;Laravel 可以創建在后臺運行…

flink Shuffle的總結

關于 ** ?5 種 Shuffle 類型** 的區別、使用場景及 Flink 版本支持的總結&#xff1a; * 注意:下面是問AI具體細節與整理學習 1. 核心區別 Shuffle 類型核心特點使用場景Flink 版本支持Pipelined Shuffle流式調度&#xff0c;純內存交換&#xff0c;低延遲&#xff08;毫秒級…

Git使用與管理

一.基本操作 1.創建本地倉庫 在對應文件目錄下進行&#xff1a; git init 輸入完上面的代碼&#xff0c;所在文件目錄下就會多一個名為 .git 的隱藏文件&#xff0c;該文件是Git用來跟蹤和管理倉庫的。 我們可以使用 tree 命令&#xff08;注意要先下載tree插件&#xff09…

計算機視覺——深度學習圖像處理中目標檢測平均精度均值(mAP)與其他常用評估指標

概述 平均精度均值&#xff08;mAP&#xff09;是目標檢測領域中最為流行且復雜的重要評估指標之一。它廣泛用于綜合總結目標檢測器的性能。許多目標檢測模型會輸出類似以下的參數結果&#xff1a; Average Precision (AP) [ IoU0.50:0.95 | area all | maxDets100 ] 0.3…

C語言中單鏈表操作:查找節點與刪除節點

一. 簡介 前面學習了C語言中創建鏈表節點&#xff0c;向鏈表中插入節點等操作&#xff0c;文章如下&#xff1a; C語言中單向鏈表&#xff1a;創建節點與插入新節點-CSDN博客 本文繼續學習c語言中對鏈表的其他操作&#xff0c;例如在鏈表中查找某個節點&#xff0c;刪除鏈表…

WePY 框架:小程序開發的“Vue式”利器!!!

WePY 框架&#xff1a;小程序開發的“Vue式”利器 &#x1f680; 哈嘍&#xff0c;大家好&#xff01;&#x1f44b; 今天我們要聊聊一個在微信小程序開發中大放異彩的框架——WePY&#xff01;它是什么&#xff1f;有什么特點&#xff1f;為啥值得一試&#xff1f;別急&#…

什么是微前端?有什么好處?有哪一些方案?

微前端&#xff08;Micro Frontends&#xff09; 微前端是一種架構理念&#xff0c;借鑒了微服務的思想&#xff0c;將一個大型的前端應用拆分為多個獨立、自治的子應用&#xff0c;每個子應用可以由不同團隊、使用不同技術棧獨立開發和部署&#xff0c;最終聚合為一個整體產品…

【家政平臺開發(33)】庫存管理模塊開發實戰:從基礎搭建到智能管控

本【家政平臺開發】專欄聚焦家政平臺從 0 到 1 的全流程打造。從前期需求分析,剖析家政行業現狀、挖掘用戶需求與梳理功能要點,到系統設計階段的架構選型、數據庫構建,再到開發階段各模塊逐一實現。涵蓋移動與 PC 端設計、接口開發及性能優化,測試階段多維度保障平臺質量,…

Mysql個人筆記

Mysql個人筆記 sql基礎書寫規則和種類種類書寫規則注釋規則啟動 DDL數據類型數據庫的操作useshowcreatedrop 表的操作useshowcreate創建表復制表 dropalter Mysql的存儲引擎 DMLselectselect語句like&#xff08;謂詞&#xff09;where聚合函數&#xff1a;關于nullgroup byexi…

【重裝系統】大白菜自制U盤裝機,備份C盤數據,解決電腦啟動黑屏/藍屏

1. 準備 U 盤 U 盤容量至少 8G&#xff0c;備份 U 盤的數據&#xff08;后期會格式化&#xff09; 2. 從微軟官網下載操作系統鏡像 https://www.microsoft.com/zh-cn/software-download/windows11 3. 下載安裝大白菜 https://www.alipan.com/s/33RVnKayUfY 4. 插入 U 盤&#…

各類神經網絡學習:(十)注意力機制(第2/4集),pytorch 中的多維注意力機制、自注意力機制、掩碼自注意力機制、多頭注意力機制

上一篇下一篇注意力機制&#xff08;第1/4集&#xff09;待編寫 一、pytorch 中的多維注意力機制&#xff1a; 在 N L P NLP NLP 領域內&#xff0c;上述三個參數都是 向量 &#xff0c; 在 p y t o r c h pytorch pytorch 中參數向量會組成 矩陣 &#xff0c;方便代碼編寫。…