MyBatis 深度解析:高效 Java 持久層框架實踐指南(基于 3.5.10)

一、MyBatis 核心架構與設計哲學

MyBatis 作為半自動 ORM 框架,核心設計目標是在靈活性開發效率之間取得平衡。與 Hibernate 等全自動 ORM 框架不同,MyBatis 允許開發者完全控制 SQL 編寫,同時通過映射機制減少重復代碼,特別適合復雜業務場景和性能敏感的系統。

1.1 核心優勢對比

特性傳統 JDBC全自動 ORM(如 Hibernate)MyBatis
SQL 控制粒度細粒度(完全手動)粗粒度(自動生成 SQL)中細粒度(手動編寫 + 映射)
學習成本高(需處理連接 / 結果集)高(需掌握 ORM 規則)中(聚焦 SQL 與映射)
性能優化空間低(依賴框架優化)高(可針對性優化 SQL)
適用場景底層工具開發簡單 CRUD 業務復雜查詢 / 性能敏感系統

1.2 架構核心組件

MyBatis 的核心流程圍繞以下組件展開:

  1. SqlSessionFactory:通過mybatis-config.xml加載配置,創建SqlSession實例。
    • 包含數據源(DataSource)、事務管理器(TransactionManager)、插件(Plugins)等全局配置。
  2. SqlSession:提供操作數據庫的接口(如selectOneinsert),維護一級緩存。
  3. Executor:執行 SQL 的核心引擎,支持三種模式:
    • Simple:默認模式,每次執行 SQL 創建新 Statement。
    • Reuse:重用 Statement 對象(適用于相同 SQL 多次執行)。
    • Batch:批量執行 SQL(適用于批量插入 / 更新)。
  4. MappedStatement:封裝單個 SQL 語句的映射信息(如idSQL語句參數類型結果映射)。

二、基礎配置與快速入門

2.1 依賴管理最佳實踐

Maven 標準配置
<dependencies><!-- MyBatis核心 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version></dependency><!-- 數據庫驅動(建議與數據庫版本嚴格匹配) --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><!-- 連接池(推薦HikariCP或Druid) --><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>5.0.1</version></dependency><!-- 與Spring整合時添加 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.7</version></dependency>
</dependencies>

2.2 核心配置文件詳解

<!-- mybatis-config.xml -->
<configuration><!-- 全局設置 --><settings><setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 駝峰命名自動映射 --><setting name="lazyLoadingEnabled" value="true"/> <!-- 開啟延遲加載 --><setting name="multipleResultSetsEnabled" value="false"/> <!-- 禁止多結果集(安全考慮) --></settings><!-- 環境配置(支持多環境切換) --><environments default="dev"><environment id="dev"><transactionManager type="JDBC"/> <!-- 使用JDBC事務 --><dataSource type="POOLED"> <!-- 池化數據源 --><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mydb?useSSL=false&amp;serverTimezone=UTC"/><property name="username" value="root"/><property name="password" value="123456"/><!-- HikariCP特有配置(池化數據源建議顯式配置) --><property name="maxPoolSize" value="10"/><property name="minIdle" value="2"/></dataSource></environment></environments><!-- 映射器注冊(推薦使用classpath*:mapper/**Mapper.xml通配符) --><mappers><mapper resource="mapper/UserMapper.xml"/><mapper class="com.example.mapper.OrderMapper"/> <!-- 注解映射器注冊方式 --></mappers>
</configuration>

2.3 初始化與核心操作

// 初始化SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 獲取SqlSession(默認自動提交為false)
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);// 單條查詢User user = mapper.selectUserById(1L);// 插入數據(需手動提交事務)User newUser = new User("Alice", 25);mapper.insertUser(newUser);sqlSession.commit(); // 提交事務
}

三、SQL 映射深度實踐

3.1 XML 映射與動態 SQL

