阶段六-Day03-MyBatis

news2024/9/20 20:39:04

一、框架介绍

1. 框架的作用

将许多项目封装起来,形成了框架

2. 框架的优缺点

1. 优点
1.1 更好用

框架都是对Java原生内容进行的封装,对于企业级项目开发来说,使用框架比使用原生Java更好用,写起来更简单。

1.2 更强大

框架封装过程中会内置一些常见必要逻辑或功能,所以在使用框架时很多能够不需要再次编码,框架本身就带有这些功能了。

1.3 开发周期更短

由于框架使用起来更加简单,必定会在一定程度上缩短程序的开发周期。很多IT公司最大的成本都是人员成本,缩短了项目的开发周期,对于企业来说利润更高。这也是企业为什么都喜欢使用框架的最主要原因之一。

2. 缺点
2.1 更多的学习成本

不同的框架由不同的公司或组织开发与维护,不同公司或组织有着不同的习惯和规则,想要使用框架就需要学习框架如何使用,学习这些框架里面的要求。

2.2 初学者更容易出错

因为框架里面都封装了很多内容,想要使用框架就必须按照框架的规则进行使用。对于初学者如果不去记忆里面的规则,自己随意发挥,很容易出错。

所以想要错误更少,学习框架时必须严格按照老师讲的去做,严格按照框架规则去使用。

2.3 对于初学者,出了错误更难解决

因为框架都是深度封装,对于开发者来说可能只写了一行代码,但这一行代码里面可能是几百或几千行代码的封装。一旦报错了,如果不知道框架原理是不太好解决的。

所以想要更好的解决出现的问题,就必须要跟着老师学习框架的原理,同时要对每次出现的错误进行整理记忆,下次在出现这个错误的时候就可以快速解决了。

4. Java中的常见框架

Java项目无论是否使用框架,多采用MVC开发模型,一个项目被分为多层。一个Java框架可能只负责里面的一层。

一个Java项目并不是使用一个框架就可能完成的,通常需要很多框架配合使用,才能实现一个完整的项目。

常见Java框架分类(不仅仅就这些,列举一些常见的):

(1)持久层框架:MyBatis、Hibernate、Spring Data、iBatis。

(2)MVC框架:Spring MVC、Struts1、Struts2。

(3)项目管理框架:Spring Framework、Spring Boot。

(4)微服务框架:Spring Cloud。

(5)权限管理框架:Spring Security、Shiro。

并不是每个项目都需要把上面所有分类都使用上,不同的项目可能只会使用里面几个分类,但是只要使用了其中某个分类,只会选择其中一个。

常见的组合:

(1)SSM:Spring Framework + Spring MVC + MyBatis。最常见组合,属于Java程序员必须掌握的内容。

(2)SSMP:Spring Framework + Spring MVC + MyBatis+MyBatis Plus。对SSM的增强,减少SQL的编写。

(3)SSI:Spring Framework + Spring MVC/Struts1/Struts2 + iBatis。SSM的上代组合,目前很少出现。

(4)SSH:Spring Framework + Struts1/Struts2 + Hibernate。和SSI属于同时代产品,只有在老项目维护时可能出现的技术栈。

(5)Spring Boot + Spring Cloud。微服务架构项目常用组合。

(6)Spring Boot+Mybatis+MybatisPlus。新项目最先选择,比SSM组合使用起来更加方便。

(6)Spring Boot + Shiro/Spring Security。具有权限控制时的组合。

(7)SSM + Shiro/Spring Security。具有权限控制时的组合。

二、软件分层开发

1. Java EE 三层模型 和 MVC模型

Java EE 三层模型和MVC模型属于两种分层模型,一些同学可能认为这是同一个概念,其实并不然。

Java EE中最经典的是三层模型。包含表示层(Presentation)、业务逻辑层(Business Logic)、持久层(Persistence)

MVC 模型也是三层模型。包含模型层(Model)、视图层(View)、控制层(Controller)。

Java EE 三层模型和MVC模型最主要的区别是:

(1)Java EE三层模型中没有控制层,MVC中有控制层。

(2)Java EE三层模型中业务模型层是单独一部分,就是service层,MVC中模型层包含:业务模型(业务逻辑层)和数据模型(实体类,持久层)。

(3)Java EE三层模型中持久层就是dao层。MVC中虽然持久层在项目中是单独的包,但是在MVC概念中持久层属于模型层中。

2. 目前Java中最常见的六层模型

目前在软件开发过程中最常见的是六层模型,我们讲解的也是六层模型:

(1)视图层。简单点说就是页面,可以是客户端页面技术,也可以是服务端页面技术。例如:HTML、JSP。

(2)控制层。处于业务层和视图层之间,根据业务层结果,控制视图层显示。例如:Servlet。

(3)实体层。就是实体类,负责封装数据,在各个层之间进行数据传递的载体。常见包名:pojo、domain、entity等。

(4)业务逻辑层。专门编写业务逻辑代码。

(5)数据持久层/数据访问层。负责编写调用数据库的代码。具体技术:JDBC、MyBatis等。

(6)数据源层。一些持久化工具,负责存储数据的。例如:MySQL、Oracle等。

3. ORM

ORM(Object/Relation Mapping),中文名称:对象/关系 映射。是一种解决数据库发展和面向对象编程语言发展不匹配问题而出现的技术。

 使用JDBC技术时,手动实现ORM映射:

 ORM框架封装了对象/关系的自动映射。

6.常见的ORM框架

对于Java程序员来说,整个职业生涯可能听说过或可能用上的ORM框架:

(1)MyBatis:目前使用最多的ORM框架。

