为了账号安全,请及时绑定邮箱和手机立即绑定

Mybatis持久层框架学习:入门与实战教程

标签:
Java 数据库
概述

Mybatis持久层框架学习包括环境搭建、核心概念介绍、基本使用方法、映射文件编写以及高级特性等,帮助开发者掌握Mybatis的基本操作和高级功能。文章还详细讲解了Mybatis与Spring的集成方法,包括事务管理和Mapper接口的使用。此外,通过实战案例分享和常见问题解决,进一步加深对Mybatis的理解和应用。

Mybatis简介与环境搭建
Mybatis概述

Mybatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。Mybatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。Mybatis通过XML或注解方式将Java方法与数据库表结构对应起来,可以将查询结果映射成Java对象,也可以从Java对象中提取属性来组成查询语句。它能够为Java应用程序提供持久化服务,是Java领域非常优秀的持久层框架之一。

开发环境配置

开发Mybatis应用需要搭建相应的开发环境。首先,确保你的开发环境包含了以下工具:

  • JDK(建议使用JDK 1.8及以上版本)
  • IDE(如IntelliJ IDEA,Eclipse等)
  • Maven(用于构建项目和管理依赖)
  • MySQL数据库(用于数据存储)

接下来,我们可以创建一个简单的Maven工程来引入Mybatis的相关依赖。在pom.xml文件中添加以下依赖:

<dependencies>
    <!-- Mybatis核心依赖 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>

    <!-- MySQL驱动 -->
    <dependency>
        <groupId>mysql</groupId>
       .<artifactId>mysql-connector-java</artifactId>
        <version>8.0.26</version>
    </dependency>
</dependencies>

同时,为了方便测试,我们还需要引入JUnit测试框架,以便进行单元测试。

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

在资源目录(如src/main/resources)下创建数据库连接的配置文件(如mybatis-config.xml),其中包含数据库连接信息和其他Mybatis配置信息。

<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

通过以上步骤,我们已经完成了Mybatis的基本环境搭建。

Mybatis的核心概念与组件介绍

Mybatis的核心组件包括SqlSessionFactorySqlSessionMapper接口。

SqlSessionFactory

SqlSessionFactory是通过SqlSessionFactoryBuilder来创建的。SqlSessionFactory是一个工厂类,用于创建SqlSession对象,它是线程不安全的,因此通常会为整个应用创建一个SqlSessionFactory的实例。

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

SqlSession

SqlSession是Mybatis中最核心的部分,提供了一系列的方法用于执行数据库操作。它是线程不安全的,因此每次使用时都需要创建一个新的实例。

SqlSession sqlSession = factory.openSession();

Mapper接口

Mapper接口是Mybatis提供的一个强大的特性,通过定义接口的方法可以对应到具体的SQL语句。Mybatis通过SqlSession来执行这些接口中的方法,从而执行相应的SQL语句。

public interface UserMapper {
    List<User> getAllUsers();
}

Mybatis的配置文件

Mybatis的配置文件(如mybatis-config.xml)中可以包含数据库连接信息、类型别名、映射器(Mapper)等配置信息。

数据库连接信息

在配置文件中,通过environments标签来定义数据库连接信息。

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
            <property name="username" value="root"/>
            <property name="password" value="password"/>
        </dataSource>
    </environment>
</environment>

映射器(Mapper)

在配置文件中,通过mappers标签来定义映射器的位置,指定Mapper接口或者Mapper XML文件的位置。

<mappers>
    <mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>

通过以上配置,我们已经完成了Mybatis的基本配置和组件介绍。接下来,我们可以开始使用Mybatis进行基本的CRUD操作。

Mybatis的基本使用
SqlSession的使用

SqlSession是Mybatis中最核心的部分,提供了执行SQL语句和管理事务的功能。通常,我们会使用SqlSessionFactory来创建SqlSession实例。

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = factory.openSession();

基本的CRUD操作

Mybatis提供了基本的CRUD操作方法,包括insertselectupdatedelete

插入数据

假设我们有一个名为User的实体类,以及对应的Mapper接口和XML映射文件。

public class User {
    private int id;
    private String username;
    private String password;
    // getter和setter方法
}

Mapper接口中定义插入数据的方法:

public interface UserMapper {
    int insertUser(User user);
}

对应的XML映射文件中定义插入语句:

