Mybatis中#与$区别
#
符号(预编译):
- 使用
#
符号时,MyBatis会将SQL中的#
替换成预编译参数的占位符(?
),然后通过PreparedStatement来执行SQL语句。这样做可以有效防止SQL注入,因为参数值会被安全地设置到预编译语句中。 - 举例来说,假设有一个查询用户信息的SQL语句:
<select id="getUserById" parameterType="int" resultType="User"> SELECT * FROM users WHERE id = #{userId} </select>
当调用这个查询并传入参数
userId = 1
时,最终执行的SQL语句会是: -
SELECT * FROM users WHERE id = ?
MyBatis会将
1
设置到?
的位置,这样执行效率高,并且安全。
$
符号(字符串替换):
使用$
符号时,MyBatis会直接将参数的值按照原样拼接到SQL语句中,不进行预编译处理。这样做灵活性更高,但也更容易受到SQL注入攻击。
举例来说,继续使用上面的例子,如果将SQL语句改成使用$
符号:
<select id="getUserById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = ${userId}
</select>
当传入userid=1 时,最终执行的SQL语句
SELECT * FROM users WHERE id = 1
这里的是直接被替换进去的,没有经过预编译,可能存在SQL注入的风险。
jdk、jre、jvm区别
JDK包含了JRE和JVM,而JRE则包含了JVM。
-
JDK(Java Development Kit) java开发工具包 是面向开发人员的,它包含了JRE以及额外的开发工具,如编译器和调试器,用于编写和测试Java程序。
-
JRE(Java Runtime Environment)java运行环境 是面向用户的,它包含了JVM以及Java程序运行所需的核心类库。JRE允许用户在没有任何开发工具的情况下运行Java应用程序。
-
JVM(Java Virtual Machine) Java虚拟机 是Java程序运行的核心,它负责将Java字节码转换为特定操作系统的机器码,从而实现了Java的跨平台特性。JVM是JRE的一部分,而JDK中则包含了JVM用于开发环境。
sql优化
-
索引优化:
确保查询中涉及的列上有合适的索引。缺乏索引或者使用不当的索引是导致查询效率低下的常见原因。使用数据库的索引优化工具或者执行计划(explain)来分析查询的执行情况,查看是否在关键的列上使用了索引,或者是否可以优化现有索引。 -
SQL语句优化:
分析慢查询的SQL语句,看是否可以通过重写SQL语句、优化连接方式、减少子查询或者使用更有效的查询方式来提升性能。有时候,复杂的SQL语句会导致数据库的性能下降。 -
数据库配置调优:
调整数据库的配置参数,如内存分配、缓存设置、并发连接数等,以确保数据库系统能够更有效地处理查询请求。不同的数据库有不同的配置调优方法,需要根据具体情况来进行调整。
Springboot与Spring Cloud区别
Spring Boot
- Spring Boot 是一个用于简化 Spring 应用开发的框架,它基于 Spring 框架,但目的是通过提供约定大于配置的方式来快速启动和运行应用程序。主要特点包括:
- 自动配置:根据应用程序的依赖和设置,自动配置Spring和第三方库。
- 独立运行:内嵌了服务器,可以将应用程序打包为可执行的JAR包。
- 简化配置:通过
application.properties
或application.yml
文件来集中管理配置。 - 生产就绪:包含了诸如健康检查、监控等生产环境特性。
快速启动和部署:将整个应用打包为可执行的 JAR 文件,通过简单的命令即可启动,适合快速部署和更新的需求。
自动配置和集成:自动配置数据库连接、Web 服务器、安全性等,大大简化了开发和维护工作,减少了人为错误的可能性。
生产环境的健康监测:利用 Actuator 组件提供的监控和管理功能,实时监测应用程序的运行状态,包括健康检查、指标收集等,帮助运维人员快速发现和解决问题。
简化配置管理: 通过 application.properties
或 application.yml
集中管理配置,支持多环境配置文件,便于在不同环境中切换和配置。
Spring Boot 的主要目标是减少开发者的配置工作,提高开发效率,使开发者能够更专注于业务逻辑的实现而不是框架的集成和配置。
Spring Cloud
- Spring Cloud 是基于 Spring Boot 的工具集合,用于快速构建分布式系统的一些工具/框架的集合。它提供了多种解决方案,用于开发分布式系统的各个方面,如配置管理、服务发现、负载均衡、断路器、消息总线等。主要特点包括:
- 分布式/微服务架构的支持:通过提供各种微服务模式的实现,如服务注册与发现(Eureka、Consul)、负载均衡(Ribbon)、断路器(Hystrix)、网关(Zuul、Spring Cloud Gateway)等,帮助构建弹性、高可用的分布式系统。
- 配置管理:提供集中式的配置管理服务(Spring Cloud Config),方便动态管理和更新配置。
- 服务间通信:通过服务调用、消息总线等机制,简化微服务之间的通信和协作。
微服务架构的构建与管理:使用 Eureka 或 Consul 进行服务注册与发现,使得各个微服务可以动态地注册和发现其他服务,实现高可用和弹性的微服务架构。
负载均衡和服务调用:过 Ribbon 或者 Spring Cloud LoadBalancer 提供的负载均衡功能,实现对微服务的智能负载均衡,提高系统的整体性能和稳定性。
断路器模式和容错管理:用 Hystrix 或者 Spring Cloud Circuit Breaker 实现断路器模式,防止微服务调用链路中的故障扩散,提高系统的容错能力。
分布式配置管理:利用 Spring Cloud Config 实现集中式的配置管理,动态地管理和更新微服务的配置,确保不同微服务在不同环境下的一致性。
网关和API管理:使用 Zuul 或者 Spring Cloud Gateway 实现统一的API网关,提供路由、认证、限流等功能,保护微服务并简化客户端与微服务的交互。
Redis为什么快
-
基于内存的存储: Redis将数据存储在内存中,这使得它能够快速读取和写入数据。与传统的磁盘存储相比,内存访问速度更快,能够大大缩短数据访问的延迟时间。
-
单线程模型: Redis采用单线程模型来处理客户端请求,这在一定程度上简化了并发控制和数据同步的复杂性。单线程模型避免了多线程并发访问时的上下文切换开销,从而提高了处理请求的效率。
-
非阻塞IO: Redis使用了非阻塞IO来处理多个客户端的请求。通过使用事件轮询机制(如epoll或者kqueue),Redis能够高效地管理多个客户端连接,实现高并发的处理能力。
-
优化的数据结构: Redis内置了丰富的数据结构,如字符串、哈希表、列表、集合、有序集合等,每种数据结构都经过优化,能够高效地支持各种操作,如添加、删除、查找和范围操作等。
-
持久化和复制支持: Redis支持多种持久化方式,如RDB快照和AOF日志,这些机制保证了数据的安全性和可靠性。此外,Redis还支持主从复制,能够通过复制机制实现数据的分布式存储和负载均衡,提高了系统的可扩展性和容错性。
-
轻量级和简洁设计: Redis本身设计简洁,专注于提供高效的内存数据存储和处理能力,没有过多的复杂功能和依赖,使得它能够在性能和资源消耗之间取得很好的平衡。
Redis如何实现持久化
RDB持久化
RDB持久化会在指定的时间间隔内生成数据库的快照(snapshot),将数据集的内容以二进制文件的形式保存到硬盘上。这种方式适合用于备份、灾难恢复等场景。
配置方法:
在Redis的配置文件(通常是redis.conf)中,可以设置RDB持久化的相关参数:
# 开启RDB持久化,默认是yes
save 900 1 # 在900秒内,如果至少有1个key发生了变化,则执行一次保存
save 300 10 # 在300秒内,如果至少有10个key发生了变化,则执行一次保存
save 60 10000 # 在60秒内,如果至少有10000个key发生了变化,则执行一次保存
# 指定RDB文件名
dbfilename dump.rdb
# 指定RDB文件存放路径
dir /path/to/your/redis/dump
示例:
假设我们有一个Redis服务器,存储了几个键值对。Redis将会根据上述配置,在特定条件下自动创建RDB快照文件。
例如,如果在900秒内至少有1个键被修改,Redis将生成一个dump.rdb文件,保存当前数据库的快照。这个快照可以在Redis重新启动时用来恢复数据。
AOF持久化
AOF持久化记录每次写操作的命令,将这些命令追加到文件末尾(Append-Only File)中。当Redis重新启动时,会重新执行这些命令来重建原始数据集。AOF持久化适合需要更高数据安全性的场景。
配置方法:
同样,在Redis的配置文件中设置AOF持久化的相关参数:
# 启用AOF持久化,默认是no
appendonly yes
# 指定AOF文件名
appendfilename "appendonly.aof"
# 指定AOF文件存放路径
dir /path/to/your/redis/appendonly
示例:
当开启AOF持久化后,Redis会将每个写操作追加到appendonly.aof文件中。例如,如果执行了一条写命令如 SET key value
,Redis会将这条命令追加到AOF文件的末尾。这确保了即使在Redis非正常关闭的情况下,数据也能得到完整恢复。
假设我们在Redis中执行了以下操作:
127.0.0.1:6379> SET mykey "Hello"
OK
127.0.0.1:6379> SET myotherkey "World"
OK
如果Redis配置了RDB持久化,根据上述配置,当满足条件(例如900秒内至少有1个键被修改)时,Redis会在指定路径下生成一个dump.rdb文件,保存当前的数据库快照。类似地,如果配置了AOF持久化,Redis会将对 SET
命令的调用追加到appendonly.aof文件中。
这样,无论是RDB还是AOF持久化,Redis都能保证在重启或者灾难恢复时,数据能够安全可靠地恢复到之前的状态。
MyBatis与MyBatis-Plus关系
MyBatis(MyBatis-3)
-
核心功能:
- MyBatis是一个半自动化的ORM框架,它通过XML或者注解配置来映射Java对象和SQL语句,实现对象关系映射。
- 提供了灵活的SQL编写和执行方式,开发者可以直接编写和调优SQL语句。
-
特点:
- 灵活性: 提供了灵活的SQL映射配置方式,可以通过XML文件或者注解来进行配置。
- SQL控制: 可以直接控制和优化SQL语句的执行方式,适合对SQL有特定优化需求的开发者。
- 原生态: 保留了SQL和Java对象之间的直接映射关系,不强制要求使用特定的数据库访问模式。
-
使用场景:
- 适合对SQL语句有较高控制要求的项目。
- 对于需要定制化SQL执行逻辑和性能优化的应用程序较为合适。
MyBatis-Plus
-
核心功能:
- MyBatis-Plus是在MyBatis的基础上进行的扩展和增强,提供了更多的便捷功能和增强特性。
- 封装了常用的CRUD操作,简化了SQL语句的编写。
- 提供了代码生成器等工具,可以快速生成MyBatis的Mapper接口和XML文件。
-
特点:
- 便捷性: 提供了一系列的便捷方法和工具类,简化了开发者对数据库操作的常规处理。
- 增强功能: 提供了更多的功能扩展,如分页插件、性能分析插件等。
- 集成: 提供了与Spring Boot等常见框架的集成支持,可以更方便地在项目中使用。
-
使用场景:
- 适合快速开发、对常规CRUD操作需求较多的项目。
- 对于简化开发、提高开发效率有较高要求的应用程序较为合适。
配置方式
MyBatis
<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper">
<select id="findById" parameterType="int" resultType="com.example.model.User">
SELECT * FROM user WHERE id = #{id}
</select>
<insert id="insertUser" parameterType="com.example.model.User">
INSERT INTO user (username, password) VALUES (#{username}, #{password})
</insert>
<update id="updateUser" parameterType="com.example.model.User">
UPDATE user SET username = #{username}, password = #{password} WHERE id = #{id}
</update>
<delete id="deleteUser" parameterType="int">
DELETE FROM user WHERE id = #{id}
</delete>
</mapper>
// UserMapper.java
public interface UserMapper {
User findById(int id);
void insertUser(User user);
void updateUser(User user);
void deleteUser(int id);
}
MyBatis-Plus
// User.java (Entity)
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private String password;
// Getters and setters
}
// UserController.java
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUser(@PathVariable("id") Long id) {
return userService.getById(id);
}
@PostMapping
public void createUser(@RequestBody User user) {
userService.save(user);
}
@PutMapping("/{id}")
public void updateUser(@PathVariable("id") Long id, @RequestBody User user) {
user.setId(id);
userService.updateById(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable("id") Long id) {
userService.removeById(id);
}
}
// UserService.java
@Service
public class UserService extends ServiceImpl<UserMapper, User> {
// Additional service methods if needed
}
// UserMapper.java
@Mapper
public interface UserMapper extends BaseMapper<User> {
// Additional methods if needed
}