(2)Hibernate:零SQL的ORM框架,N年前使用最多的ORM框架。目前只能在一些老的项目中看到。

(3)Spring Data JPA:目前个别公司中使用的ORM框架。是Spring Data家族中的一员。是对JPA(Java Persistence API,JDK5.0)的封装。

(4)Spring Data JDBC:Spring Data中的二级项目,类似Spring Data JPA,但框架的功能要比Spring Data JPA少一些。

三、MyBatis介绍

1. 介绍

MyBatis 是一款优秀的ORM框架,MVC分层开发中的持久层框架,它支持自定义 SQL、存储过程以及高级映射。

四、第一个MyBatis项目

2. 创建Maven项目并添加依赖

创建一个Maven项目(示例中叫做:maven1),并配置pom.xml。

需要添加MyBatis的依赖和MySQL驱动的依赖。(文档制作时MyBatis最新版本为3.5.9,mysql驱动最新版本为8.0.29)因为MyBatis的底层也是MySQL,JDBC实现的

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.sh</groupId>
  <artifactId>MyBatis01</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <!-- MyBatis 框架依赖 -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.9</version>
    </dependency>
    <!-- 数据库驱动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.28</version>
    </dependency>
  </dependencies>

</project>

3. 创建MyBatis全局配置文件

在项目的src/main/resources目录下新建mybatis.cfg.xml文件。并在配置文件中填写下面内容。

配置文件解释:

  1. XML文档头是XML文件必须有的。

  2. DOCTYPE声明文档类型,引入外部约束。

  3. <configuration>是根节点。

  4. <environments>的default属性取值必须是下面某个<environment>标签的id属性值。表示当前MyBatis框架到底使用哪个环境。

  5. <environment>的id值是自定义的。表示当前数据库环境的名称。在全局配置文件中<environment>标签可以有多个,里面分别配置上数据源相关参数。例如一个里面配置连接本地MySQL的参数,另一个配置连接服务器中MySQL的参数,还有一个配置连接Oracle数据库的相关参数。都准备好了以后可以通过修改<environments>中default的值来切换连接的数据库,这样要比修改里面具体的连接参数更加方便。

  6. <transactionManager>中type属性用于配置事务的类型。可取值:

    • JDBC:使用原生JDBC的事务管理进行提交和回滚。

    • MANAGED:MyBatis不参与事务管理。交给其他人管理事务。

  7. <dataSource>中type属性值用于配置数据源类型。可取值:

    • UNPOOLED:不使用数据库连接池。每次执行SQL都会打开数据库连接,执行SQL结束都会关闭连接。适用于简单小型应用。

    • POOLED:使用MyBatis内置数据库连接池。对于频繁访问数据库的应用程序来说,这个取值是很适合的。

    • JNDI:使用本地目录接口技术连接容器外部的数据源。这种方式很少使用,一般都是极其复杂的项目,对数据源要求极高的情况下才能使用。

  8. <properties>配置具体属性和值

    driver、url、username、password四个属性名称是固定的,但是没有顺序要求,添加到<properties>的name属性中即可。分别代表驱动类、连接字符串、用户名、密码。value属性的值为连接数据库的具体参数值。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <!-- 配置执行的数据库环境 default中是默认使用哪个数据库技术-->
    <!-- default中的名字也可以叫别的-->
    <environments default="mysql">
        <environment id="mysql">
            <!--
            事务控制器有两种
            1. JDBC : 使用原生的JDBC的事务管理
            2. MANAGED : MyBatis不参与事务管理,交给其他人管理
            -->
            <transactionManager type="JDBC"></transactionManager>
            <!--
            配置数据源有三种
            UPOOLED: 不使用数据库连接池
            POOLED : 使用数据库连接池
            JNDI : 使用本地目录接口技术,特殊情况使用
            -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

4. 创建Mapper映射文件

在src/main/resources目录中新建mybatis目录。这个文件夹可以新建也可以不建立,名称也是随意的。以后mapper文件会比较多,建立一个文件夹项目结构比较好看,名称叫做mybatis也好记。

在mybatis文件夹下新建xml文件,文件名称随意。示例中就叫做mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--  配置SQL映射的文件 -->
<mapper namespace="a.b">
    <insert id="addUser">
        insert into people values(default ,'zs','123')
    </insert>
</mapper>

5. 配置加载mapper映射文件

映射文件是不能默认被加载的。需要在全局配置文件mybatis.cfg.xml中手动指定加载路径。

6. 编写测试类,启动项目

package com.sh;

import static org.junit.Assert.assertTrue;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

/**
 * Unit test for simple App.
 */
public class AppTest {
    /**
     * Rigorous Test :-)
     */
    @Test
    public void test1() throws IOException {
        // 1. 获取全局配置文件输入流
        InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");
        // 2. 加载全局配置文件后创建工厂类
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        // 3. 使用工厂创建SqlSession. 里面封装了所有增删改查的方法
        SqlSession session = factory.openSession();
        // 4. 执行sql方法,里面传递 namespace.id 通过语句的唯一标识找到sql语句
        int index = session.insert("a.b.addUser");
        System.out.println(index);
        // 5. mybatis是手动提交
        session.commit();
        // 6. 关闭连接,释放资源
        session.close();
    }
}

五、MyBatis属性加载

MyBatis支持加载属性文件(.properties文件),可以通过在属性文件中配置数据库连接属性然后加载。这种方式要比直接写稍微麻烦一点点,但是却把所有的数据库连接书写到了统一的文件中,以后查看或修改时更加方便。

1. 创建属性文件

在src/main/resources目录中创建jdbc.properties文件

注意:需要将$amp;转义字符变为&,否则运行报错

jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.username=root
jdbc.password=root

2. 修改全局配置文件

修改mybatis.cfg.xml文件,设置加载属性。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <!-- 加载属性文件 ,再给属性赋值 -->
    <properties resource="jdbc.properties"></properties>
    <!-- 配置执行的数据库环境 default中是默认使用哪个数据库技术-->
    <!-- default中的名字也可以叫别的-->
    <environments default="mysql">
        <environment id="mysql">
            <!--
            事务控制器有两种
            1. JDBC : 使用原生的JDBC的事务管理
            2. MANAGED : MyBatis不参与事务管理,交给其他人管理
            -->
            <transactionManager type="JDBC"></transactionManager>
            <!--
            配置数据源有三种
            UPOOLED: 不使用数据库连接池
            POOLED : 使用数据库连接池
            JNDI : 使用本地目录接口技术,特殊情况使用
            -->
            <!--<dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=GMT%2B8&amp;allowPublicKeyRetrieval=true"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mybatis/mapper.xml"></mapper>
    </mappers>
</configuration>

五、常见Java日志工具包

1. 日志介绍

日志是项目开发非常重要的一项。项目部署到服务器以后,并不能所有信息都通过控制台或命令窗口进行查看。把日志信息输入到文件中更有利于项目的维护。

Java项目的日志是可以输入到控制台、可以输入到文件中、甚至可以输入到某个数据源中。但是常用的还是控制台和文件。

在Java项目中常见的日志工具包:

  • Log4j:Apache推出的日志工具。于2012年5月发布1.2.17版本后停止更新。

  • Logback:属于Log4j的继承者。Spring Boot默认日志文件支持类型。

  • Log4j2:属于Log4j升级版,同时里面还包含了Logback的很多改进。

  • commons-logging:Apache早期基于门面(Facade)设计模式的日志包,提供了日志解构能力,按照顺序寻找当前项目日志接口实现,Log4j、JDK Log、SimpleLog。

  • Slf4j( Simple Logging Facade for Java ):目前使用非常多的门面日志。统一项目中日志。

  • JDK Logging:JDK自带的日志API。

2. JDK Logging

JDK Logging 是JDK自带的日志工具。存在于java.uti.logging包中。

日志的级别: OFF > SEVERE > WARNING > INFO > CONFIG > FINE > FINER > FINEST > ALL

注意:

1. 默认级别为INFO。

2. 只会显示该级别及该级别以上日志信息。

package com.sh;

import java.io.IOException;
import java.util.logging.*;

public class Demo {
    public static void main(String[] args) throws IOException {
        //参数通常设置为所在的类名
        Logger logger = Logger.getLogger("Demo");
        // 默认为INFO级别,同时设置当前和父处理器级别才能修改
        // OFF > SEVERE > WARNING > INFO > CONFIG > FINE > FINER > FINEST > ALL
        logger.setLevel(Level.FINEST);
        Handler[] handlers = logger.getParent().getHandlers();// 获取输出控制台的处理器
        handlers[0].setLevel(Level.FINEST);// 设置控制台输出级别

        // 默认没有输出到文件,只输出到控制台,通过添加Handler增加输出目的地,输出到文件中
        FileHandler fh = new FileHandler("my.log");// 如果路径夹会不存在文件夹会报错
        fh.setFormatter(new SimpleFormatter());// 设置输出内容为普通格式
        logger.addHandler(fh);

        logger.severe("severe");// 严重
        logger.warning("warning");// 警告
        logger.info("info");// 信息
        logger.config("config");// 配置
        logger.fine("fine");// 详细
        logger.finer("finer");// 较详细
        logger.finest("finest");// 非常详细
    }
}

3. Log4j的使用

Log4j是Apache的开源日志工具。最新版本为2012年发布的1.2.17。

Log4j会自动寻找classpath下log4j.properties作为配置文件。

具体使用步骤:

3.1 配置pom.xml
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
3.2 编写配置文件

在resources中新建log4j.properties,名称不要写错了。

log4j中定义的级别:fatal(致命错误) > error(错误) > warn(警告) > info(普通信息) > debug(调试信息) > trace(跟踪信息)

# log4j中定义的级别:fatal(致命错误) > error(错误) > warn(警告) > info(普通信息) > debug(调试信息) > trace(跟踪信息)
# 跟日志等级为debug 使用console和file两种方式输出
log4j.rootLogger = DEBUG , console , file

### console ###(日志显示在控制台的配置)
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n

### log file ###(日志输出在文件中的配置)
log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
# 日志输出的路径
log4j.appender.file.File = log4j.log
# 是否给日志文件追加
log4j.appender.file.Append = true
# 级别只能比根日志界别高,比根日志级别低不生效
#log4j.appender.file.Threshold = info
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n
3.3 编写测试类

注意:千万不要倒错包。

package com.sh;
// 不要导错包
import org.apache.log4j.Logger;

public class TestLog4j {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(TestLog4j.class);
        logger.trace("跟踪级别");
        logger.debug("调试信息");
        logger.info("普通信息");
        logger.warn("警告信息");
        logger.error("错误信息");
        logger.fatal("重大错误信息");
    }
}

4. Log4j2

4.1 配置pom.xml

虽然只导入了log4j-core,但是实际导入log4j-core和log4j-api。

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.2</version>
</dependency>
4.2 编写配置文件

Log4j2不再支持Log4j的.properties格式配置文件。而是支持.xml、.json、jsn。

Log4j2中定义的级别:fatal(致命错误) > error(错误) > warn(警告) > info(普通信息) > debug(调试信息) > trace(跟踪信息)

在resource目录新建log4j2.xml。

