MyBatis查询数据库入门学习<一>

news2024/11/15 8:34:01

目录

1.MyBatis 是什么?

MyBatis官网:mybatis – MyBatis 3 | 简介

2.为什么要学习 MyBatis?

3.怎么学MyBatis?

4.第⼀个MyBatis查询

4.1 创建数据库和表

4.2 添加MyBatis框架⽀持

4.2.1 ⽼项⽬添加MyBatis

 

4.2.2 新项⽬添加MyBatis

4.3 配置连接字符串和MyBatis

4.3.1 配置连接字符串

 4.3.2 配置 MyBatis 中的 XML 路径

4.4 添加业务代码

4.4.1 添加实体类

4.4.2 添加 mapper 接⼝

4.4.3 添加UserMapper.xml

4.4.4 添加 Service

4.4.5 添加 Controller

5.增、删、改操作

5.1 增加用户操作

 5.2 修改用户操作

5.3 删除用户操作

6.查询操作

6.1 单表查询

6.1.1 参数占位符 #{} 和 ${}

SQL 注入问题

6.1.2 ${} 优点

6.1.3 SQL 注入问题

6.1.4 like 查询


1.MyBatis 是什么?

MyBatis 是⼀款优秀的持久层框架,它⽀持⾃定义 SQL、存储过程以及⾼级映射。MyBatis 去除了⼏乎所有的 JDBC 代码以及设置参数和获取结果集的⼯作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接⼝和 Java POJO(Plain Old Java Objects,普通⽼式 Java 对象)为数据库中的记录。
简单来说 MyBatis 是更简单完成程序和数据库交互的⼯具,也就是更简单的操作和读取数据库⼯具。

MyBatis官网mybatis – MyBatis 3 | 简介

2.为什么要学习 MyBatis?

对于后端开发来说,程序是由以下两个重要的部分组成的:
1. 后端程序
2. 数据库

⽽这两个重要的组成部分要通讯,就要依靠数据库连接⼯具,那数据库连接⼯具有哪些?⽐如之前我学习的 JDBC,还有今天我将要介绍的 MyBatis,那已经有了 JDBC 了,为什么还要学习 MyBatis?
这是因为 JDBC 的操作太繁琐了,回顾⼀下 JDBC 的操作流程:
  • 1. 创建数据库连接池 DataSource
  • 2. 通过 DataSource 获取数据库连接 Connection
  • 3. 编写要执⾏带 ? 占位符的 SQL 语句
  • 4. 通过 Connection 及 SQL 创建操作命令对象 Statement
  • 5. 替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值
  • 6. 使⽤ Statement 执⾏ SQL 语句
  • 7. 查询操作:返回结果集 ResultSet,更新操作:返回更新的数量
  • 8. 处理结果集
  • 9. 释放资源

 JDBC 操作示例回顾

下⾯的⼀个完整案例,展示了通过 JDBC 的 API 向数据库中添加⼀条记录,修改⼀条记录,查询⼀条记录的操作。
-- 创建数据库
create database if not exists `library` default character set utf8mb4;
-- 使⽤数据库
use library;
-- 创建表
create table if not exists `soft_bookrack` (
 `book_name` varchar(32) NOT NULL,
 `book_author` varchar(32) NOT NULL,
 `book_isbn` varchar(32) NOT NULL primary key
) ;