<mapper namespace="com.example.mapper.UserMapper">
    <insert id="insertUser">
        INSERT INTO users (username, password) VALUES (#{username}, #{password})
    </insert>
</mapper>

在代码中使用SqlSession来执行插入操作:

User user = new User();
user.setUsername("testUser");
user.setPassword("testPass");

int rowsAffected = sqlSession.insert("com.example.mapper.UserMapper.insertUser", user);

查询数据

Mapper接口中定义查询数据的方法:

public interface UserMapper {
    List<User> getAllUsers();
}

对应的XML映射文件中定义查询语句:

<mapper namespace="com.example.mapper.UserMapper">
    <select id="getAllUsers" resultType="com.example.domain.User">
        SELECT * FROM users
    </select>
</mapper>

在代码中使用SqlSession来执行查询操作:

```java.
List<User> users = sqlSession.selectList("com.example.mapper.UserMapper.getAllUsers");


#### 更新数据
Mapper接口中定义更新数据的方法:

```java
public interface UserMapper {
    int updateUser(User user);
}

对应的XML映射文件中定义更新语句:

<mapper namespace="com.example.mapper.UserMapper">
    <update id="updateUser">
        UPDATE users SET username=#{username}, password=#{password} WHERE id=#{id}
    </update>
</mapper>

在代码中使用SqlSession来执行更新操作:

User user = new User();
user.setId(1);
user.setUsername("newUser");
user.setPassword("newPass");

int rowsAffected = sqlSession.update("com.example.mapper.UserMapper.updateUser", user);

删除数据

Mapper接口中定义删除数据的方法:

public interface UserMapper {
    int deleteUser(int id);
}

对应的XML映射文件中定义删除语句:

<mapper namespace="com.example.mapper.UserMapper">
    <delete id="deleteUser">
        DELETE FROM users WHERE id=#{id}
    </delete>
</mapper>

在代码中使用SqlSession来执行删除操作:

int rowsAffected = sqlSession.delete("com.example.mapper.UserMapper.deleteUser", 1);

以上是Mybatis基本的CRUD操作,通过SqlSession和对应的Mapper接口及XML映射文件,我们可以方便地执行数据库操作。

参数绑定与结果映射

在实际开发中,我们经常需要传递复杂的参数或处理复杂的查询结果。Mybatis提供了强大的参数绑定和结果映射功能,使得处理复杂数据变得简单。

参数绑定

参数绑定是指将Java对象的属性值映射到SQL语句中的参数。除了简单的类型,还可以传递复杂的Java对象作为参数。

复杂对象作为参数

假设我们有一个名为User的实体类,以及一个名为UserMapper的Mapper接口。

public class User {
    private int id;
    private String username;
    private String password;
    // getter和setter方法
}

Mapper接口中定义一个方法,接受一个User对象作为参数:

public interface UserMapper {
    int updateUser(User user);
}

在XML映射文件中定义对应的SQL语句:

<update id="updateUser">
    UPDATE users SET username=#{username}, password=#{password} WHERE id=#{id}
</update>

在代码中使用SqlSession来执行更新操作:

User user = new User();
user.setId(1);
user.setUsername("newUser");
user.setPassword("newPass");

int rowsAffected = sqlSession.update("com.example.mapper.UserMapper.updateUser", user);

结果映射

结果映射是指将查询结果映射到Java对象中。除了简单的类型,还可以映射为复杂的对象。

复杂对象作为结果

Mapper接口中定义一个方法,返回一个List<User>对象:

public interface UserMapper {
    List<User> getAllUsers();
}

在XML映射文件中定义对应的SQL语句:

<select id="getAllUsers" resultType="com.example.domain.User">
    SELECT * FROM users
</select>

在代码中使用SqlSession来执行查询操作:

List<User> users = sqlSession.selectList("com.example.mapper.UserMapper.getAllUsers");

另外,还可以使用resultMap来处理更复杂的映射情况,例如一对一、一对多等。

<resultMap id="userResultMap" type="com.example.domain.User">
    <id column="user_id" property="id"/>
    <result column="user_name" property="username"/>
    <result column="user_password" property="password"/>
</resultMap>

通过以上示例,我们可以看到Mybatis强大的参数绑定和结果映射功能,能够方便地处理复杂的数据库操作。

Mybatis的映射文件编写
SQL语句映射

Mybatis通过XML映射文件(Mapper XML文件)来定义SQL语句及其参数和结果映射。Mapper XML文件通常与Mapper接口相对应,用于实现SQL语句的定义。

基本SQL语句

在Mapper XML文件中,可以定义各种SQL语句,包括selectinsertupdatedelete

示例

假设我们有一个名为UserMapper的Mapper接口和对应的XML映射文件。

public interface UserMapper {
    int insertUser(User user);
    List<User> getAllUsers();
}

对应的XML映射文件如下:

<mapper namespace="com.example.mapper.UserMapper">
    <insert id="insertUser">
        INSERT INTO users (username, password) VALUES (#{username}, #{password})
    </insert>

    <select id="getAllUsers" resultType="com.example.domain.User">
        SELECT * FROM users
    </select>
</mapper>

使用resultType

resultType属性用于指定返回结果的Java类型,通常用于简单的SQL语句。

<select id="getUserById" resultType="com.example.domain.User">
    SELECT * FROM users WHERE id = #{id}
</select>

使用resultMap

对于复杂的查询结果,可以使用resultMap来定义结果映射规则。

<resultMap id="userResultMap" type="com.example.domain.User">
    <id column="user_id" property="id"/>
    <result column="user_name" property="username"/>
    <result column="user_password" property="password"/>
</resultMap>

<select id="getUserById" resultMap="userResultMap">
    SELECT user_id, user_name, user_password FROM users WHERE id = #{id}
</select>
动态SQL

Mybatis提供了强大的动态SQL功能,可以通过条件标签来生成不同的SQL语句。常用的条件标签包括ifchoosewhenotherwiseforeach等。

条件标签

if标签

if标签用于条件判断,仅当条件为真时才会包含在SQL语句中。

<select id="getUserById" resultType="com.example.domain.User">
    SELECT * FROM users WHERE 1=1
    <if test="id != null">
        AND id = #{id}
    </if>
    <if test="username != null">
        AND username = #{username}
    </if>
</select>

choosewhenotherwise标签

choosewhenotherwise标签用于多条件选择,类似于SQL中的CASE语句。

<select id="getUserById" resultType="com.example.domain.User">
    SELECT * FROM users WHERE 1=1
    <choose>
        <when test="id != null">
            AND id = #{id}
        </when>
        <when test="username != null">
            AND username = #{username}
        </when>
        <otherwise>
            AND password = #{password}
        </otherwise>
    </choose>
</select>

foreach标签

foreach标签用于遍历集合或数组,生成多条语句。

<select id="getUserByIds" resultType="com.example.domain.User">
    SELECT * FROM users WHERE id IN
    <foreach item="item" index="index" collection="ids" open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

通过以上示例,我们可以看到Mybatis强大的动态SQL功能,可以灵活地生成不同的SQL语句。

分页查询

分页查询是一种常见的需求,可以通过Mybatis的RowBounds接口来实现简单的分页功能。

使用RowBounds

RowBounds接口提供了简单的分页功能,支持偏移量和限制。

RowBounds rowBounds = new RowBounds(offset, limit);
List<User> users = sqlSession.selectList("com.example.mapper.UserMapper.getAllUsers", null, rowBounds);

使用分页插件

对于复杂的分页需求,可以使用分页插件来实现更灵活的分页功能。

分页插件示例

假设我们有一个分页插件类,可以通过配置来启用分页插件。

public class PaginationInterceptor extends Interceptor {
    // ...
}

在Mybatis配置文件中启用分页插件:

<configuration>
    <plugins>
        <plugin interceptor="com.example.plugin.PaginationInterceptor">
            <!-- 配置插件参数 -->
        </plugin>
    </plugins>
</configuration>

通过以上示例,我们可以看到Mybatis提供了多种分页实现方式,可以根据实际需求选择合适的分页方案。

Mybatis的高级特性
关联查询与嵌套结果映射

在实际开发中,我们经常会遇到关联查询的需求。Mybatis提供了强大的嵌套结果映射功能,可以方便地处理复杂的关联查询。

一对一关联查询

假设我们有一个User实体和一个Address实体,以及对应的Mapper接口和XML映射文件。

public class User {
    private int id;
    private String username;
    private String password;
    private Address address;
    // getter和setter方法
}

public class Address {
    private int id;
    private String street;
    private String city;
    // getter和setter方法
}

Mapper接口中定义一个方法,返回User对象及其关联的Address对象。

public interface UserMapper {
    User getUserWithAddress(int id);
}

对应的XML映射文件中定义SQL语句和嵌套结果映射:

<resultMap id="userResultMap" type="com.example.domain.User">
    <id column="user_id" property="id"/>
    <result column="user_name" property="username"/>
    <result column="user_password" property="password"/>
    <association property="address" javaType="com.example.domain.Address">
        <id column="address_id" property="id"/>
        <result column="address_street" property="street"/>
        <result column="address_city" property="city"/>
    </association>
</resultMap>

<select id="getUserWithAddress" resultMap="userResultMap">
    SELECT u.user_id, u.user_name, u.user_password,
           a.address_id, a.address_street, a.address_city
    FROM users u
    JOIN addresses a ON u.address_id = a.address_id
    WHERE u.user_id = #{id}
</select>

一对多关联查询

假设我们有一个User实体和一个Order实体,以及对应的Mapper接口和XML映射文件。

public class User {
    private int id;
    private String username;
    private String password;
    private List<Order> orders;
    // getter和setter方法
}

public class Order {
    private int id;
    private String orderName;
    private String orderDate;
    // getter和setter方法
}

Mapper接口中定义一个方法,返回User对象及其关联的Order对象列表。

public interface UserMapper {
    User getUserWithOrders(int id);
}

对应的XML映射文件中定义SQL语句和嵌套结果映射:

<resultMap id="userResultMap" type="com.example.domain.User">
    <id column="user_id" property="id"/>
    <result column="user_name" property="username"/>
    <result column="user_password" property="password"/>
    <collection property="orders" ofType="com.example.domain.Order">
        <id column="order_id" property="id"/>
        <result column="order_name" property="orderName"/>
        <result column="order_date" property="orderDate"/>
    </collection>
</resultMap>

<select id="getUserWithOrders" resultMap="userResultMap">
    SELECT u.user_id, u.user_name, u.user_password,
           o.order_id, o.order_name, o.order_date
    FROM users u
    JOIN orders o ON u.user_id = o.user_id
    WHERE u.user_id = #{id}
</select>

通过以上示例,我们可以看到Mybatis强大的关联查询和嵌套结果映射功能,可以方便地处理复杂的关联查询。

缓存机制

Mybatis提供了缓存机制,可以通过配置来启用缓存。Mybatis的缓存分为一级缓存和二级缓存。

一级缓存

一级缓存是SqlSession级别的缓存,当一个SqlSession执行相同的SQL语句时,会先从一级缓存中查找,如果查找到结果,则直接返回缓存中的对象,而不会执行SQL语句。SqlSession的一级缓存默认是开启的,可以通过配置文件关闭。

<settings>
    <setting name="cacheEnabled" value="false"/>
</settings>

二级缓存

二级缓存是全局的缓存,所有SqlSession共用一个二级缓存。二级缓存默认是关闭的,可以通过配置文件开启,并进行自定义配置。

<cache-ref local="true" />
<cache type="org.apache.ibatis.builtin.local.LocalCache" />
<cache type="org.apache.ibatis.builtin.local.LocalCache" local="true" />

通过以上示例,我们可以看到Mybatis的缓存机制,可以有效提高查询性能。

插件开发

Mybatis支持插件开发,可以通过编写插件来扩展Mybatis的功能。插件开发的主要目的是对SQL执行过程进行拦截和增强。

插件开发示例

假设我们有一个插件类,用于在SQL执行前拦截和增强。

public class MybatisPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 拦截逻辑
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 配置属性
    }
}