基礎 CRUD 映射
<mapper namespace="com.example.mapper.UserMapper"><!-- 查詢(使用resultType自動映射簡單對象) --><select id="selectUserById" resultType="User">SELECT id, user_name AS name, user_age AS age FROM t_user WHERE id = #{id, jdbcType=BIGINT}</select><!-- 插入(使用useGeneratedKeys獲取自增主鍵) --><insert id="insertUser" useGeneratedKeys="true" keyProperty="id">INSERT INTO t_user (user_name, user_age)VALUES (#{name, jdbcType=VARCHAR}, #{age, jdbcType=INTEGER})</insert><!-- 更新(動態SET子句) --><update id="updateUser">UPDATE t_user<set><if test="name != null">user_name = #{name},</if><if test="age != null">user_age = #{age},</if>update_time = NOW()</set>WHERE id = #{id}</update>
</mapper>
復雜動態 SQL 場景
<select id="searchUsers" resultType="User">SELECT * FROM t_user<where><!-- 模糊查詢(注意%的拼接方式) --><if test="name != null and name != ''">user_name LIKE CONCAT('%', #{name}, '%')</if><!-- 范圍查詢 --><if test="minAge != null">AND user_age &gt;= #{minAge}</if><!-- 排序(通過OGNL表達式安全拼接字段) --><if test="orderByColumn in {'name', 'age', 'id'}">ORDER BY ${orderByColumn} ${orderByDirection}</if></where><!-- 分頁(建議使用PageHelper插件) --><if test="pageable != null">LIMIT #{pageable.offset}, #{pageable.pageSize}</if>
</select>

3.2 注解映射高級用法

public interface UserMapper {// 單參數查詢(自動識別參數名)@Select("SELECT * FROM t_user WHERE id = #{id}")User selectById(Long id);// 多參數查詢(必須使用@Param注解)@Select("SELECT * FROM t_user WHERE user_name = #{name} AND user_age = #{age}")User selectByNameAndAge(@Param("name") String name, @Param("age") Integer age);// 插入返回主鍵(通過@Options配置)@Insert("INSERT INTO t_user (user_name, user_age) VALUES (#{name}, #{age})")@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")int insert(@Param("user") User user);// 動態SQL注解(結合SqlProvider)@SelectProvider(type = UserSqlProvider.class, method = "buildSearchSql")List<User> search(@Param("query") UserQuery query);
}// SQLProvider類(動態拼接SQL)
public class UserSqlProvider {public String buildSearchSql(UserQuery query) {SQL sql = new SQL();sql.SELECT("id, user_name, user_age");sql.FROM("t_user");if (StringUtils.isNotBlank(query.getName())) {sql.WHERE("user_name LIKE CONCAT('%', #{query.name}, '%')");}if (query.getMinAge() != null) {sql.WHERE("user_age >= #{query.minAge}");}if (StringUtils.isNotBlank(query.getOrderBy())) {sql.ORDER_BY(query.getOrderBy());}return sql.toString();}
}

四、結果集映射與關聯查詢

4.1 基礎結果映射

<!-- 使用resultMap顯式映射(解決字段名與屬性名不匹配) -->
<resultMap id="userResultMap" type="User"><id column="user_id" property="id" jdbcType="BIGINT"/> <!-- 主鍵映射 --><result column="user_name" property="name" jdbcType="VARCHAR"/><result column="user_age" property="age" jdbcType="INTEGER"/><result column="create_time" property="createTime" jdbcType="TIMESTAMP"/> <!-- 駝峰映射示例 -->
</resultMap><select id="selectUserWithMap" resultMap="userResultMap">SELECT user_id, user_name, user_age, create_time FROM t_user WHERE id = #{id}
</select>

4.2 關聯對象映射

一對一關聯(使用 association)
<resultMap id="userWithDeptResultMap" type="User"><id column="user_id" property="id"/><result column="user_name" property="name"/><!-- 關聯部門對象(使用嵌套查詢) --><association property="department" column="dept_id" javaType="Department" select="selectDepartmentById"/>
</resultMap><select id="selectUserWithDept" resultMap="userWithDeptResultMap">SELECT user_id, user_name, dept_id FROM t_user WHERE id = #{id}
</select><select id="selectDepartmentById" resultType="Department">SELECT dept_id, dept_name FROM t_department WHERE dept_id = #{deptId}
</select>
一對多關聯(使用 collection)
<resultMap id="userWithRolesResultMap" type="User"><id column="user_id" property="id"/><result column="user_name" property="name"/><!-- 關聯角色集合(使用嵌套結果) --><collection property="roles" ofType="Role" columnPrefix="role_"><id column="role_id" property="id"/><result column="role_name" property="name"/></collection>
</resultMap><select id="selectUserWithRoles" resultMap="userWithRolesResultMap">SELECT u.user_id, u.user_name, r.role_id, r.role_name FROM t_user u LEFT JOIN t_user_role ur ON u.user_id = ur.user_id LEFT JOIN t_role r ON ur.role_id = r.role_id WHERE u.id = #{id}
</select>

五、高級特性與性能優化

5.1 緩存機制深度解析

一級緩存(SqlSession 級別)
  • 作用范圍:同一SqlSession內,默認開啟,無法關閉。
  • 失效場景
    1. 調用sqlSession.clearCache()手動清空緩存。
    2. 執行insert/update/delete操作(自動清空緩存)。
二級緩存(Mapper 級別)
<!-- 在Mapper中開啟二級緩存 -->
<cache eviction="LRU"        <!-- 淘汰策略:LRU(最近最少使用) -->flushInterval="60000"  <!-- 刷新間隔:60秒 -->size="512"            <!-- 緩存容量:512個對象 -->readOnly="true"/>      <!-- 是否只讀:true(適合只讀場景,性能更高) --><!-- 使用二級緩存(需在select語句中聲明useCache="true") -->
<select id="selectUserById" resultType="User" useCache="true">SELECT * FROM t_user WHERE id = #{id}
</select>

注意事項

  • 二級緩存跨SqlSession共享,需確保 POJO 可序列化(實現Serializable接口)。
  • 建議僅在讀多寫少的場景使用二級緩存,頻繁更新的表禁用緩存。

5.2 插件開發實戰

自定義 SQL 執行監控插件
@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class PerformanceInterceptor implements Interceptor {private static final Logger log = LoggerFactory.getLogger(PerformanceInterceptor.class);@Overridepublic Object intercept(Invocation invocation) throws Throwable {long start = System.currentTimeMillis();Object result = invocation.proceed();long cost = System.currentTimeMillis() - start;MappedStatement ms = (MappedStatement) invocation.getArgs()[0];String statementId = ms.getId();String sql = ms.getBoundSql(invocation.getArgs()[1]).getSql();if (cost > 1000) { // 記錄耗時超過1秒的SQLlog.warn("Slow SQL executed: {} Cost: {}ms\n{}", statementId, cost, sql);}return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}
}<!-- 在mybatis-config.xml中注冊插件 -->
<plugins><plugin interceptor="com.example.performance.PerformanceInterceptor"><!-- 插件參數配置 --><property name="slowSqlThreshold" value="500"/> <!-- 慢SQL閾值(毫秒) --></plugin>
</plugins>

5.3 批量操作優化

批量插入(Batch 模式)
try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);for (int i = 0; i < 1000; i++) {User user = new User("user_" + i, 20 + i);mapper.insertUser(user);if (i % 200 == 0) { // 每200條提交一次,避免內存溢出sqlSession.flushStatements();}}sqlSession.commit(); // 最終提交事務
}
批量更新(使用<foreach>標簽)
<update id="batchUpdateStatus">UPDATE t_userSET status = #{status}WHERE id IN<foreach collection="idList" item="id" open="(" separator="," close=")">#{id}</foreach>
</update>

六、與 Spring 整合最佳實踐

6.1 基于注解的整合配置

1. 配置類(替代 XML 配置)
@Configuration
@MapperScan(basePackages = "com.example.mapper") // 掃描Mapper接口
public class MyBatisConfig {@Bean@ConfigurationProperties(prefix = "spring.datasource") // 讀取application.yml中的數據源配置public DataSource dataSource() {return new HikariDataSource();}@Beanpublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/**/*.xml")); // 加載Mapper XML文件// 配置MyBatis全局屬性Configuration configuration = factoryBean.getObject().getConfiguration();configuration.setMapUnderscoreToCamelCase(true); // 開啟駝峰映射configuration.setLogImpl(StdOutImpl.class); // 開發環境打印SQL日志factoryBean.setConfiguration(configuration);return factoryBean.getObject();}@Beanpublic DataSourceTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource); // 配置事務管理器}
}

6.2 事務管理與 Spring 整合

聲明式事務配置
@Service
public class UserService {private final UserMapper userMapper;private final OrderMapper orderMapper;@Autowiredpublic UserService(UserMapper userMapper, OrderMapper orderMapper) {this.userMapper = userMapper;this.orderMapper = orderMapper;}// 使用@Transactional聲明事務(默認傳播行為:REQUIRED)@Transactionalpublic void createUserAndOrder(User user, Order order) {userMapper.insertUser(user); // 插入用戶order.setUserId(user.getId());orderMapper.insertOrder(order); // 插入訂單(與用戶操作在同一事務中)// 模擬異常回滾if (order.getAmount() <= 0) {throw new BusinessException("訂單金額不能為負數");}}
}// 全局異常處理器(回滾事務)
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(BusinessException.class)public ResponseEntity<String> handleBusinessException(BusinessException ex) {return ResponseEntity.badRequest().body(ex.getMessage());}
}
事務傳播行為示例
@Service
public class TransactionService {@Autowiredprivate UserService userService;@Autowiredprivate OrderService orderService;// 外層事務(REQUIRED)@Transactionalpublic void outerTransaction() {userService.updateUser(new User(1L, "Updated")); // 新增事務?取決于內層配置try {orderService.createOrder(new Order(1L, -100)); // 內層事務拋出異常} catch (Exception e) {// 外層可捕獲異常并決定是否回滾System.out.println("捕獲內層異常,手動回滾");TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}}// 內層事務(REQUIRES_NEW:新建獨立事務)@Transactional(propagation = Propagation.REQUIRES_NEW)public void createOrder(Order order) {orderMapper.insertOrder(order);if (order.getAmount() < 0) {throw new IllegalArgumentException("無效金額");}}
}

七、MyBatis 最佳實踐

7.1 SQL 編寫規范

避免的反模式
-- 反模式:使用SELECT *(性能差、耦合度高)
SELECT * FROM t_user-- 推薦:顯式指定字段
SELECT id, user_name, user_age FROM t_user-- 反模式:子查詢性能差
SELECT * FROM t_user WHERE id IN (SELECT user_id FROM t_order)-- 推薦:JOIN優化
SELECT u.* FROM t_user u JOIN t_order o ON u.id = o.user_id
動態 SQL 安全原則
<!-- 安全寫法:使用預編譯防止SQL注入 -->
<select id="findUserByName">SELECT * FROM t_user WHERE user_name = #{name}
</select><!-- 危險寫法:直接拼接用戶輸入(僅用于可信場景) -->
<select id="sortUsers">SELECT * FROM t_user ORDER BY ${sortColumn} ${sortDirection}<!-- 必須確保sortColumn和sortDirection為預定義值 -->
</select>

7.2 性能優化策略

分頁查詢優化
<!-- 物理分頁(推薦使用PageHelper插件) -->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.3.2</version>
</dependency>// 使用方式
PageHelper.startPage(pageNum, pageSize); // 開啟分頁
List<User> userList = userMapper.searchUsers(query);
PageInfo<User> pageInfo = new PageInfo<>(userList); // 獲取分頁信息
延遲加載與懶加載
<!-- 全局開啟延遲加載 -->
<settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/> <!-- 禁止激進加載(默認false) -->
</settings><!-- 關聯查詢使用延遲加載 -->
<association property="department" column="dept_id" javaType="Department" select="selectDepartmentById" lazy="true"/>
批量操作性能對比
操作方式單次插入 1000 條數據耗時優點缺點
單條插入~2000ms簡單直接網絡 IO 次數多
批量插入(XML)~200ms性能提升明顯需要拼接 SQL
批量插入(Batch)~150ms最優性能需手動管理事務批次

八、常見問題與解決方案

8.1 參數綁定失效問題

現象

org.apache.ibatis.exceptions.PersistenceException: 
Error querying database. Cause: org.apache.ibatis.binding.BindingException: 
Parameter 'name' not found. Available parameters are [0, 1, param1, param2]

原因:多參數未使用@Param注解標識。
解決

// 錯誤寫法(MyBatis無法識別參數名)
User selectUser(String name, Integer age);// 正確寫法(顯式指定參數名)
User selectUser(@Param("name") String name, @Param("age") Integer age);

8.2 結果映射類型不匹配

現象

org.apache.ibatis.type.TypeException: 
Could not set parameters for mapping: ParameterMapping{property='createTime', ...}
Cause: java.sql.SQLException: Invalid value for getLong() - '2023-10-01 12:00:00'

原因:數據庫字段類型(如 TIMESTAMP)與 Java 屬性類型(如String)不匹配。
解決

<!-- 顯式指定JDBC類型 -->
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" javaType="java.time.LocalDateTime"/>

8.3 二級緩存不生效

排查步驟

  1. 檢查 Mapper 是否開啟緩存:
    <cache/> <!-- 確保存在緩存聲明 -->
    
  2. 確認select語句是否啟用緩存:
    <select ... useCache="true"/> <!-- 默認為true,但需顯式聲明 -->
    
  3. 檢查 POJO 是否實現Serializable接口:
    public class User implements Serializable { ... }
    
  4. 確認是否執行了insert/update/delete操作(會清空二級緩存)。

九、MyBatis 3.5 + 新特性

9.1 注解式動態 SQL 增強

// 使用@SqlSource聲明動態SQL
public interface UserMapper {@Select({"<script>","SELECT * FROM t_user","<where>","<if test='name != null'>user_name LIKE CONCAT('%', #{name}, '%')</if>","<if test='age != null'>AND user_age &gt;= #{age}</if>","</where>","</script>"})List<User> search(@Param("name") String name, @Param("age") Integer age);
}

9.2 自動映射枚舉類型

<!-- 全局配置枚舉類型處理器 -->
<typeHandlers><typeHandler handler="org.apache.ibatis.type.EnumTypeHandler"/>
</typeHandlers>// 枚舉類
public enum UserStatus {ACTIVE(1, "活躍"),INACTIVE(0, "禁用");private final int code;private final String desc;// 構造方法與getter
}// 映射使用
<result column="status" property="status" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>

十、總結與學習資源

10.1 核心價值

MyBatis 的核心競爭力在于可控性靈活性

  • 適合復雜業務場景(如多表關聯查詢、動態報表)。
  • 便于優化 SQL 性能(如索引優化、分頁策略)。
  • 輕量級依賴(僅需 MyBatis 核心庫,無額外框架侵入)。

10.2 學習路徑建議

  1. 基礎階段:掌握 XML 映射、動態 SQL、結果集映射。
  2. 進階階段:深入緩存機制、插件開發、批量操作優化。
  3. 實戰階段:結合 Spring Boot/Spring Cloud 構建微服務,處理分布式事務場景。
  4. 源碼階段:閱讀 MyBatis 核心類(如ExecutorStatementHandler),理解底層執行邏輯。

10.3 推薦資源

  • 官方文檔:MyBatis 3 中文文檔
  • 書籍:《MyBatis 從入門到精通》《Java 持久層技術實戰》
  • 開源項目:MyBatis-Plus(增強工具包,簡化 CRUD)、TkMapper(通用 Mapper 工具)。

結語

MyBatis 通過將 SQL 編寫與業務邏輯解耦,在保持開發效率的同時提供了極高的性能優化空間,是企業級應用中持久層的首選方案。開發者需在實際項目中積累 SQL 優化經驗,結合業務場景合理使用緩存、批量操作和關聯映射,以充分發揮 MyBatis 的優勢。未來可進一步關注 MyBatis 與響應式編程(如 Reactive SQL)的整合,以及云原生場景下的持久層解決方案。

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

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

相關文章

二叉樹(二)

98.驗證二叉樹 中序遍歷二叉樹&#xff0c;每次遍歷存下當前節點的值&#xff0c;遍歷到下一個節點比較&#xff0c;根據二叉搜索樹的特性&#xff0c;左<中<右有&#xff1a; 如果當前值小于或等于上一個的值&#xff0c;說明不是二叉搜索樹 如果當前值大于上一個節點…

解決Vue3+uni-app導航欄高亮自動同步方案

路由跳轉自動識別導航高亮實現方法 以下代碼使用wd-tabbar組件實現路由跳轉時自動同步導航欄高亮狀態&#xff0c;適用于所有的Vue3uni-app項目。 請根據自身使用框架類型完成&#xff0c;也可根據我使用的UI組件進行完成地址如下&#xff1a; Tabbar 標簽欄 | Wot UI &#…

免費論文查重與AI檢測工具推薦

文章目錄 概要一、PaperPass二、PaperYY注意 概要 畢業季&#xff0c;總少不了查重這一步&#xff0c;甚至查 AI 率。推薦兩款免費查重AIGC檢測的工具。 論文免費查重查AI&#xff1a; https://paperpass.com/ https://www.paperyy.com/ 一、PaperPass 網址&#xff1a; ht…

4、ubuntu系統 | 文本和目錄操作函數

1、目錄操作函數 ls(列出目錄內容) 用途:列出指定目錄中的文件和子目錄。語法:ls [選項] [路徑]常用選項: -l:以長格式顯示文件詳細信息(權限、所有者、大小、時間等)。-a:顯示隱藏文件(以.開頭的文件)。-R:遞歸列出子目錄內容。# 列出當前目錄下的所有文件和子目…

C++--范圍for循環詳解

范圍 for 循環是 C11 引入的語法特性&#xff0c;用于簡化遍歷容器或數組元素的過程。它比傳統 for 循環更簡潔安全&#xff0c;特別適合初學者。以下是詳細講解&#xff1a; 基本語法 for (元素類型 變量名 : 容器/數組) {// 循環體&#xff08;使用變量名訪問當前元素&#…

RDMA簡介1之RDMA開發必要性

為了滿足大批量數據的采集、存儲與傳輸需求&#xff0c;越來越多的數據密集型應用如機器學習、雷達、金融風控、航空航天等選擇使用現場可編程邏輯門陣列作為數據采集前端硬件來實現高性能的數據采集系統。FPGA憑借其高靈活性、高并行能力及可高度定制化的特點&#xff0c;能夠…

xmake的簡易學習

文章目錄 1. xmake是什么2. 一個可執行程序3. 一個庫文件4. 遍歷文件用法5. 第三方庫3.1 系統安裝庫3.2 獨立庫 6. 后續 由于前一篇博客的最后說要做一些rknn的優化&#xff0c;其實這個工作很早就完成了&#xff0c;但是我是使用 xmake這個來做我的工程的構建的&#xff0c;不…

【ArcGIS微課1000例】0147:Geographic Imager6.2下載安裝教程

文章目錄 一、軟件功能二、下載地址三、安裝教程Geographic Imager地圖工具使Adobe Photoshop空間圖像可以快速高效地工作。它增加了導入,編輯,操作和導出地理空間圖像的工具,例如航空和衛星圖像。Geographic Imager Mac功能非常強大,擁有柵格數據輸出、投影信息修改、基于…

【 java 集合知識 第一篇 】

1.概念 1.1.集合與數組的區別 集合&#xff1a;長度不固定&#xff0c;動態的根據數據添加刪除改變長度&#xff0c;并且只能存入引用類型&#xff0c;讀取采用迭代器或其他方法 數組&#xff1a;長度固定&#xff0c;不可改變&#xff0c;既可以存入基本類型也可以存入引用…

嵌入式開發學習日志(linux系統編程--系統編程之 進程間通信IPC)Day32

一、引言 空間獨立&#xff0c;需要一些操作&#xff1b; 分為三大類&#xff1a; 1、古老的通信方式 無名管道 有名管道 信號 2、IPC對象通信 system v BSD suse fedora kernel.org 消息隊列(用的相對少&#xff0c;這里不討論) …

metersphere不同域名的參數在鏈路測試中如何傳遞?

域名1&#xff1a;https://api.domain1.com 域名2&#xff1a;https://api.domain2.com 域名1的返回參數stteid會作為域名2的入參 步驟&#xff1a; 1&#xff09;先在metersphere—接口測試—接口定義中創建域名1和域名2的接口 2&#xff09;接口創建好后&#xff0c;在接口測…

使用Process Explorer、System Informer(Process Hacker)和Windbg工具排查軟件高CPU占用問題

目錄 1、問題現象 2、使用Process Explorer和System Informer&#xff08;該工具原先叫Process Hacker&#xff09;查看占用CPU高的線程 3、使用System Informer工具時發現了一個關鍵細節 4、將Windbg附加到軟件進程上&#xff0c;根據System Informer中顯示的線程id到Wind…

Linux(線程概念)

目錄 一 虛擬地址到物理地址的轉換 1. 操作系統如何管理物理內存&#xff1a; 2. 下面來談談虛擬地址如何轉換到物理地址&#xff1a; 3. 補充字段&#xff1a; 二 Linux中的線程 1. 先來說說進程&#xff1a; 2. 線程&#xff1a; 3. 線程相比較于進程的優缺點&#x…

阿里云為何,一個郵箱綁定了兩個賬號

阿里云“幽靈賬號”之謎&#xff1a;同一個郵箱注銷后仍有兩個賬號&#xff1f;深度揭秘成因與終極解決方案&#xff01; 你是否曾在阿里云上使用同一個郵箱注冊過多個賬號&#xff0c;明明已經**“徹底”注銷了其中一個**&#xff0c;卻驚愕地發現系統里依然**“幽靈般”掛著…

動態規劃-數位DP

今天開始做關于數位DP的問題&#xff0c;首先對于數位DP來說&#xff0c;這類問題難度較大&#xff0c;比較難理解&#xff0c;所以博主也會盡量講的更加詳細一些&#xff0c;來幫助大家更好地理解這里的相關知識。 前置知識&#xff1a; 1.首先對于數位DP來說&#xff0c;主…

總覽四級考試

別被“四級”這個龐然大物嚇到&#xff01;我們一起拆解它&#xff1a;?? &#x1f4cd; ??核心認知&#xff1a;四級是一場策略性考試&#xff01;?? 它不考智商&#xff0c;考的是??基礎英語能力 考試技巧 時間管理??。基礎可以通過努力補&#xff0c;技巧可以…

BSRR對比BRR對比ODR

? 三種操作方式的本質區別 寄存器功能原子操作特點BSRR同時支持置位(1)和復位(0)?? 是單指令完成任意位操作&#xff0c;無競爭風險ODR直接讀寫輸出狀態? 否需"讀-改-寫"&#xff0c;多線程/中斷中需關中斷保護BRR只能復位(0)?? 是僅清零功能&#xff0c;無置…

職坐標精選嵌入式AI物聯網開源項目

隨著嵌入式、AI與物聯網技術的深度融合&#xff0c;開源生態已成為開發者構建智能硬件解決方案的核心驅動力。本文將從嵌入式實時操作系統、多模態AI數據集及物聯網接入平臺三大維度切入&#xff0c;系統性梳理技術選型要點與實踐路徑。在嵌入式領域&#xff0c;重點解析低功耗…

Ubuntu系統 | 本地部署ollama+deepseek

1、Ollama介紹 Ollama是由Llama開發團隊推出的開源項目,旨在為用戶提供高效、靈活的本地化大型語言模型(LLM)運行環境。作為Llama系列模型的重要配套工具,Ollama解決了傳統云服務對計算資源和網絡連接的依賴問題,讓用戶能夠在個人電腦或私有服務器上部署和運行如Llama 3等…

【數據庫】關系數據庫標準語言-SQL(金倉)下

4、數據查詢 語法&#xff1a; SELECT [ALL | DISTINCT] <目標列表達式> [,<目標列表達式>] … FROM <表名或視圖名>[, <表名或視圖名> ] … [ WHERE <條件表達式> ] [ GROUP BY <列名1> [ HAVING <條件表達式> ] ] [ ORDER BY <…