以下是JDBC操作的具体实现代码

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SimpleJdbcOperation {
 private final DataSource dataSource;
 
 public SimpleJdbcOperation(DataSource dataSource) {
 this.dataSource = dataSource;
 }
 
 /**
 * 添加⼀本书
 */
 public void addBook() {
 Connection connection = null;
 PreparedStatement stmt = null;
 try {
 //获取数据库连接
 connection = dataSource.getConnection();
 //创建语句
 stmt = connection.prepareStatement(
 "insert into soft_bookrack (book_name, book_author, b
ook_isbn) values (?,?,?);"
 );
 //参数绑定
 stmt.setString(1, "Spring in Action");
 stmt.setString(2, "Craig Walls");
 stmt.setString(3, "9787115417305");
 //执⾏语句
 stmt.execute();
 } catch (SQLException e) {
 //处理异常信息
 } finally {
 //清理资源
 try {
 if (stmt != null) {
 stmt.close();
 }
 if (connection != null) {
 connection.close();
 }

 } catch (SQLException e) {
 //
 }
 }
 }
 
 /**
 * 更新⼀本书
 */
 public void updateBook() {
 Connection connection = null;
 PreparedStatement stmt = null;
 try {
 //获取数据库连接
 connection = dataSource.getConnection();
 //创建语句
 stmt = connection.prepareStatement(
 "update soft_bookrack set book_author=? where book_is
bn=?;"
 );
 //参数绑定
 stmt.setString(1, "张卫滨");
 stmt.setString(2, "9787115417305");
 //执⾏语句
 stmt.execute();
 } catch (SQLException e) {
 //处理异常信息
 } finally {
 //清理资源
 try {
 if (stmt != null) {
 stmt.close();
 }
 if (connection != null) {
 connection.close();
 }
 } catch (SQLException e) {
 //
 }
 }
 }
 
 /**
 * 查询⼀本书
 */
 public void queryBook() {
 Connection connection = null;
 PreparedStatement stmt = null;
 ResultSet rs = null;
 Book book = null;
 try {
 //获取数据库连接
 connection = dataSource.getConnection();
 //创建语句
 stmt = connection.prepareStatement(
 "select book_name, book_author, book_isbn from soft_b
ookrack where book_isbn =?"
 );
 //参数绑定
 stmt.setString(1, "9787115417305");
 //执⾏语句
 rs = stmt.executeQuery();
 if (rs.next()) {
 book = new Book();
 book.setName(rs.getString("book_name"));
 book.setAuthor(rs.getString("book_author"));
 book.setIsbn(rs.getString("book_isbn"));
 }
 System.out.println(book);
 } catch (SQLException e) {
 //处理异常信息
 } finally {
 //清理资源
 try {
 if (rs != null) {
 rs.close();
 }
 if (stmt != null) {
 stmt.close();
 }
 if (connection != null) {
 connection.close();
 }
 } catch (SQLException e) {
 //
 }
 }
 }
 
 public static class Book {
 private String name;
 private String author;
 private String isbn;
 //省略 setter getter ⽅法
 }
}
从上述代码和操作流程可以看出,对于 JDBC 来说,整个操作⾮常的繁琐,对于程序员来说非常的麻烦,我们不但要拼接每⼀个参数,⽽且还要按照模板代码的⽅式,⼀步步的操作数据库,并且在每次操作完,还要⼿动关闭连接等,⽽所有的这些操作步骤都需要在每个⽅法中重复书写。于是我们就想,那有没有⼀种⽅法,可以更简单、更⽅便的操作数据库呢?
答案是肯定的,这就是要学习 MyBatis 的真正原因,它可以帮助我们更⽅便、更快速的操作数据库。

3.怎么学MyBatis?

MyBatis 学习只分为两部分:
配置 MyBatis 开发环境;
使⽤ MyBatis 模式和语法操作数据库。

4.第⼀个MyBatis查询

开始搭建 MyBatis 之前,我们先来看⼀下 MyBatis 在整个框架中的定位,框架交互流程图:

MyBatis 也是⼀个 ORM 框架 ORM(Object Relational Mapping),即对象关系映射
在⾯向对象编程语⾔中,将关系型数据库中的数据与对象建⽴起映射关系,进⽽⾃动的完成数据与对象的互相转换:
1. 将输⼊数据(即传⼊对象)+SQL 映射成原⽣ SQL
2. 将结果集映射为返回对象,即输出对象

 ORM 把数据库映射为对象:

数据库表(table)--> 类(class)
记录(record,⾏数据)--> 对象(object)
字段(field) --> 对象的属性(attribute)