在Mybatis配置文件中启用插件:

<plugins>
    <plugin interceptor="com.example.plugin.MybatisPlugin">
        <!-- 配置插件参数 -->
    </plugin>
</plugins>

通过以上示例,我们可以看到Mybatis的插件开发功能,可以方便地扩展Mybatis的功能。

Mybatis与Spring集成
Mybatis-Spring整合

Mybatis与Spring的整合可以使得Mybatis更加方便地使用Spring的依赖注入、事务管理等功能。通常,我们会使用mybatis-spring库来实现Mybatis与Spring的整合。

引入依赖

在pom.xml文件中引入mybatis-spring库:

<dependency>
    <groupId>org.mybatis.spring</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.6</version>
</dependency>

配置SqlSessionFactory

通过SqlSessionFactoryBean来创建SqlSessionFactory实例,并进行配置。

@Configuration
public class MybatisConfig {
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        return factoryBean.getObject();
    }
}

配置DataSource

通过DruidDataSource来配置数据源。

@Configuration
public class DataSourceConfig {
    @Bean
    @Primary
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        return dataSource;
    }
}

配置Mapper扫描

通过MapperScannerConfigurer来扫描并注册Mapper接口。

@Configuration
public class MapperConfig {
    @Autowired
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactoryBean sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        return factoryBean;
    }

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("com.example.mapper");
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        return mapperScannerConfigurer;
    }
}