<?xml version="1.0" encoding="utf-8" ?>
<Configuration >
    <!-- 定义输出的目的地 -->
    <Appenders>
        <!-- Console 定义控制台输出 name:自定义名称 target:输出方式,支持SYSTEM_OUT SYSTEM_ERR -->
        <!-- 
        SYSTEM_OUT 正常输出内容
        SYSTEM_ERR 错误高亮输出内容
        -->
        <Console name="console" target="SYSTEM_OUT">
            <!-- 输出信息表达式 -->
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        
        <!-- File 定义文件输出 fileName 文件路径  append是否允许追加 -->
        <File name="file" fileName="log4j2.log" append="true">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </File>
    </Appenders>

    <Loggers>
        <!-- 控制总体级别 -->
        <!-- fatal > error > warn > info > debug > trace -->
        <Root level="info">
            <!-- 引用输出位置的配置,Appenders中直接子标签的name属性值 -->
            <!-- 映射哪种输出模式 -->
            <AppenderRef ref="console"/>
            <AppenderRef ref="file"/>
        </Root>
    </Loggers>
</Configuration>
4.3 编写测试类
package com.bjsxt;
// 千万别导错包了
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class TestLog4j {
    public static void main(String[] args) {
        Logger logger = LogManager.getLogger(TestLog4j.class);
        logger.trace("跟踪级别");
        logger.debug("调试信息");
        logger.info("普通信息");
        logger.warn("警告信息");
        logger.error("错误信息");
        logger.fatal("重大错误信息");
    }
}

5. SLF4j

SLF4j是日志的接口声明,不参与日志的具体实现,需要配合其它日志具体实现工具包才能进行使用。

每次添加其它日志工具包时,不要忘记SLF4j整合这个日志的依赖。

5.1 整合Log4j
5.1.1 导入依赖

导入3个依赖,分别代表slf4j依赖、整合依赖、log4j的依赖。

<!--slf4j整合log4j的依赖,版本要和slf4j的版本对应 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.36</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
5.1.2 编写log4j的配置文件

使用写号的log4j.properties文件就行

5.1.3 编写测试类

小提示:

SLF4J作为门面设计模式的具体实现,无论使用哪种日志具体实现,都是下面的API。

public class TestSlf4j {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(TestSlf4j.class);

        logger.trace("trace");
        logger.debug("debug");
        logger.info("info");
        logger.warn("warn");
        logger.error("error");
    }
}
5.2 整合Log4j2
5.2.1 配置pom.xml

与SLF4J整合Log4j的整合包是不一样的。

<dependencies>
    <!-- SLF4j整合Log4j2的依赖 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.17.2</version>
    </dependency>
    <!-- Log4j2工具的依赖-->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.17.2</version>
    </dependency>
</dependencies>
5.2.2 添加Log4j2的配置文件

使用之前的log4j2.xml文件。

5.2.3 运行测试类

测试类的API和整合Log4j的API是完全相同的,直接运行即可。

5.3 即整合Log4j又整合Log4j2

SLF4J支持多种日志实现,但是在项目中整合依赖最好只有一个,否则会出现警告。

六、MyBatis启用日志功能

1. MyBatis支持的日志

MyBatis框架内置日志工厂。日志工厂负责自动加载项目中配置的日志。MyBatis支持以下日志,当存在多个日志工具时,严格按照从上往下顺序使用,且只会使用一个。

  • SLF4J

  • Apache Commons Logging

  • Log4j 2

  • Log4j (deprecated since 3.5.9)

  • JDK logging

2. MyBatis结合Log4j实现打印执行的SQL

3. MyBatis结合Log4j2实现打印执行SQL

同理演示Log4j2

3.1 编写pom.xml,引入依赖
<dependencies>
    <!-- MyBatis 框架依赖 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.9</version>
    </dependency>
    <!-- 数据库驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.28</version>
    </dependency>
    <!-- log4j2 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.17.2</version>
    </dependency>
</dependencies>
3.2 创建配置文件

在resources目录下新建log4j2.xml文件

<?xml version="1.0" encoding="utf-8" ?>
<Configuration >
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
        <!-- namespace的值 -->
        <logger name="a.b" level="debug"></logger>
    </Loggers>
</Configuration>

4. 指定生效的日志

在MyBatis中默认按照顺序寻找,如果项目中存在多个日志。可以通过mybatis全局配置文件进行设置哪个日志生效。

在mybatis.cfg.xml中配置<settings>的标签

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <properties resource="jdbc.properties"></properties>
    <!-- 配置哪个日志生效 , 多个日志的时候设置 -->
    <!--<settings>
        <setting name="log4j2" value="LOG4J2"/>
    </settings>-->
    <!-- 配置执行的数据库环境 default中是默认使用哪个数据库技术-->
    <!-- default中的名字也可以叫别的-->
    <environments default="mysql">
        <environment id="mysql">
            <!--
            事务控制器有两种
            1. JDBC : 使用原生的JDBC的事务管理
            2. MANAGED : MyBatis不参与事务管理,交给其他人管理
            -->
            <transactionManager type="JDBC"></transactionManager>
            <!--
            配置数据源有三种
            UPOOLED: 不使用数据库连接池
            POOLED : 使用数据库连接池
            JNDI : 使用本地目录接口技术,特殊情况使用
            -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url"
                          value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper.xml"></mapper>
    </mappers>
</configuration>

5. 测试

package com.sh;

import static org.junit.Assert.assertTrue;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

/**
 * Unit test for simple App.
 */