⼀般的 ORM 框架,会将数据库模型的每张表都映射为⼀个 Java 类。
也就是说使⽤ MyBatis 可以像操作对象⼀样来操作数据库中的表,可以实现对象和数据库表之间
的转换,接下来我们来看 MyBatis 的使⽤吧。

4.1 创建数据库和表

接下来我们要实现的功能是:使⽤ MyBatis 的⽅式来读取⽤户表中的所有⽤户,我们使⽤个⼈博
客的数据库和数据包,具体 SQL 如下。
-- 创建数据库
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8mb4;
-- 使⽤数据数据
use mycnblog;
-- 创建表[⽤户表]
drop table if exists userinfo;
create table userinfo(
 id int primary key auto_increment,
 username varchar(100) not null,
 password varchar(32) not null,
 photo varchar(500) default '',
 createtime datetime default now(),
 updatetime datetime default now(),
 `state` int default 1
) default charset 'utf8mb4';
-- 创建⽂章表

drop table if exists articleinfo;
create table articleinfo(
 id int primary key auto_increment,
 title varchar(100) not null,
 content text not null,
 createtime datetime default now(),
 updatetime datetime default now(),
 uid int not null,
 rcount int not null default 1,
 `state` int default 1
)default charset 'utf8mb4';

-- 创建视频表
drop table if exists videoinfo;
create table videoinfo(
 vid int primary key,
 `title` varchar(250),
 `url` varchar(1000),
createtime datetime default now(),
updatetime datetime default now(),
 uid int
)default charset 'utf8mb4';
-- 添加⼀个⽤户信息

INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`,
`createtime`, `updatetime`, `state`) VALUES
(1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1)
;
-- ⽂章添加测试数据
insert into articleinfo(title,content,uid)
 values('Java','Java正⽂',1);
 
-- 添加视频
insert into videoinfo(vid,title,url,uid) values(1,'java title','http://ww
w.baidu.com',1);

4.2 添加MyBatis框架⽀持

添加 MyBatis 框架⽀持分为两种情况:⼀种情况是对⾃⼰之前的 Spring 项⽬进⾏升级,另⼀种情况是创建⼀个全新的 MyBatis 和 Spring Boot 的项⽬

4.2.1 ⽼项⽬添加MyBatis

如果是在⽼项⽬中新增功能,添加框架⽀持:
<!-- 添加 MyBatis 框架 -->
<dependency>
 <groupId>org.mybatis.spring.boot</groupId>
 <artifactId>mybatis-spring-boot-starter</artifactId>
 <version>2.1.4</version>
</dependency>
<!-- 添加 MySQL 驱动 -->
<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>5.1.38</version>
 <scope>runtime</scope>
</dependency>
添加了 MyBatis 之后,为什么还需要添加 MySQL 驱动呢?
MyBatis 就像⼀个平台(类似京东),⽽数据库相当于商家有很多种,不⽌有 MySQL,还有 SQL
Server、DB2 等等.....因此这两个都是需要添加的。
扩展:在⽼项⽬中快速添加框架,跟简单的操作⽅式是使⽤EditStarters插件

EditStarters 插件的使⽤⽅法:

搜索“MyBatis”添加即可:

4.2.2 新项⽬添加MyBatis

如果是新项⽬创建 Spring Boot 项⽬的时候添加引⽤就可以了,如下图所示:

4.3 配置连接字符串和MyBatis

此步骤需要进⾏两项设置,数据库连接字符串设置和 MyBatis 的 XML ⽂件配置。

4.3.1 配置连接字符串

如果是application.yml添加如下内容

# 数据库连接配置
spring:
 datasource:
 url: jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL
=false
 username: root
 password: 123456
 driver-class-name: com.mysql.cj.jdbc.Driver
注意事项:
如果使⽤ mysql-connector-java 是 5.x 之前的使⽤的是“ com.mysql.jdbc.Driver ” ,如果是⼤于 5.x 使⽤的是“ com.mysql.cj.jdbc.Driver ” 。

 4.3.2 配置 MyBatis 中的 XML 路径

MyBatis 的 XML 中保存是查询数据库的具体操作 SQL,配置如下:
# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
mybatis:
 mapper-locations: classpath:mapper/**Mapper.xml

4.4 添加业务代码

下⾯按照后端开发的⼯程思路,也就是下⾯的流程来实现 MyBatis 查询所有⽤户的功能:

4.4.1 添加实体类

先添加用户的实体类:

import lombok.Data;
import java.util.Date;
@Data
public class User {
 private Integer id;
 private String username;
 private String password;
 private String photo;
 private Date createTime;
 private Date updateTime;
}

4.4.2 添加 mapper 接⼝

数据持久层的接⼝定义:
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
 public List<User> getAll();
}

此处引用ibatis和mybatis的区别博客http://t.csdn.cn/oVVj5

4.4.3 添加UserMapper.xml

数据持久层的实现,mybatis的固定xml格式:

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybati
s.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper"> 
</mapper>
UserMapper.xml 查询所有⽤户的具体实现 SQL:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybati
s.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
 <select id="getAll" resultType="com.example.demo.model.User">
 select * from userinfo
 </select>
</mapper>
以下是对以上标签的说明:
<mapper>标签:需要指定 namespace 属性,表示命名空间,值为 mapper 接⼝的全限定
名,包括全包名.类名。
<select>查询标签:是⽤来执⾏数据库的查询操作的:
id:是和 Interface(接⼝)中定义的⽅法名称⼀样的,表示对接⼝的具体实现⽅法。
resultType:是返回的数据类型,也就是开头我们定义的实体类。

4.4.4 添加 Service

服务层实现代码如下:
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UserService {
 @Resource
 private UserMapper userMapper;
 public List<User> getAll() {
 return userMapper.getAll();
 }
}

4.4.5 添加 Controller

控制器层的实现代码如下:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/u")
public class UserController {
 @Resource
 private UserService userService;
 @RequestMapping("/getall")
 public List<User> getAll(){
 return userService.getAll();
 }
}
以上代码写完,整个 MyBatis 的查询功能就实现完了,接下来使⽤ postman 来测试⼀下。

5.增、删、改操作

接下来,我们来实现⼀下⽤户的增加、删除和修改的操作,对应使⽤ MyBatis 的标签如下:
  • <insert>标签:插⼊语句
  • <update>标签:修改语句
  • <delete>标签:删除语句
具体实现如下。

5.1 增加用操作

controller 实现代码:

@RequestMapping(value = "/add",method = RequestMethod.POST)
public Integer add(@RequestBody User user){
 return userService.getAdd(user);
}
mapper interface:
Integer add(User user);
mapper.xml
<insert id="add">
 insert into userinfo(username,password,photo,state)
 values(#{username},#{password},#{photo},1)
</insert>

Postman添加访问:

默认情况下返回的是受影响的⾏数,如上图所示,⽤到的 json 数据如下:
{"username":"mysql","password":"mysql","photo":"img.png"}
特殊的添加:返回⾃增 id
默认情况下返回的是受影响的⾏号,如果想要返回⾃增 id,具体实现如下。
controller 实现代码:
@RequestMapping(value = "/add2", method = RequestMethod.POST)
public Integer add2(@RequestBody User user) {
 userService.getAdd2(user);
 return user.getId();
}
mapper 接⼝:
@Mapper
public interface UserMapper {
 // 添加,返回⾃增id
 void add2(User user);
}
mapper.xml 实现如下:
<!-- 返回⾃增id -->
<insert id="add2" useGeneratedKeys="true" keyProperty="id">
 insert into userinfo(username,password,photo,state)
 values(#{username},#{password},#{photo},1)
</insert>
  • useGeneratedKeys:这会令 MyBatis 使⽤ JDBC 的 getGeneratedKeys ⽅法来取出由数据 库内部⽣成的主键(⽐如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的⾃动 递增字段),默认值:false。
  • keyColumn:设置⽣成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列 不是表中的第⼀列的时候,是必须设置的。如果⽣成列不⽌⼀个,可以⽤逗号分隔多个属性 名称。
  • keyProperty:指定能够唯⼀识别对象的属性,MyBatis 会使⽤ getGeneratedKeys 的返回 值或 insert 语句的 selectKey ⼦元素设置它的值,默认值:未设置(unset)。如果⽣成列 不⽌⼀个,可以⽤逗号分隔多个属性名称。

postman 返回结果:

 5.2 修改用户操作

controller:

 /** 修改操作
 *
 * @param id
 * @param name
 * @return
 */
 @RequestMapping("/update")
 public Integer update(Integer id, String name) {
 return userService.update(id, name);
 }
mapper.xml 实现代码:
<update id="update">
 update userinfo set username=#{name} where id=#{id}
</update>

5.3 删除用户操作

<delete id="delById" parameterType="java.lang.Integer">
 delete from userinfo where id=#{id}
</delete>

6.查询操作

6.1 单表查询

下⾯我们来实现⼀下根据⽤户 id 查询⽤户信息的功能。
Controller 实现代码如下:
@RequestMapping("/getuser")
public User getUserById(Integer id) {
 return userService.getUserById(id);
}
Mapper.xml 实现代码如下:
<select id="getUserById" resultType="com.example.demo.model.User">
 select * from userinfo where id=#{id}
</select>

6.1.1 参数占位符 #{} 和 ${}

  • #{}:预编译处理。
  • ${}:字符直接替换。
预编译处理是指:MyBatis 在处理#{}时,会将 SQL 中的 #{} 替换为?号,使⽤ PreparedStatement
的 set ⽅法来赋值。
直接替换:是MyBatis 在处理 ${} 时,就是把 ${} 替换成变量的值。字符的内容,直接就被当作SQL的一部分来运行了
预编译处理和字符串替换的区别故事(头等舱和经济舱乘机分离的故事):
在坐⻜机的时候头等舱和经济舱的区别是很⼤的,如下图所示:

⼀般航空公司乘机都是头等舱和经济舱分离的,头等舱的⼈先登机,登机完之后,封闭经济舱,然后再让经济舱的乘客登机,这样的好处是可以避免浑⽔摸⻥,经济舱的⼈混到头等舱的情况,这就相当于预处理,可以解决程序中不安全(越权处理)的问题。
⽽直接替换的情况相当于,头等舱和经济舱不分离的情况,这样经济舱的乘客在通过安检之后可能越权摸到头等舱,如下图所示:

⽽直接替换的情况相当于,头等舱和经济舱不分离的情况,这样经济舱的乘客在通过安检之后可能越权摸到头等舱,如下图所示:

这就相当于参数直接替换,它的问题是可能会带来越权查询和操作数据等问题,⽐如

SQL 注入问题

6.1.2 ${} 优点

<select id="getAllBySort" parameterType="java.lang.String" resultType="com.
example.demo.model.User">
 select * from userinfo order by id ${sort}
</select>
使⽤ ${sort} 可以实现排序查询,⽽使⽤ #{sort} 就不能实现排序查询了,因为当使⽤ #{sort} 查询时,如果传递的值为 String 则会加单引号,就会导致 sql 错误。

6.1.3 SQL 注入问题

<select id="isLogin" resultType="com.example.demo.model.User">
 select * from userinfo where username='${name}' and password='${pwd}'
</select>
sql 注⼊代码:“' or 1='1”

 结论:⽤于查询的字段,尽量使⽤ #{} 预查询的⽅式。

6.1.4 like 查询

like 使⽤ #{} 报错
<select id="findUserByName2" resultType="com.example.demo.model.User">
 select * from userinfo where username like '%#{username}%';
 </select>
相当于: select * from userinfo where username like '%'username'%';
这个是不能直接使⽤ ${},可以考虑使⽤ mysql 的内置函数 concat() 来处理,实现代码如下:
<select id="findUserByName3" resultType="com.example.demo.model.User">
 select * from userinfo where username like concat('%',#{usernam
e},'%');
</select>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/801692.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git时间:版本控制工具进阶

Git时间&#xff1a;版本控制工具进阶 忽略文件 Git允许用户将指定的文件或目录排除在版本控制之外&#xff0c;它会检查代码仓库的目录下是否存在一个名为.gitignore的文件&#xff0c;如果存在&#xff0c;就去一行行读取这个文件中的内容&#xff0c;并把每一行指定的文件…

Matlab的SimuLink对FS32K144编程--SPI通讯控制12bitDAC输出

​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ 1、硬件介绍&#xff0c;DAC芯片&#xff1a;AD5328BRUZ DAC_SPI_SCK----PTD0(SPI1) DAC_SPI_DIN----PTE0(SPI1)单片…

Android 之 使用 SoundPool 播放音效

本节引言&#xff1a; 第九章给大家带来的是Android中的多媒体开发&#xff0c;与其说是多媒体开发还不如是多媒体相关API的 的使用&#xff0c;说下实际开发中我们做了一些和多媒体搭边的东西&#xff1a;拍照&#xff0c;录音&#xff0c;播放音乐&#xff0c;播放视频... 嗯…

stable-diffusion-webui汉化教程

第一种方法 1.打开stable diffusion webui&#xff0c;进入"Extensions"选项卡 2.点击"Install from URL" 3、注意"URL for extension’s git repository"下方的输入框 4、填入地址&#xff1a;https://github.com/VinsonLaro/stable-diffus…

让企业出海支付流程更加安全,亚马逊云科技推出支付加密服务

在咖啡店买一杯咖啡&#xff0c;在电商平台下单一件商品&#xff0c;其消费流程背后&#xff0c;都要涉及到金融支付的多个环节&#xff0c;而其中对金融数据存储和流通的加密则是保障金融安全的重要环节。 加密是保障消费者支付流程安全的最大挑战。亚马逊云科技首席安全布道…

医学案例|ROC曲线

一、案例介绍 研究者想要进行“糖化血蛋白”的研究&#xff0c;对糖尿病患者和非糖尿病患者各100名检测糖化血红蛋白&#xff08;HbAlc&#xff09;含量&#xff0c;希望可以研究糖化血蛋白对患有糖尿病的情况是否有诊断价值&#xff0c;如果有最佳的诊断界值是多少。 二、问…

MQ, RocketMQ, 安装

文章说明 本文主要说明RocketMQ的几种常见的安装方式。之前在工作中也用过RocketMQ&#xff0c;但是一直用的是测试环境上的&#xff0c;也没有自己动手安装过。这次专门抽了时间学习了一下。 文章目录 文章说明参考文献安装windows安装环境要求下载配置环境变量启动注意事项 …

OJ练习第146题——杨辉三角 II

力扣链接&#xff1a;119. 杨辉三角 II 题目描述 给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 Java代码&#xff08;直接法&#xff09; class Solution {/*** 获取…

程序员自由创业周记#4:从一笔30美元的收入谈起

程序员自由创业周记#4&#xff1a;从一笔30美元的收入谈起 pexels-freestocksorg-127713 本文是一位程序员进行独立开发创业的记录&#xff0c;将分享创业过程中的所思所想以及收支明细。在文末&#xff0c;您还可以找到之前的历史文章。 惊喜之旅 这次的惊喜源于 学伟扫描Pro …

初探webAssembly | 京东物流技术团队

1 WebAssembly是什么&#xff1f; 一种运行在现代网络浏览器中的新型代码&#xff0c;并且提供新的性能特性和效果 W3C WebAssembly Community Group开发的一项网络标准&#xff0c;对于浏览器而言&#xff0c;WebAssembly 提供了一条途径&#xff0c;让各种语言编写的代码以接…

AXI协议之AXILite开发设计(三)

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 三、xilinx的AXILite的ip组件生成及…

智能RFID追溯系统优化空调装配效能

智能RFID追溯系统优化空调装配效能 空调作为现代家庭和工业建筑中必备的设备&#xff0c;其装配过程对生产效率和质量至关重要。传统的装配方式往往依赖于人工操作&#xff0c;存在一定的人为失误和效率低下的问题。而RFID技术的应用能够为空调装配带来一系列的优势。 RFID技…

景区如何对旅行社进行分销管理?

旅行社的买票能力强&#xff0c;一般景区会跟多家旅行社合作门票分销。其中卖票下单、价格设定、财务对账结算都出现了很多问题&#xff0c;导致对账困难&#xff0c;查询困难&#xff0c;甚至可能有偷票漏票的情况出现&#xff0c;给景区收入造成损失。那要怎么处理呢&#xf…

C#..上位机软件的未来是什么?

C#是一种流行的编程语言&#xff0c;广泛应用于桌面应用程序和上位机软件开发。未来&#xff0c;C#上位机软件将继续不断发展和创新&#xff0c;以满足用户日益增长的需求。以下是我认为C#上位机软件未来可能会涉及的一些方向&#xff1a; 更加智能化&#xff1a;随着人工智能…

全面防护!Fortinet发布混合式部署防火墙HMF

在企业IT复杂性日益增长、网络安全威胁日趋紧迫、网络安全设施可维护性逐渐降低的背景下&#xff0c;企业迫切寻求可无缝跨越所有IT区域&#xff0c;有效简化企业防护架构的统一解决方案。近日&#xff0c; Fortinet Accelerate 2023中国区15城巡展圆满落幕&#xff0c;在收官之…

CentOS 项目发出一篇奇怪的博文

导读最近&#xff0c;在红帽限制其 RHEL 源代码的访问之后&#xff0c;整个社区围绕这件事发生了很多事情。 CentOS 项目发出一篇奇怪的博文 周五&#xff0c;CentOS 项目董事会发出了一篇模糊不清的简短博文&#xff0c;文中称&#xff0c;“发展社区并让人们更容易做出贡献…

安卓:Picasso——加载网络图片的库

目录 一、Picasso介绍及其优势 二、Picasso的使用方法 1、添加依赖&#xff1a; 2、Picasso常用方法&#xff1a; 1、加载图像&#xff1a; 2、图像显示&#xff1a; 3、图像处理&#xff1a; 4、图像占位符和错误处理&#xff1a; 5、缓存控制&#xff1a; 6、清除缓…

INDEMIND:告别人工智障,扫地机器人哪种避障方式能让你“躺平”?

方寸之间&#xff0c;腾转自如&#xff0c;这或许是人们对扫地机器人避障功能的理想期待。 谁才是扫地机器人的“最优解”&#xff1f; 评判一款扫地机器人好用与否&#xff0c;避障表现无疑是核心因素。一款能够准确有效规避家居、行人、动物的产品&#xff0c;不仅能够保障产…

标准信号槽

标准信号槽 定义使用关于绑定的注意事项 定义 在Qt提供的很多标准类中都可以对用户触发的某些特定事件进行检测, 因此当用户做了这些操作之后, 事件被触发类的内部就会产生对应的信号, 这些信号都是Qt类内部自带的, 因此称之为标准信号。 在Qt的很多类内部为我了提供了很多功…

k3s安装使用

文章目录 k3s单机安装报错:1. container-selinux软件包版本不匹配的问题 验证安装是否成功 【TODO】 集群安装&#xff1a;AutoK3skubectl连接1. 本机访问2. 远程机器访问 部署Kubernetes Dashboard v2.71. 部署2. 集群内 访问服务3. 集群外 访问服务3. 生成用户token、用token…