通过以上配置,我们已经实现了Mybatis与Spring的基本整合,可以通过Spring的依赖注入来使用Mybatis的Mapper接口。

使用Spring管理Mybatis的SqlSessionFactory

通过Spring的依赖注入来管理SqlSessionFactory,可以更加方便地使用Mybatis的Mapper接口。

使用SqlSessionTemplate

通过SqlSessionTemplate来操作数据库。

@Service
public class UserService {
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;

    public List<User> getAllUsers() {
        return sqlSessionTemplate.selectList("com.example.mapper.UserMapper.getAllUsers");
    }
}

使用Mapper接口

通过Spring的依赖注入来使用Mapper接口。

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public List<User> getAllUsers() {
        return userMapper.getAllUsers();
    }
}

通过以上示例,我们可以看到Mybatis与Spring的整合方式,可以通过Spring的依赖注入来使用Mybatis的Mapper接口。

事务管理

Spring提供了强大的事务管理功能,可以方便地管理数据库事务。通过配置DataSourceTransactionManager来管理数据库事务。

配置事务管理器

通过DataSourceTransactionManager来配置事务管理器。

@Configuration
public class TransactionConfig {
    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;

    @Bean
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource);
    }
}

使用@Transactional注解

通过@Transactional注解来声明事务。

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrderMapper orderMapper;

    @Transactional
    public void addUserWithOrders(User user, List<Order> orders) {
        userMapper.insertUser(user);
        for (Order order : orders) {
            orderMapper.insertOrder(order);
        }
    }
}