public class AppTest {
    /**
     * Rigorous Test :-)
     */
    @Test
    public void test1() throws IOException {
        //1.通过流读取全局配置文件
        InputStream is = Resources.getResourceAsStream("mybatis_config.xml");
        //2.创建工厂SqlSessionFactory构建器然后创建工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //3.通过工厂创建SqlSession
        SqlSession session = factory.openSession();
        //4.session中封装了所有的增删改查的方法
        int i = session.insert("a.b.add1");
        //验证结果
        System.out.println(i);
        //5. 增删改手动提交事务
        session.commit();
        //6. 释放资源
        session.close();
    }
}

七、SQL参数

1. MyBatis中的占位符

MyBatis中最常用的占位符为 #{},在MyBatis的mapper文件的SQL中使用#{}作为占位符。最终解析时会解析成JDBC的占位符?。

2. 当参数为简单数据类型

当参数为一个简答数据类型时。例如:八大基本数据类型、String类型等。可以通过#{任意内容}获取到。

小提示:

1. 任意内容代表着,随意写,只要不是特殊字符即可。

2. 但是要注意不能不写。

2.1 修改Test类

SqlSession的insert()方法有两种。

想要传递参数就需要使用insert(String,Object)的方法。

 @Test
    public void test2(){
        SqlSessionFactory factory = getFactory();
        //3.通过工厂创建SqlSession
        SqlSession session = factory.openSession();
        int i = session.insert("a.b.add2","456");
        System.out.println(i);
        session.commit();
        session.close();
    }
 <insert id="add2">
        insert into user values (default ,'ls',#{pwd})
    </insert>

通过使用,使用#{} 给占位赋值  先将#{}变成? 再进行解析 只有一个值需要赋值时

#{}括号中写什么都行

3. 当参数为多个值时 

3.1 修改Test类

由于insert(String,Object)方法只有一个Object类型方法能作为SQL参数,如果希望传递多个值,有两种选择:

1.可以创建一个对应类,通过对象进行传递。

参数是对象通过${属性名}获取

 @Test
    public void test3(){
        SqlSessionFactory factory = getFactory();
        //3.通过工厂创建SqlSession
        SqlSession session = factory.openSession();
        User user = new User();
        user.setUsername("zw");
        user.setPassword("789");
        int i = session.insert("a.b.add3",user);
        System.out.println(i);
        session.commit();
        session.close();
    }

2.也可以把所有SQL参数放入到一个Map中。

参数是Map,通过${key}获取

@Test
    public void test3(){
        SqlSessionFactory factory = getFactory();
        //3.通过工厂创建SqlSession
        SqlSession session = factory.openSession();
       /* User user = new User();
        user.setUsername("zw");
        user.setPassword("789");*/
        HashMap<String, String> map = new HashMap<>();
        map.put("username","zw");
        map.put("password","147");
        int i = session.insert("a.b.add3",map);
        System.out.println(i);
        session.commit();
        session.close();
    }
3.2 mapper文件
 <insert id="add3">
        insert into user values (default ,#{username},#{password})
    </insert>

4. ${} 的使用

在MyBatis中还有一种占位符写法:${}。

${}在被MyBatis进行解析时,不会解析为占位符?,而是直接解析成对应的,类似字符串拼接

学习JDBC时我们知道SQL中存在字符串拼接时,会有SQL注入问题。

那是不是意味着${}没有使用场景了?答案是否定的。JDBC中占位符?是不允许代替列名和表名的,也就意味着MyBatis的#{}不允许代替表名和列名但是使用${}可以动态设置列名或表名。

${}和#{}获取参数的写法完全相同。如果参数是对象通过${属性名}获取。如果参数是Map,通过${key}获取。如果参数是简单数据类型,通过${任意不为空的内容}进行获取。

4.1 修改映射文件

${}和#{}可以混合使用。实例中使用${}代替表名。

<insert id="add4">
        insert into ${table} values (default ,#{username},#{password})
    </insert>
4.2 修改Test类
 @Test
    public void test4(){
        SqlSessionFactory factory = getFactory();
        SqlSession session = factory.openSession();
        HashMap<String, String> map = new HashMap<>();
        map.put("table","user");
        map.put("username","zw");
        map.put("password","258");
        int i = session.insert("a.b.add4", map);
        System.out.println(i);
        session.commit();
        session.close();
    }

通过日志可以看到

${}直接解析为值  ,  而#{}则被解析为?

八、MyBatis中修改和删除实现

1. 修改和删除功能总体说明

MyBatis实现修改和删除功能与实现新增时是非常类型的,SQL参数传递的几种方式也是相同的。

主要区别:

就是mapper文件中标签名不同。

SqlSession的方法名不同。

操作mapper标签SqlSession方法名
新增<insert>insert(String)、insert(String,Object)
修改<update>update(String)、update(String,Object)
删除<delete>delete(String)、delete(String,Object)

2. 修改实现

2.1 修改映射文件

修改suiyi.xml文件.在里面添加上<update>标签。设定使用Map进行传递参数了,所以直接使用#{key}获取到参数。

 <update id="update1">
        update user set username=#{username} where id=#{id}
    </update>
2.2 修改测试类
 @Test
    public void test5(){
        SqlSessionFactory factory = getFactory();
        SqlSession session = factory.openSession();
        HashMap<String, String> map = new HashMap<>();
        map.put("username","hhh");
        map.put("id","1");
        int i = session.update("a.b.update1", map);
        System.out.println(i);
        session.commit();
        session.close();
    }

3. 删除实现

3.1 修改映射文件

修改suiyi.xml文件.在里面添加上<delete>标签。设定使用Map进行传递参数了,所以直接使用#{key}获取到参数。

 <delete id="delete1">
        delete from user where id=#{id}
    </delete>
3.2 修改测试类
/* 删除实现 */
    @Test
    public void test6(){
        SqlSessionFactory factory = getFactory();
        SqlSession session = factory.openSession();
        int i = session.delete("a.b.delete1", 10);
        System.out.println(i);
        session.commit();
        session.close();
    }

九、MyBatis中DQL操作

MyBatis的DQL操作在映射文件都是通过<select>标签实现的。

SqlSession根据根据查询结果类型不同,提供了五种查询方法:

方法名解释说明
selectOne()查询一行数据时,返回值为Object。如果没有查询到,但是不能查询到多行。
selectMap()查询多行数据时,把其中某列结果当做key,每行结果为Value
selectList()当查询多行数据时,返回值为List。如果没有查询到返回长度为零的List对象。
selectCursor()使用游标查询时使用,在大量数据时可以代替分页
select()万能方法,需要自己定义结果处理器

2. selectOne()方法使用

selectOne()方法要求查询结果是一行或没有查询到。如果查询结果是多行会报异常。

如果这行数据有多个值,可以放在实体类对象中。如果这行数据只有一列,可以使用简单数据类型接收

2.1 查询到一行或没有查询到结果时
2.1.1 修改映射文件

在映射中添加<select>标签,resultType属性是<select>标签必须有的属性,表示查询结果最终类型。取值为类型的全限定路径。就是查询结果对应的类是哪个要指定,而且要使用包名+类名

<!--
    DQL:selectOne
    必须保证列名和resultType中类型的属性名相同才能保证把查询到的结果自动放入对象当中
-->
    <select id="one" resultType="com.sh.util.User">
        select * from user where id = #{id}
    </select>
2.1.2 修改Test类

selectOne()方法返回值是泛型类型,所以可以直接写对应的类型。

@Test
    public void test7(){
        SqlSessionFactory factory = getFactory();
        SqlSession session = factory.openSession();
        Map<String,Object> map = new HashMap<>();
        map.put("id",1);
        // 使用selectOne方法进行查询
        // 返回值可以直接写映射文件中select的resultType对应类型
        //知道是user类型直接转换成user类型
        User user = session.selectOne("a.b.select1", map);
        System.out.println(user);
        //查询不需要事务的提交
        /*session.commit();*/
        //释放资源
        session.close();
    }
2.1.3 当没有写resultType属性时

resultType是<select>必须写的属性。如果不写resultType属性执行时会报错。在示例中删除掉了resultType属性。

2.1.4 查询到多行数据时

如果使用selectOne()方法,对应的SQL查询到多行数据会报错。

例如:修改映射文件的SQL为查询全部,且保证数据库people表有2行以上数据

3. selectList()方法使用

selectList()方法主要用在多行查询时,查询时把每行结果按照resultType类型进行封装,最终放入到List中。

3.1 修改映射文件

注意:resultType的类型为每行结果的类型,也就是List的泛型的类型。

<select id="select2" resultType="com.sh.util.User">
        select * from user
    </select>
3.2 修改Test类

        //查询多个
        @Test
        public void test8(){
            SqlSessionFactory factory = getFactory();
            SqlSession session = factory.openSession();
            // 使用selectList方法进行查询
            // 返回值可以直接写映射文件中select的resultType对应类型
            List<User> list = session.selectList("a.b.select2");
            System.out.println(list);
            //查询不需要事务的提交
            /*session.commit();*/
            //释放资源
            session.close();
        }

4. selectMap()方法使用

selectMap(String statement,Object param,String key);比上面多了String key参数。

String key:指定查询结果中哪列的值作为map的key。map的value是整行数据,类型和resultType类型一致。

4.1 修改映射文件
<select id="select3" resultType="com.sh.util.User">
        select * from user
    </select>
4.2 修改测试类

修改后运行效果,查看key和value的值

 // 使用 selectMap()
        @Test
        public void test9(){
            SqlSessionFactory factory = getFactory();
            SqlSession session = factory.openSession();
            // 使用selectList方法进行查询
            // 返回值可以直接写映射文件中select的resultType对应类型
            Map<String, Object> map = session.selectMap("a.b.select3", "id");
            System.out.println(map);
            //查询不需要事务的提交
            /*session.commit();*/
            //释放资源
            session.close();
        }

5. selectCursor()方法使用

cursor 表示游标。属于对查询结果集的一种遍历方式。MyBatis底层使用JDBC,在MyBatis封装的Cursor中只有遍历功能。其实就是一个一个的查询出来

5.1 修改映射文件
 <select id="select4" resultType="com.sh.util.User">
        select * from user
    </select>
5.2 修改Test类

selectCursor()返回值为Cursor,提供了forEach()遍历和iterator()两种遍历方式,下面使用forEach()遍历方式。

@Test
    public void test10(){
        SqlSessionFactory factory = getFactory();
        SqlSession session = factory.openSession();
        // 使用selectList方法进行查询
        // 返回值可以直接写映射文件中select的resultType对应类型
        //泛型知道是user
        Cursor<User> cursor = session.selectCursor("a.b.select4");
        cursor.forEach(System.out::println);
        //查询不需要事务的提交
        /*session.commit();*/
        //释放资源
        session.close();
    }

6. select()方法使用

select(String statement,Object param,ResultHandler resultHandler);方法中第三个参数表示结果处理。

在ResultHandler接口中只有一个方法,表示如何处理

//使用select
    //自定义查询
    @Test
    public void test11(){
        SqlSessionFactory factory = getFactory();
        SqlSession session = factory.openSession();
        // 使用selectList方法进行查询
        // 返回值可以直接写映射文件中select的resultType对应类型
        //该方法是自定义查询,需要重写handleResult方法,可以创建一个类继承ResultHandle来实现
        //也可以使用匿名内部类,这里使用内部类
        MyResultHandler myResultHandler = new MyResultHandler();
        session.select("a.b.select5",myResultHandler);
        //查询不需要事务的提交
        /*session.commit();*/
        System.out.println("-------------------");
        System.out.println(myResultHandler.getResult());
        //释放资源
        session.close();
    }

    public class MyResultHandler implements ResultHandler {
        HashSet<Object> set = new HashSet<>();

        @Override
        public void handleResult(ResultContext resultContext) {
            // System.out.println(resultContext.getResultObject());
            set.add(resultContext.getResultObject());
        }

        public Set<Object> getResult(){
            return set;
        }
    }

十、分页查询

1. MyBatis实现分页查询的几种方式

在MyBatis中实现查询有两种方式:

  1. 根据对应的数据库,编写SQL。这种方式与数据库耦合度较高,移植性差。但是确实我们平时使用的方式,因为大部分项目是没有修改数据库类型的场景。

  2. 使用MyBatis提供的RowBounds实现分页

2. 根据对应数据库编写SQL

2.1 修改映射文件
<select id="select6" resultType="com.sh.util.User">
        select * from user limit #{index},#{size}
    </select>
2.2 修改测试类
@Test
    public void test12(){
        SqlSessionFactory factory = getFactory();
        SqlSession session = factory.openSession();
        HashMap<String, Object> map = new HashMap<>();
        map.put("index",0);
        map.put("size",3);
        session.selectList("a.b.select6",map);
        System.out.println(map);
        //释放资源
        session.close();
    }

这是类似JDBC的方法

3. RowBounds方式进行分页

RowBounds是MyBatis中提供的一种"假分页"实现方式。对从数据库中查询到的结果进行截取。所以如果数据库中数据量特别大的时候可能会出现OOM等问题。就是当查询第二页时会把第一页的数据也查询出来,但是最终只截取第二页的内容

但是由于RowBounds不需要考虑底层数据库是什么,且使用简单,所以对于一些数据量不是特别大的应用还是有人选择使用的。

在SqlSession中select、selectMap、selectList中通过方法重载都提供了一个带有RowBounds。

3.1 修改映射文件
<!-- 使用RowBounds -->
    <select id="select7" resultType="com.sh.util.User">
        select * from user
    </select>
3.2 修改Test类
/* 使用RowBounds */
    @Test
    public void test13(){
        SqlSessionFactory factory = getFactory();
        SqlSession session = factory.openSession();
        //创建偏移量对象
        RowBounds rowBounds = new RowBounds(0, 3);
        //因为偏移量必须是第三个参数,再不需要给占位符赋值的时候,第二个参数也必须要写,写为null
        List<User> list = session.selectList("a.b.select7", null, rowBounds);
        System.out.println(list);
        //释放资源
        session.close();
    }

十一、模糊查询

1. 使用#{}实现模糊查询

1.1 修改映射文件
<select id="select8" resultType="com.sh.util.User">
        select * from user where username like #{username}
    </select>
1.2 修改测试类
// 模糊查询
    @Test
    public void test14(){
        SqlSessionFactory factory = getFactory();
        SqlSession session = factory.openSession();
        List<User> list = session.selectList("a.b.select8","%s%");
        System.out.println(list);
        //释放资源
        session.close();
    }

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

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

相关文章

LaunchView/启动页 的实现

1. 创建启动画板&#xff0c;LaunchScreen.storyboard 添加组件如图: 2. 项目中设置只支持竖屏&#xff0c;添加启动画板&#xff0c;如图: 3. 创建启动画面动画视图&#xff0c;LaunchView.swift import SwiftUI/// 启动视图 struct LaunchView: View {/// 字符串转换为字符串…

第二章——古典密码学及算法实现

凯撒加密 凯撒加密算法实现&#xff1a; # 凯撒密码加密函数 def caesar_encrypt():string [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,v, w, x, y, z]# 密文列表cipher_text_list []cipher int(input("请输入你的密钥:"))plain_text in…

基于ChatGPT+词向量/词嵌入实现相似商品推荐系统

最近一个项目有个业务场景是相似商品推荐&#xff0c;给一个商品描述(比如 WIENER A/B 7IN 5/LB FZN )&#xff0c;系统给出商品库中最相似的TOP 5种商品&#xff0c;这种单纯的推荐系统用词向量就可以实现&#xff0c;不过&#xff0c;这个项目特点是商品库巨大&#xff0c;有…

SQL中for xml path 的用法

1. 用法 是一种将查询结果转换为 XML 格式的方法。它可以将查询结果中的每一行转换为一个 XML 元素&#xff0c;并且可以指定元素的名称和属性。 2. 应用示例 有一张学生选修课程的表&#xff0c;如下图所示 希望整合成下图所示效果 --建表 if object_id(StudentInfo,u) is…

webrtc用clang编译支持h264,支持msvc调用库

webrtc遇到困扰&#xff1a; 如果msvc编译&#xff0c;ffmpeg编译失败&#xff0c;需要替换ffmpeg库。如果用clang编译&#xff0c;vs或qt调用dll又存在崩溃。 经过反复尝试找到解决方法&#xff1a; 一、编译 1、编译参数 //我得环境配置 set DEPOT_TOOLS_UPDATE0 set DEP…

解决linux终端启动后不能自动加载环境变量配置(个人配置文件)详解

文章目录 设备环境问题阐述解决方法 设备环境 WSL2 Ubuntu-20.04 本教程适配所有linux&#xff0c;不管你是虚拟机还是WSL或者其他的平台。 问题阐述 由于专业课的要求&#xff0c;需要在Linux中新建一个用户&#xff0c;然后转到这个用户来完成专业课的各种实践要求。有可…

HttpServletRequest对象与RequestDispatcher对象

一、HttpServletRequest对象 1.介绍 在Servlet API中&#xff0c;定义了一个HttpServletRequest接口&#xff0c;它继承自ServletRequest接口&#xff0c;专门用来封装HTTP请求消息。由于HTTP请求消息分为请求行、请求消息头和请求消息体三部分&#xff0c;因此&#xff0c;在…

Android免杀小结

目录 msfvenom 自动生成 自带免杀 工具免杀 Thefatrat backdoor-apk old-fatrat msfVenom嵌入式方法 venom 工具小记 加壳 源码免杀 加壳 源码混淆 数据通信 启动和运行方式修改 对抗反编译 反编译工具崩溃 ZIP文件格式对抗 ZIP通用位伪加密 AndroidManife…

暴涨100万粉仅用一个月,B站内容趋势前线洞察

- 导语 在这个9月&#xff0c;B站涌现多位黑马UP主&#xff0c;有的UP主自入驻B站以来&#xff0c;一个月的时间就涨粉百万晋升为头部UP主&#xff0c;有的UP主因内容受到B站百万年轻人的追捧&#xff0c;展现账号爆发力。 接下来&#xff0c;飞瓜数据&#xff08;B站版&…

智慧工地:助力数字建造、智慧建造、安全建造、绿色建造

智慧工地管理系统融合计算机技术、物联网、视频处理、大数据、云计算等&#xff0c;为工程项目管理提供先进的技术手段&#xff0c;构建施工现场智能监控系统&#xff0c;有效弥补传统监理中的缺陷&#xff0c;对人、机、料、法、环境的管理由原来的被动监督变成全方位的主动管…

将 mysql 数据迁移到 clickhouse (最新版)

一、前驱知识 已经在mysql中插入了海量的数据了&#xff0c;这个时候mysql 承载不了这么大的数据&#xff0c;并且数据只需要查询&#xff0c;修改和删除非常少&#xff0c;并且不需要支持事务&#xff0c;这个时候需要换一个底层存储&#xff0c;这里选用的是 clickhouse 来进…

智能视频分析系统AI智能分析网关V3触发告警图片不显示该如何解决?

AI智能分析网关V3包含有20多种算法&#xff0c;包括人脸、人体、车辆、车牌、行为分析、烟火、入侵、聚集、安全帽、反光衣等等&#xff0c;可应用在安全生产、通用园区、智慧食安、智慧城管、智慧煤矿等场景中。将网关硬件结合我们的视频监控系统EasyCVR一起使用&#xff0c;可…

vue3插件——vue-web-screen-shot——实现页面截图功能

最近在看前同事发我的vue3框架时&#xff0c;发现他们有个功能是要实现页面截图功能。 vue3插件——vue-web-screen-shot——实现页面截图功能 效果图如下&#xff1a;1.操作步骤1.1在项目中添加vvue-web-screen-shot组件1.2在项目入口文件导入组件——main.ts1.3在需要使用的页…

对话天润云CEO吴强,未来所有企业都要用AI重构一遍 | AIGC入局者栏目

近日&#xff0c;铅笔道联合知乎&#xff0c;与天润云&#xff08;又称“天润融通”&#xff09;创始人兼CEO吴强先生深度交流&#xff0c;大模型如何提升客户联络效率以帮助企业完成变革。 吴强认为&#xff1a;“丰富、专业的语料决定了大模型的能力&#xff0c;企业生产过程…

小程序, 多选项

小程序, 多选项 <view class"my-filter-btnwrap"><block wx:for"{{archiveList}}" wx:key"index"><view class"my-filter-btnitem text-ellipsis {{item.checked ? active : }}" data-index"{{index}}" wx…

Vuex的同步存值与取值及异步请求

前言 1.概念 Vuex是一个用于管理Vue.js应用程序中状态的状态管理模式和库。Vue.js是一个流行的JavaScript框架&#xff0c;用于构建用户界面&#xff0c;而Vuex则专门用于管理应用程序的状态&#xff0c;以确保状态在整个应用程序中保持一致和可维护。 2.Vuex的特点&#xf…

uniapp-vue3微信小程序实现全局分享

uniapp-vue3微信小程序实现全局分享 文章目录 uniapp-vue3微信小程序实现全局分享微信小程序官方文档的分享说明onShareAppMessage(Object object)onShareTimeline() uniapp 官方文档的分享说明onShareAppMessage(OBJECT) 实现全局分享代码结构如下share.js文件内容main.js注意…

XML是不是主要用做配置文件?

2023年10月11日&#xff0c;周三下午 这几天发现tomcat的配置文件主要是用XML文件来写的&#xff0c; 于是就有了这个问题。 是的,XML非常适合用来做配置文件。 XML作为配置文件的主要优点: 可读性强。XML使用标签结构组织数据,内容清晰易懂。跨语言和跨平台。XML作为纯文本…

一站式新零售管理系统提供商,数字化收银系统与连锁门店运营优化

在数字化时代&#xff0c;连锁超市行业正面临巨大的转型压力。消费者对购物体验的需求不断提升&#xff0c;线上线下购物的融合趋势明显&#xff0c;同时物流、供应链和库存管理也变得越来越复杂。面对日益激烈的竞争和消费者需求的变化&#xff0c;连锁超市亟需通过数字化手段…

Linux:I/O 5种模型

图片来源&#xff1a;https://pdai.tech/md/java/io/java-io-model.html