通过以上示例,我们可以看到Mybatis与Spring的事务管理方式,可以通过Spring的事务管理器来管理数据库事务。

实战案例与常见问题
实战案例分享

假设我们有一个简单的用户管理系统,包括用户注册、登录、查询用户信息等功能。我们可以使用Mybatis来实现数据库操作。

用户注册

在用户注册时,需要插入用户信息到数据库中。

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public void registerUser(User user) {
        userMapper.insertUser(user);
    }
}

用户登录

在用户登录时,需要查询用户信息,并验证密码。

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public User login(String username, String password) {
        User user = userMapper.getUserByUsername(username);
        if (user != null && user.getPassword().equals(password)) {
            return user;
        }
        return null;
    }
}

查询用户信息

在查询用户信息时,需要从数据库中查询用户信息。

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public User getUserById(int id) {
        return userMapper.getUserById(id);
    }
}

通过以上示例,我们可以看到Mybatis在实际项目中的应用,可以方便地实现数据库操作。

常见问题解决

在使用Mybatis时,经常会遇到一些常见的问题,这里列举一些常见的问题及其解决方案。

Mybatis插入数据报错

问题描述:在插入数据时,可能会遇到数据库约束冲突导致的异常。

解决方案:检查插入的数据是否满足数据库的约束条件,例如是否符合主键唯一性要求。

Mybatis查询数据报空指针异常

问题描述:在查询数据时,可能会遇到查询结果为空导致的空指针异常。

解决方案:检查查询的SQL语句是否正确,以及查询的条件是否满足要求。

Mybatis缓存失效

问题描述:在使用缓存时,可能会遇到缓存失效导致的查询结果不准确。

解决方案:检查缓存配置是否正确,以及缓存的使用场景是否合理。

性能优化与注意事项

在使用Mybatis时,需要注意一些性能优化和注意事项,以提高系统的性能和稳定性。

避免N+1查询问题

N+1查询问题是指多次执行相同的SQL查询,可以通过使用<resultMap><association><collection>来优化查询。

使用Mybatis的缓存机制

通过合理使用Mybatis的缓存机制,可以减少数据库的查询次数,提高查询性能。

使用动态SQL减少查询次数

通过使用动态SQL,可以根据不同的查询条件生成不同的查询语句,减少不必要的查询次数。

使用分页插件优化查询

对于大数据量的查询,可以通过使用分页插件来分页查询,提高查询性能。

通过以上示例,我们可以看到Mybatis在实际项目中的应用,可以方便地实现数据库操作,并需要注意一些性能优化和注意事项,以提高系统的性能和稳定性。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消